Google Analytics, jQuery, and File Downloads
by
First, let me say that Google Analytics is awesome. Anytime someone purchases a company and makes their industry-leading, $200-a-month product freely available, it’s a-ok in my book. While you won’t see any complaining out of me, there are a few aspects of the package that are less than desirable, but are simply the nature of the beast.
To understand the limitations, it’s important to understand that Google Analytics is javascript based and does all of it’s nice tracking on the browser side once a page is loaded. That’s fine, but it is difficult to track anything other than a standard web page. Because files (zip, word, pdf, mp3, etc.) can’t contain javascript and aren’t processed in a browser, you have to track these files by inserting special code on the links pointing to those files. Google has a help page explaining how to track these downloaded files (it also works for tracking links to anything, such as links to external sites or mailto links).
Google provides the following instructions on formatting these links:
<a href="http://www.example.com/files/map.pdf" onClick="javascript:urchinTracker ('/downloads/map'); ">Important: if your pages include a call to urchinTracker(), utmLinker(), utmSetTrans(), or utmLinkPost(), your Analytics tracking code must be placed in your HTML code above any of these calls. In these cases the tracking code can be placed anywhere between the opening
tag and the JavaScript call.
Well, I don’t know about you, but all that javascript in my link tags gives me the willies. If Google every changes their script (or something better comes along), have fun changing every single download link on your site. That’s every template, every article, everything.
So, I went looking for a way to apply this code dynamically into the appropriate links on my site, and sadly, I didn’t mind much. It was obvious that I was going to have to do a good portion of this on my own, and I might as well make good use of my new best friend, jQuery, while I was at it. (Note: I know some of the following techniques come from other, smarter people, but this became such a mismatch of ideas that I honestly am unsure who to give credit to. If you recognize anything that needs attribution, please let me know)
First things first, I didn’t follow Google’s guidelines for how to include their javascript, but everything seems to work great in my testing (I have been using this technique for a couple months now without incident or report of problem - across multiple sites). The following can be found in the
section of every page on my site:<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
<script type="text/javascript" src="/javascript/jquery.js"></script>
<script type="text/javascript" src="/javascript/analytics.js"></script>
I’ve included the Google Analytics javascript, the jQuery javascript, and my own custom analytics javascript. It’s important to include the analytics.js file last.
Ok, now let’s take a look at what’s inside my file:
$(document).ready(function(){
// This code needs to be changed to the code Google Analytics provides for your account
_uacct = "UA-1111111-1";
urchinTracker();
// The slashes are to ensure the period is in the url, the $ is to make sure it is the end of the url, the i is to make it case insensitive.
filetypes = /\.doc$|\.xls$|\.exe$|\.zip$|\.pdf$|\.mp3$|\.psd$/i;
$("a").each(function(){
// Track mailto links
if ($(this).attr("href").match(/^mailto\:/i)) {
var url = $(this).attr("href").replace(/^mailto\:/i, "")
$(this).click(function() {urchinTracker("/mailto/" + url);})
}
// Track external links
else if (location.host != this.host.replace(/\:80$/i, "")) {
var url = $(this).attr("href").replace(/^http\:\/\/(www\.)*/i, "")
$(this).click(function() {urchinTracker("/outgoing/" + url);})
}
// Track downloads (links with a given extension)
else if ($(this).attr("href").match(filetypes)) {
// The URL needs to be changed for each site this is applied to.
var url = $(this).attr("href").replace(/^(http\:\/\/)*(www\.)*(permanentinkdesign\.com")*\//i, "")
$(this).click(function() {urchinTracker("/downloads/" + url);})
}
});
});
And that’s it. There are a few things worth noting in this script. First,
_uacct = "UA-1111111-1";
needs to be replaced by the code that Google supplies to you (the numbers here have been changed for my protection). Second,
filetypes = /\.doc$|\.xls$|\.exe$|\.zip$|\.pdf$|\.mp3$|\.psd$/i;
is a variable containing a regular expression stating the file extension of all the file types I’d like to track. If regular expressions don’t make much sense to you (they didn’t to me when I started working through this), then you’d be wise spending some time learning how they work. They are very powerful and can help in a lot of nifty ways.
The next part of the script goes through every link on the page, applying functions that will fire when links that match our criteria are clicked.
$("a").each(function(){
This is the jQuery code that says, “Give me every ‘a’ tag, and for each one, run the following function.” There are three types of links I want to track (you can add others as you see fit). The first type is the mailto link.
if ($(this).attr("href").match(/^mailto\:/i)) {
var url = $(this).attr("href").replace(/^mailto\:/i, "")
$(this).click(function() {urchinTracker("/mailto/" + url);})
}
The first line of this part says, “If the href attribute of this link starts with ‘mailto:’ then do the following.” Line 2 rips the email address out of the link and applies it to the url variable. Line 3 adds the onclick function to this link. It means that anytime someone clicks on this link, it will show up as a pageview for /mailto/example@nospam.com in Google Analytics (yes, the email address will be what is actually set in the link, not example@nospam.com). The last half of this line should look eerily similar to the Google approved method shown at the top of this article.
The second type of link I would like to track is a link to an external site. I look for links in a particular order because I want to catch all links to external sites, even if they are linking to files, before I look for files on my own server. Otherwise, I could have other people’s files show up in my downloads list in Google Analytics. I search for mailto links first because I am unsure how these links work with the location lookups I do for external links, so I remove the uncertainty by looking for them first.
else if (location.host != this.host.replace(/\:80$/i, "")) {
var url = $(this).attr("href").replace(/^http\:\/\/(www\.)*/i, "")
$(this).click(function() {urchinTracker("/outgoing/" + url);})
}
The first thing you’ll notice is the “else if.” In plain english, this line says, “Ok, so this link isn’t a mailto link. Fine. If, however, the website to where this link is pointing isn’t the same as the website I’m currently on, do the following.” You’re sure to notice the .replace(/\:80$/i, “”) portion of this statement. That is a regular expression to make the way all browsers view this.host consistent with how they view location.host (basically, Internet Explorer adds :80 to the end of this.host, so we’re removing that if it exists).
Line 2 sets the url variable to the url of the external link, minus the http and www bits (for easy reading). Line 3 adds the onclick function, which should make sense at this point.
Moving on, I want to track links to files on my server (downloads, if you will).
else if ($(this).attr("href").match(filetypes)) {
// The URL needs to be changed for each site this is applied to.
var url = $(this).attr("href").replace(/^(http\:\/\/)*(www\.)*(permanentinkdesign\.com")*\//i, "")
$(this).click(function() {urchinTracker("/downloads/" + url);})
}
The first line says, “Alright, this link isn’t a mailto link, and it isn’t an external link. If, however, the href attribute of this link ends with one of my specified file extensions, do the following.” Line 2 (line 3 if you count the comment) again sets the url variable, this time to the url of the file minus the http://www.mywebsite.com/ stuff. You’ll need to replace the “permanentinkdesign” portion of this line with the site that you’re using this script on. I have a sneaking suspicion that there is a better way to do this, perhaps by using something similar to this.host, but I couldn’t get it to work. I’m open to recommendations for improvements. Line 3 once again adds the onclick function.
And now, that really is all there is to it.
Comments
Robin says:
Jake, I hope someone has commented on this by now! Great stuff here. I’m going to give it a whirl, although I am going to try it by putting the analytics.js code right beneath the urchin code that sits at the end of the page body (just to keep things together).
Good work!
permanent link|Wednesday, February 13, 2008, at 5:35pm
Jake says:
Robin,
Thanks for the comment! You should be able to add this to the bottom of your page without incident (just be sure to include jQuery in the head). If you do add it at the bottom, you may want to take out the opening “$(document).ready(function(){” and closing “});” because you don’t have to worry about it firing when the page finishes loading if it is at the end of the document.
Also, you may want to remove the
since that is already part of the standard code Google has you add to the bottom of each page.
Let me know how it turns out.
P.S.—for testing purposes, you can change each “urchinTracker” you find to ‘alert’ so you can see what is happening on each link you click. Once you know everything is working, change it back to “urchinTracker” and you’re good to go.
permanent link|Thursday, February 14, 2008, at 11:17am
Pirkka says:
Looks pretty useful and I’ll give it a try. Thanks for the tip!
I suppose the code is compatible with the latest jQuery?
permanent link|Thursday, February 5, 2009, at 1:18am
Jake says:
Pirkka,
I’m about to post a new article with an updated version of this script. It requires the latest version of jQuery because it makes use of the new live() funtion. It also now calls the Google Analytics script for you, and runs through functions only after it has loaded. If you look at the source of this page, you’ll see I’ve included the javascript in the footer.
For now, here is the raw script—it is gzipped—(just change the pageTracker code to your site’s code and you should be good to go).
permanent link|Thursday, February 5, 2009, at 4:16pm