Thursday, December 9, 2010

Link Tracking using jQuery and the Google Analytics Asynchronous Tracking Code

The Google Analytics tracking code is triggered when pages that include the code are called. But what about when users request PDFs and other documents that aren't web pages or click on links to external web pages on other websites?  How do we track these events also?

Here is some jQuery you can add to your pages that will allow you to track when people click on these links.  You will have to add the Google Analytics Asynchronous Tracking code (found here: and add jQuery to your page (see here: to use this code:



  href = ($(this).attr('href') == undefined) ? ('') : ($(this).attr('href'));
  href_lower = href.toLowerCase();
  if(href_lower.substr(-3) == "pdf" || href_lower.substr(-3) == "xls" || href_lower.substr(-3) == "doc") {
   _gaq.push(['_trackEvent', 'document', 'download', href_lower.substr(-3), $(this).text()]);
   _gaq.push(['_trackPageview', href]);
  if(href_lower.substr(0, 4).toLowerCase() == "http") {
   _gaq.push(['_trackEvent', 'external_link', 'open', 'href', $(this).text()]);
   _gaq.push(['_trackPageview', href]);
  if ($(this).attr('target') != undefined && $(this).attr('target').toLowerCase() != '_blank' && href_lower.substr(0,10) != "javascript") {
   setTimeout(function() { location.href = href; }, 200);
   return false;



So, the example above will track clicks on internal links opening files with the extensions pdf, xls, and doc and will categorize them in your Google Analytics event tracking reports as "documents".  It will also track outgoing links (links with URLs beginning with "http") and categorize them as "external_links".

If you need more categories, add more if statements.  In the method above I create one click event that is attached to every link on the page, rather than just attaching specific events to the links that require them.  If a link satisfies more than one criteria (e.g. it's a link both to a PDF, and it's on an external website) then both events will be created.  In the end I thought this approach was probably more customizable and efficient overall, especially if there are several event categories.

The setTimeout bit is to allow links that replace the page content (i.e. regular links) a moment before calling the page; so that the GA function has time to execute before opening the page. Be careful when using plugins like Fancybox; add links to such plugins to the exception list in the condition wrapped around the setTimeout function as these functions remove the href attribute and the combination of that and the setTimeout can cause unpredictable behaviour.

You may want to track events for clicks made by specific links like the nav or featured content.  You can achieve this using a similar method:

$("#main_menu a").mouseup(function(){
if($(this).attr('href').toLowerCase() != "javascript:;" && $(this).attr('href') != "#") {
_gaq.push(['_trackEvent', 'main_menu', 'open', $(this).attr('href')]);

Change the ID in the yellow to whatever you call the container that your menu is kept in.  I added the check for JavaScript:; and # just in case there are links that don't open pages (e.g. links that reveal further options).

Leave comments if you have other suggestions for mixing jQuery and GA for better tracking.

Wednesday, December 8, 2010

Google Nexus S Fun

I happened to catch the second clue in the Google Nexus (@googlenexus) Nexus S contest about 20 minutes or so after they posted it. I didn't get the first puzzle; I thought I did but I was wrong. This one I was on the right track right away. The clue was:

Puzzle Challenge #2: There is more than meets the eye at You'll find the answer in a tweet.

So the FIRST thing I did when I went to the page was look at the source code. At the very bottom of the page I found this:

                               I                I                               
                                I      ++      I                                
                            IIII   IIIIIIIIII  IIIII                            
                    IIII  IIIIIIIIIIIIIIIIIIIIIIIIIIII  IIII                    
                   IIIIII IIIIIIIIIIIIIIIIIIIIIIIIIIII IIIIII                   
                   IIIIII IIIIIIIIIIIIIIIIIIIIIIIIIIII IIIIII                   
                   IIIIII 0110100001110100011101000111 IIIIII                   
                   IIIIII 0000001110100010111100101111 IIIIII                   
                   IIIIII 0110011101101111011011110010 IIIIII                   
                   IIIIII 1110011001110110110000101111 IIIIII                   
                   IIIIII 0110101001010000010011110100 IIIIII                   
                   IIIIII 100101101100IIIIIIIIIIIIIIII IIIIII                   
                   IIIIII IIIIIIIIIIIIIIIIIIIIIIIIIIII IIIIII                   
                   IIIIII IIIIIIIIIIIIIIIIIIIIIIIIIIII IIIIII                   
                   +IIII  IIIIIIIIIIIIIIIIIIIIIIIIIIII  IIII:                   
                                IIIIII    IIIIII                                
                                IIIIII    IIIIII                                
                                IIIIII    IIIIII                                
                                IIIIII    IIIIII                                
                                IIIIII    IIIIII                                
                                IIIII,    IIIIII                                
                                  I:        ~I                     

I noticed the binary around the android's belly so I translated it into ascii text and got the following URL:

I went to the URL and was faced with a puzzle with a timer. The puzzle involved rearranging letters, by swapping two neighbours, in a string so they were in the "correct" order. You could see how many were correct at the bottom of the page. It was pretty simple and I got the solution before the timer ran out (it took me a few seconds to recognize I was being timed).

Clicking the Tweet your victory! button opened a web tweet box with the message:

@googlenexus Run, run, as fast as you can! You can't catch me, I'm the Gingerbread Android!

I hope it's not against the rules to post the solution; I looked quickly through the legalese and didn't see anything forbidding it.

Tuesday, July 27, 2010

Getting my Images on Canvas

I've been rendering some of my models to print them on canvas recently.

I had to wait to buy a new computer to render my stuff. Can you believe it though? I'm already upgrading. You'd think 8 gb would be lots of RAM, wouldn't you? My new RAM is in the mail.

I transferred one of the images to canvas already. It's only a little over 2' by a little over 4' but it cost me nearly $300 to print after taxes! My neighbour is going to stretch it onto a frame for me. I'm pretty excited.