Extend Google Analytics with jQuery

Originally posted on 16th May 2009 by Ian Harris

« Back to articles

For quite some time now Google Analytics has been leading the way when it comes to gathering free statistics about the web traffic of your website. I’m sure that you many of you have installed the Google code on your sites and are already using the great reporting tools it provides. However, there are a few limitations to the standard service which you may or may not have come across yet. Using the standard code, we can only track views of pages where the tracking code is installed. It becomes a little bit more difficult if we want to track file downloads and external links, where we cannot add the Google JavaScript.

The aim of this tutorial is to show you how you can modify the standard Google tracking code using the power of jQuery to get extra information from your Google Analytics reports. With jQuery, we can get Google Analytics track your file downloads and clicks to external sites without having to trawl through your code and write any extra mark up.

We are also going to use a new feature of Google Analytics which are known as ‘Events’. This should give you a good base for you to build your own code and extend the power of Google Analytics even more.

Getting started

If you haven’t already, head over to the Google Analytics site and sign up for a free account. You will need to setup a Website Profile, which should be pretty self explanatory.

When you have your unique tracking code, either from your new Google account or from your current websites tracking code, take a note of the UA number, for example: UA-1234567-1. This is your unique identifier which tells Google what website to track and we will need it later on. If you already have the tracking code installed on your website, remove it now. Otherwise you could end up duplicating your stats!

Google Analytics Events

Before Google released the new pageTracker._trackEvent() function, we would use the normal pageTracker._trackPageview() function. To make your external links and file downloads stand out from your normal page visits, you can pass this function a modified url. For example, say we wanted to track the download of a PDF called myfile.pdf. We would add a pretend folder in front of the file name. This folder may not exist on your site, it’s there so you can easily spot downloads in your Google Analytics reports.

We could call this function like so:

1
pageTracker._trackPageview('/downloads/myfile.pdf')

You may wish to use this method instead of the newer functions, it’s up to you. However, I would recommend that you take a look into the new functions as it allows you to track much more.

For more information about tracking events read, the Google Analytics Event Tracker Guide. You will see how flexible the new method is and you can expand on this tutorial to track other events on your website.

Viewing you new events in Google Analytics

At present, the new event tracking function is still in beta on the Google Analytics site and not all accounts have access to view them by default. However, this is not a problem as you can add it in manually. When you are logged into your Analytics, type the following url into your browser: https://www.google.com/analytics/reporting/events. This will take you to events page. Once there, click on the “Add to Dashboard” button above the report and this will add the Events Tracking Overview section to your dashboard.

Integrating jQuery

There are a couple options available to you when you load the jQuery code; you can download a copy from the jQuery site and call it locally, or as we will do, call it directly from the Google code library. For more information why this is the better way to load jQuery, read 3 reasons why you should let Google host jQuery for you.

In the <head></head> section of your HTML, copy and paste the following code.

1
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js" type="text/javascript"></script>

This load the minimised version of jQuery 1.3.2, which is the current verison at the time of writing, you may wish to check to see if there is a newer version available. For more information about jQuery, take a look at the jQuery Documentation.

Writing the custom tracking code

Still in the <head></head>, directly beneath the code we have just inserted, enter the following:

1
2
3
4
5
6
7
8
9
10
11
12
<script type="text/javascript">
$(document).ready(function(){
 
	var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
	$.getScript(gaJsHost + "google-analytics.com/ga.js", function(){
 
	try {
		var pageTracker = _gat._getTracker("UA-xxxxxxx-x");
		pageTracker._trackPageview();
	} catch(err) {}
 
	var filetypes = /\.(zip|exe|pdf|doc*|xls*|ppt*|mp3)$/i;

Instead of loading the Google Javascript directly in the mark up, we are using the jQuery $(document).ready function to load the code as soon as the DOM is ready, which means that our code is ready before any of the page content gets loaded. Therefore we can target elements, such as links, when they are loaded by the browser.

Next, we include the standard Google tracking code to register that the current page has been visited. The difference here is that we are using another jQuery function, $.getScript, to load the Google JavaScript file and then create a function to run once the file is loaded. Make sure you replace the UA-xxxxxxx-x with your own unique UA number. We then set a variable called filetypes which holds a regular expression to find any links with popular file extensions, you can add or remove any file extensions you wish.

Outbound links

Now we get to the part where we add the code which will actually start tracking the additional links. We will start with all of the external links on the page.

Add the following code to your script:

1
2
3
4
5
6
7
8
9
        $('a').each(function(){
            var href = $(this).attr('href');
 
            if ((href.match(/^https?\:/i)) &amp;&amp; (!href.match(document.domain))){
                $(this).click(function() {
                    var extLink = href.replace(/^https?\:\/\//i, '');
                    pageTracker._trackEvent('External', 'Click', extLink);
                });
            }

The $('a').each function will target each <a> tag in turn and execute the code within the function itself against that tag. The first part of this function is to set a variable, href, which will hold the value of the href attribute of each <a> tag.

Our first if statement performs two checks. It is making use of the .match function to check to see if the value of our href variable either starts with http: or https: (using a simple regular expression) and that it does not contain the current domain of the website (i.e. it is external).

If this if statement is returned true, we then add a click event to the current <a> tag the our script is currently looking at. When this click event is triggered, we use another regular expression to strip the http:// or https:// from the link path. Finally, we use Google’s pageTracker._trackEvent function to send the event details to our Google Analytics account. The first option for the function it to set the link category, I have used ‘External’. The next option is the to set the action, this has been set to ‘Click’. The last option is to sent the link label. This is set to the url of the external link.

Mailto: links

The next type of link we are going to target are any email address links that may be on the current page. As you know, the email address is preceeded with mailto:, so we can easily pick them out with jQuery.

Directly after the last if statement, add the following code to your script:

1
2
3
4
5
6
            else if (href.match(/^mailto\:/i)){
                $(this).click(function() {
                    var mailLink = href.replace(/^mailto\:/i, '');
                    pageTracker._trackEvent('Email', 'Click', mailLink);
                });
            }

This works in exactly the same way as the external link if statement. We use a regular expression to find any email links, clean the link up by removing the preceeding mailto: and then fire off the Google tracking event.

File downloads

The last type of links we are going to track are file downloads. Again, using a regular expression, we will check each link and match ita againsts the filetypes variable we created earlier.

Add the following code to your script under the last statement:

1
2
3
4
5
6
7
8
9
10
11
            else if (href.match(filetypes)){
                $(this).click(function() {
                    var extension = (/[.]/.exec(href)) ? /[^.]+$/.exec(href) : undefined;
                    var filePath = href.replace(/^https?\:\/\/(www.)mydomain\.com\//i, '');
                    pageTracker._trackEvent('Download', 'Click - ' + extension, filePath);
                });
            }
        });
    });
});
</script>

Again, the process is the same, but this time we are going to extract the file extension into a variable called extension using yet another regular expression. If the link is an absolute link (i.e. it has the full http://www.mydomain.com/ in the file path), we removed the protocol and domain name as we don’t really need this in our Google Analytics reports as we already know that the link is local to our site. Make sure you replace mydomain.com with your own domain name.

Here is the code in full (with the gaps removed so it fits on the page better):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<script type="text/javascript">
$(document).ready(function(){
 
    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
    $.getScript(gaJsHost + "google-analytics.com/ga.js", function(){
 
        try {
            var pageTracker = _gat._getTracker("UA-xxxxxxx-x");
            pageTracker._trackPageview();
        } catch(err) {}
 
        var filetypes = /\.(zip|exe|pdf|doc*|xls*|ppt*|mp3)$/i;
 
        $('a').each(function(){
            var href = $(this).attr('href');
 
            if ((href.match(/^https?\:/i)) && (!href.match(document.domain))){
                $(this).click(function() {
                    var extLink = href.replace(/^https?\:\/\//i, '');
                    pageTracker._trackEvent('External', 'Click', extLink);
                });
            }
            else if (href.match(/^mailto\:/i)){
                $(this).click(function() {
                    var mailLink = href.replace(/^mailto\:/i, '');
                    pageTracker._trackEvent('Email', 'Click', mailLink);
                });
            }
            else if (href.match(filetypes)){
                $(this).click(function() {
                    var extension = (/[.]/.exec(href)) ? /[^.]+$/.exec(href) : undefined;
                    var filePath = href.replace(/^https?\:\/\/(www.)mydomain\.com\//i, '');
                    pageTracker._trackEvent('Download', 'Click - ' + extension, filePath);
                });
            }
        });
    });
});
</script>

Conclusion

With the power of jQuery and the new Google ‘Events’, it is clear that you can take your website statistics further and produce more meaningful reports. This will help you gain a better understanding of how your website is being used and what your users and looking for, which can only be better for all concerned.

You can download the full code below, make sure you add in your own UA number and domain name.

Have you extended this code further? Have you found any other uses for the new Google ‘Events’? Perhaps you have written your own jQuery plugin with it. Please comment below and let us know, we would love to hear if you have found this useful in any way.

Thanks!

Resources

Comments

  • How can we track the time of users visit.

    I think it will help in deciding maintenance period because you will know at what time you have least amount of visitors.

    Thank You.

    • Hi Shishant,

      I’m not aware of anything in Google Analytics that allows you to do this. However, you may be able to add a second _trackEvent function to each click event. Maybe you could set the catagory to Time and then use Javascript to dynamically set the Action/Label to the current hour of the day. That way you could track the busiest hours.

      Let me know how you get on.

      Thanks!!

  • Very interesting article, and explained very clearly – I look forward to implementing this on my corporate website.

    Already looking forward to the next CM article!

    Thanks
    Stuart

  • Very interesting and great article indeed.

    Looking forward to try it as well!

    Thanks for sharing

  • I wrote a jQuery plugin that incorporates this functionality against the old urchintracker version of GA back in 2007. The original post is here:

    http://devblog.jasonhuck.com/2007/11/19/google-analytics-integration-with-jquery/

    Since then, David Simpson has quite nicely expanded on that code and updated it to work with the current ga.js script. He’s done a great job with it. The current version (about a year old now) is here:

    http://davidsimpson.me/2008/06/18/jgoogleanalytics-google-analytics-integration-for-jquery/

    We use this on our sites now and it works great.

    – jason

  • Great article with good tips on extending the capabilities of the standard app.

    Shishant – You can track visits per hour by clicking on Visits from the Site Usage dashboard. Below the date bar, you’ll see graphing options. Click on the option that looks like a clock. You’ll then see visits by hour.

  • The events of analytics are very interesting. If to this we join the jquery the results are spectacular.
    Thanks

  • Thanks for a decent article. I’m looking forward to read it thoroughly and give it a try.

    Thanks

  • Hi there.
    Great article. I’m gonna take a look at it and see if we can implement it.

    Thank you!

  • Must say this is one of the most interesting articles I’ve read in a while. I’ll definately be giving this a try.

    Thanks for sharing.

  • This was a very well written tutorial. We are testing this code now.

    Thank you for posting.

  • Hi. Great post. Thanks!

    Newbie question:

    We are running some in-text advertising js code that is also supposed to be placed before the ending html tag.

    Can we include this ja in your $(document).ready(function(){} code, for example, here?


    blah blah blah code

    });

    Or, should we do it differently?

    • Hi Tim,

      Yes, you should be able to use the same method, but the only way to tell is to give it a go. Some scripts may not like it, but I haven’t had one yet.

      Thanks for the comments, I’m glad this has been useful for you.

      Ian

  • Hi Ian,

    BTW, We get an error in the error console when we run the code in this post. We tried it “full code” and also tried it “outbound clicks only”, but got the same error.

    I forwarded you a screen dump, because I could not cut-and-paste from the Opera error console.

    Cheers.

    • Hi Neo,

      I’ve sent you an email. I looks like there is a conflict with jQuery.

      Try replacing all of the ‘$’ symbols in the script with ‘jQuery’. This should help prevent any conflicts. For example, “$(‘a’).each(function(){” would become “jQuery(‘a’).each(function(){“.

      Hope this helps!

      Ian

  • Hi Ian,

    Thanks! I wish I knew jQuery like you.

    I’ll post back the results of implementing your suggested changes, when I get a low traffic window to implement and test.

    Cheers.

  • Jquery.getScript() does NOT cache!

    So if you follow the instructions in the custom tracking script section you will now be downloading ga.js for each request instead of hitting the browser cache.

    http://jamazon.co.uk/web/2008/07/21/jquerygetscript-does-not-cache/

  • Is there a way to get the full file path of a link if it is relative path for example:

    Current page http://www.yourdomain.com/hr/subsection/document.html

    Link
    ../downloads/document.doc

    So the final path would be
    http://www.yourdomain.com/hr/downloads/document.doc

  • Hi,

    What if I want to host the extendga.js file in a subdomain instead of the actual domain for example in sub.domain.com/extendga.js ? Should the code be modified to enable this fox example:

    try {
    var pageTracker = _gat._getTracker(“UA-xxxxxxx-x”);
    pageTracker._setDomainName(“.domain.com”);
    pageTracker._trackPageview();
    }
    catch(err) {}

    http://www.google.com/support/googleanalytics/bin/answer.py?hl=en&answer=55524

    Thanks!

    • Hi,

      It doesn’t matter where the extendga.js JavaScript file is called from as the code is effectively inserted into the page itself. You could host the file on a completely different domain if you wish, however it’s probably not recommended due to latency issues.

      Therefore you will not need to modify the code if you host it in your sub domain. As it happens, we host the file on a sub domain of this site.

      Hope this helps,

      Ian

  • Hi !

    Many thanks for the great article.

    I’m looking for a way to track external accesses to my PDF’s URLs, I mean when someone browses directly for the URL without loading any web page where the onClick event is located.

    Is it possible? Any hints?

    Many thanks !!!!!

  • Hi Ian, I just thought I’d chime in on an error that I noticed. Any old-school anchors with the name attribute used to send a user to navigate to a different location within the page that do not include an HREF attribute will throw an error. It’s an easy fix:

    $(‘a[href]’).each(function(){

    Cheers!

  • When I use your script, I get an error in Firebug:
    href is undefined
    [Break on this error] if ((href.match(/^https?:/i)) && (!href.match(document.domain))){
    Line 21
    I use jQuery 1.4.2
    How can I solve this?

    • Hi Johan,

      I think that Brendon has posted a fix for this in the comments already. Find the line $('a').each(function(){ in the file and replace it with $('a[href]').each(function(){. This filters out any <a> tags that do not have an href attribute.

      Thanks to Brendon for pointing that out, I will update the post later with this fix.

      Cheers,

      Ian

  • Thanks for this great article Ian. Really well written and easy to follow.

    Is there a way to also see which page the links were clicked on in your site?

  • Hi Ian, does this mean we won’t need the normal GA code since this already includes it?

    Thanks for a great article!

    Len

  • I have installed your tracking code and it is working partially. It is tracking clicks on links to external sites but not tracking clicks to download a document on the page

    How can I track this event with your code?

    />

    I would like to see how many clicks or “Plays” each file gets like LoveSong for media/LoveSong.mp3
    Thank you for your advice.
    Hal

  • Ian, I was trying to simplify the process as best I could and have been having problems doing so. Since you’ve worked with GA’s Event Tracking…can you see any reason why this code wouldn’t work?

    http://pastebin.com/VyB1aijn

    • Hi Brendon, try changing line 16 to :

      $('a[href^="http"]').not('a[href*="'+domain+'"])').each(function(){

      I haven’t tested this, but let me know how you get on.

      Thanks,

      Ian

      • Hey Ian, thanks for taking a quick look. The problem seems to specifically be that the event tracking itself is not working. I’ve checked the hyperlink onclick event with a simple alert box and that seems to work as expected. If I simply run a call to trackPageview instead of trackEvent, the call works.

        I’ll try your code anyway since I’m picking at straws. 🙂 Thanks!

      • The problem was that I wanted to track where the page from which the current click came from, so I used:

        document.location

        Unfortunately, this is not strictly a type of “String” in JavaScript (and google’s methods for analytics are strictly typed). It’s an object with properties. One could have assigned it to a variable and then used toString(), or just used the property .href on the object to get the desired string to pass to the trackEvent method. Once I (finally realized and) did that, all was happy in Google Analytics land. Thanks again for taking a quick look over it! I never thought document.location was not of type “String” since alerting it will show (by default) the value of document.location.href. Oops.

  • I wrote about doing something similar, but with the new Asynchronous Tracking Code. I don’t go into as much detail as you do, but people may find it helpful:

    http://stephenakins.blogspot.com/2010/12/link-tracking-using-jquery-and-google.html

  • Thanks for the great tutorial, well explained and easy to implement!

    My question I think is pretty basic…

    Instead of pulling the href with the full link name, is it possible to pull a different user-defined variable associated with the link, such as the title attribute or some other user-definable variable? So extLink would be something like extTitle, making it a more user-friendly name?

    Thanks again!

    Ethan

      • Is it possible not to exclude own domain? Would it look like this?

        //check for links starting with http or https, making sure that links to our own domain are excluded

        if (href.match(/^https?:/i)){
        $(this).click(function() {
        var extLink = href.replace(/^https?:///i, ”);
        pageTracker._trackEvent(‘External’, ‘Click’, extLink);
        });

        • Hi Ethan,

          Yes, that should work, although I’m not sure why you would want to do this as each time one of your internal links is clicked, it will then be recorded twice in Google Analytics.

          Many thanks,

          Ian

    • Hi Ethan,

      Many thanks for the nice comments!

      Yeah, you can pull what ever information you like from the link. First of all, you’ll need to cache the $(this) object in a variable, then you can select which attribute to choose. The final code could look like the following:


      $('a').each(function(){
      var curLink = $(this);
      var href = curLink.attr('href');

      if ((href.match(/^https?:/i)) && (!href.match(document.domain))){
      curLink.click(function() {
      var extLink = curLink.attr('title');
      pageTracker._trackEvent('External', 'Click', extLink);
      });
      }

      I haven’t tested this, so please let me know if it works OK.

      Many thanks,

      Ian

  • Hi,

    Very good post, I translated it in French on this page: http://blog.carnould.com/2011/05/comment-ajouter-des-evenements-google-analytics-avec-jquery/

    And I put a trackback to your website.

  • Hi Mike,

    Let me know if you need a hand, drop me an email when you are ready.

    Speak to you soon,

    Ian

  • Hi Ian,

    I found a slight issue in the script if the page contains anchor tags with no hrefs (eg when used with an id for in page links). The lines “href.match” were throwing “href undefined” errors for those links. I didn’t try to see if this prevented the script as a whole from working, but I thought you might like to know. I solved this by wrapping the href.match statements in

    if(!(typeof href === “undefined”)) {

    }

    Thanks for the excellent script though.

    Regards,
    Robin

  • I know very little about jQuery, but I’m trying to implement this on an older website whose download links tend to look something like this: http://ccrc.tc.columbia.edu/DefaultFiles/SendFileToPublic.asp?ft=pdf&FilePath=c:Websitesccrc_tc_columbia_edu_documents332_974.pdf&fid=332_974&aid=47&RID=974&pf=Publication.asp?UID=974

    Do you think this script should be able to pick out the file type from all that so I can track downloads?

    Unfortunately, I can only upload files through a content management system that generates download links like that, so I can’t make them any cleaner.

  • Hi,

    Thanks for the article. I am trying to implement on website powered by CommonSpot CMS, but it is showing all the JS code on the pages.

    Did I missed anything?

    Thanks,
    Ashraf

  • Thanks for this great info..!
    Is it applicable to asynchronous tracking code?

  • var href = this.href;

    is much faster than

    var href = $(this).attr(‘href’);

    No need to use jQuery.

  • Can you add a Blackberry template? This web page is tricky to read otherwise for those of us browsing with cell phones. Otherwise, in the event you can place a RSS link up, that would be good also. dbgadadagdce

  • Hi. Any updates to the code since first posted or an additional PHP library with examples for us to follow?

    Thanks

Comments are closed.