Thursday, 23 May 2013

Making sure Google Analytics is done before submitting a form

Want to track form submissions with Google Analytics, but losing the data because the form submits before the asynchronous GA code is done? Fear not, Google has added a callback event.

This StackOverflow post contains an answer that outlines (in a single onclick statement if that floats your boat) how to do it. In summary:

onclick="var _this=this;_gaq.push(['_set','hitCallback',function(){$(_this).parents('form').first().submit();}]);_gaq.push(['_trackEvent','My category','My action']);return !window._gat;"

Tuesday, 18 December 2012

Securing web fonts in IIS 7

Need to prevent leaching or hot-linking of your web fonts in IIS 7? I found not just one but two posts outlining how to achieve this. To sum up, put something like this in your web.config:

<system.webServer>
 <rewrite>
   <rules>
     <rule name="Prevent font hotlinking">
       <match url=".*\.(eot|svg|ttf|woff)$" />
       <conditions logicalGrouping="MatchAny">
         <add input="{HTTP_REFERER}" pattern="$^" /> <!-- No referrer -->
         <add input="{HTTP_REFERER}" pattern="^https?://(.*\.)?({local domain}|{dev domain}|{staging domain}|{live domain}).*$" negate="true" /> <!-- Not from your site -->
       </conditions>
       <action type="Rewrite" url="/font/no-hotlinking.txt" />
     </rule>
   </rules>
 </rewrite>
</system.webServer>

Of course, don't forget to change the {domains} in the above example for your own.

Monday, 12 November 2012

LINQ, Counts and Group By

After a particularly busy weekend full of late nights working remotely towards a looming deadline, I was having trouble with writing a LINQ query that would return me values based on a GROUP BY clause. What I basically wanted was:

SELECT COUNT(Id)
FROM Table
GROUP BY UserId

I had no idea what the LINQ GroupBy() method actually returned, but this article helped me figure it out.

Table
  .GroupBy(x => x.UserId)
  .Select(g => g.Count());

Or, even more handy:

Table
  .GroupBy(x => x.UserId)
  .Select(g => new { userId = g.Key, count = g.Count() });

Thursday, 8 November 2012

Application level error handling

On the project I've been working on, we've been asked to log any exceptions that are thrown by the site. There are packages out there (like ELMAH), but in case you want to add some form of custom logging (or extra handling), there's a useful chunk of sample code for doing just that. :)

Wednesday, 31 October 2012

Facebook - Finding a user's friends who use your app

This is something I've had to find before, but I'd forgotten the Facebook Graph API call to fetch it ... so here it is, written down so I can find it again later :)

This call returns all the user's friends (including their names) and adds a property of "installed" (set to true) to the object for each user that's also a user of the app:

https://graph.facebook.com/{userid}/friends?fields=installed,name

Of course, there are new ways of doing things since I last tried to do this and now, using FQL, you can fetch a list without the users who don't use the app. There's a field called is_app_user you can query against:

https://graph.facebook.com/fql?q=SELECT uid,name FROM user WHERE uid IN (SELECT uid2 FROM friend WHERE uid1={userid}) AND is_app_user=1 ORDER BY name

Easy!

Tuesday, 30 October 2012

Sessions not persisting for Facebook app in Safari

I had an issue recently with a Facebook app (using .Net in the back end) in Safari. Nothing put into the user session was persisting between page loads. The user was authenticated, put into the session, but on the next page bam - gone again.

After doing some checking, I found a few posts that pointed me in the direction of the issue. Turns out that Safari considers the app inside the iframe to be a "third-party" site and therefore doesn't accept the session cookie. More searching turned up a suggestion - open the app site outside of the iframe if you're in Safari so that the cookie can be set.

So that's exactly what I did. During the authentication stage of the app (when dealing with the oauth token and so on), I check to see if the Request.UserAgent contains "Safari" (and not "Chrome"). If so, I redirect to a new view, SafariRedirect which uses a chunk of JavaScript to force my Facebook Authorisation view to open in the top frame.

This view sets the session cookie by putting a dummy value into it, allowing the cookie to exist for the site going forward (including within the iframe).

And that managed to do the trick.

It's been too long

But I'm back - no longer will I be "too busy" to update this thing. I'm going to start sharing stuff a lot more :)