Track outbound links and file downloads automatically in Google Analytics

Just to let you know that I have finally gotten round to updating the original combined tracking script hack I had for urchin.js to the new ga.js. Essentially the combined tracking script is a modification of the GATC so that it automatically tracks:

  • outbound links – Automatically
  • file downloads – Automatically
  • mailto links – Automatically

Therefore, instead of having to manually modify such links by adding an onClick event handler to your ‘a’ tags, this script will do it all for you.

April 2011 – New async hack launched
This hack has been completely revise for the latest GA async code. Further info >>


Why is this necessary?

Outbound links (links to other websites from yours), file downloads (e.g. PDFs, exe, xls etc.) and mailto links (links to an email address) can be important indicators as to whether your site is engaging with visitors. If so, you will certainly want to track these and potentially define them as goals in your Google Analytics reports.

Normally you do this by creating a virtual pageview. However if you have hundreds/thousands of these, or even just a few dozen that constantly change, manually tagging them is an administrative nightmare.

This script uses the properties of the browser (Document Object Model, or DOM for short), to capture links that are non-standard pageviews and automatically create the event handler for you.

The result is that your outbound links, file downloads and mailto links are tracked for you and are always up to date. The default virtual locations for these in your Google Analytics reports are: /ext/, /downloads/, and /mailto/ respectively, though of course you can change these as you wish. Typically you will wish to view these in your Content > Top Content report as shown below:

IMPORTANT: The position of this code within your page is important. This must placed after your call to the GATC. Add addLinkerEvents() in an onLoad event handler and host the JavaScript in a separate file. As an example I show this below, assuming the javascript is hosted in a file called trackExternal.js, as follows:


…your remaining web page content…


A note on performance: Each time your page loads, this script will go through all links referenced on the page to see if it is for a download. Clearly the more links on your page, the harder the script must work. As long as the number of links on each page number in the hundreds and not thousands, performance should not be a problem. Also, pages with a large number of links, it is possible that visitors will click on a download link before the script has modified it. The result is that click through will not be tracked by Google Analytics.

Related posts:

Are you using this or creating your own hacks for Google Analytics? Please post your comments and share your thoughts here.

Looking for a keynote speaker, or wish to hire Brian…?

If you are an organisation wishing to hire me and my team, please view the Contact page. I am based in Sweden and advise organisations in Europe as well as North America.

You May Also Like…


  1. Olaf

    Nice article, just to add a bit: If you want to see in Google Analytics, how often an email or newsletter was opened (or viewed), you can use, There you can get a pixel which you insert into your email. The pixel will then cause your Google Analytics to show how often the email has been read.

    • Brian Clifton

      Olaf: I am not a fan of this technique (hiding a tracking pixel in emails) as 1) it violates the recipients privacy and damages trust – usually tracked at individual level and collects personally identifiable information (their email address) and 2) because it is very inaccurate – all email programs I know of block 3rd party images by default as it is a spam technique.

      Of course if you have a very loyal email list e.g. double opt-in and so much more likely to allow image display, and do NOT track any PII, there is a strong case for doing this.

  2. Paul Taylor

    Hi Brian,

    I tried that but my analitcs stopped working, when i removed the code it started working again.

    Any idea?



    • Brian Clifton

      Paul: Sounds like a javascript error. Have you debugged all code?

      BTW, I run the same script on this site and all working fine for me…

  3. silviacc

    if (flag == extTrack.length && as[i].href.indexOf(“mailto:”) == -1){
    as[i].onclick = function(){ var splitResult = this.title.split(“//”);
    pageTracker._trackPageview(‘/LINK/’ +splitResult[1]) + “;” +((tmp != null) ? tmp+”;” : “”);};

    In the html :

  4. Whimsical

    Hi 🙂

    Will there be an updated version of this script to work with the asynchronous tracking code? I did have a look in the Pro Lounge but didn’t find an async compatible version available ..unless my specs arent working properly?

    Whims 🙂

    • Brian Clifton

      Whims – new async scripts are not ready just yet, though look out for the announcement in the Pro Lounge soon (Feb)…

  5. silviacc

    HI, I have found the solution with “title” ..

    • Brian Clifton

      Silviacc: Thanks for letting us know. Would you like to publish your work around here?

  6. silviacc

    Hi, Can we replace


    with the “alt” attribute


    I ask that because my url are always on the same domain and finish alway with number : it s not easy to say which content is view..



  7. Jan


    will there be a version working with the new async method for GA?



  8. Brendan Halloran

    Hi Jonathan,

    I too have encountered this issue before. Usually there is some common element in the URL that you can pick up on and identify as the trigger for tracking of file downloads. If you provide the URL of a webpage where this type of file download link exists, I should be able to suggest a workaround.


  9. Jonathan

    Hi Brian,

    Thanks for all the insight! I have bought both of your books, but still in my learning curve :).

    I am wondering if you have had any experience working with sites that have the same file extension for ALL pages and file downloads? specifically .ashx. This looks to be a limitation of the Sitecore CMS as we are having trouble tracking files downloads to show engagement.

    Any insight would be greatly appreciated.

    Happy Holidays, Jonathan

    • Brian Clifton

      Jonathan: thanks for being a great purchaser 😉

      I have seen this issue (same file extension for all file types and downloads) once before. I struggle to understand why a CMS developer would do this – I real lack of insight from them. Search Engine visibility i.e. Google not able to index content properly was also an issue. It begs the question, was is the point of it…?

      The team hosting the CMS ended up applying custom code to overcome the issue though I have lost contact with them. I will see what I can dig up, though long-term my advice is to start planning your move to a different CMS… Drupal and EPiServer have been recommended to me form people who’s opinion on such matters I respect, though even WordPress in impressive and powerful.

      Hope that helps.

  10. dhl

    Hi Brian,

    great website you have and great book(s) ( I have both editions, and they are money well spent!)

    I have a problem with the script and simply cannot get it to work.

    I’ve tried to use Google Chromes developer tool, the Javascript console, to see if that can help me.

    In your scriptfile, line 53 after the following code:

    >if (flag == extTrack.length && >as[i].href.indexOf(“mailto:”) == -1){
    >as[i].onclick = function(){ var splitResult = >this.href.split(“//”);pageTracker._trackPageview(‘/ext/’ >+splitResult[1]) + “;” +((tmp != null) ? tmp+”;” : “”);};

    I get the following errormessage:
    Uncaught Reference Error: pageTracker is not defined.
    This happens everytime I click on a link and thus should track the link…

    I’m a novice in Java Script and really cant figure out where i’m going wrong.

    You can see the website where I’ve implemented your code here:

    I understand if you don’t have time to help me out, but I’m crossing my fingers anyway 😉


    • Brian Clifton

      David – I hope you understand that I am unable to help directly. Essentially, scripts are provided free of charge and available “as is”. However, I can assure you that the script you reference is working on as well as others that I have implemented on.

      BTW, note that this script is not available for the new async method for GA installation.

  11. Robin

    Hi Brian,

    Am running into a odd ASP.NET (Version Information: Microsoft .NET Framework Version:2.0.50727.3615; ASP.NET Version:2.0.50727.3614 as part of Ektron CMS) error when trying to implement the onLoad event handler within the body of the site pages.

    The error is as follows:
    error BC30456: ‘AddHandler__ctrl’ is not a member of ‘ASP.get_involved_default_aspx’.

    AddHandler __ctrl.Load, AddressOf Me.AddHandler__ctrl.Load, AddressOf Me.addLinkerEvents()

    Would you happen to have exprienced this issue before? Is it a problem with the standard DOM approache being incompatible with ASP.NET?

    Thanks in advance for any help or guidance you can provide on this query.

    • Brian Clifton

      Robin: I haven’t come across this error before, but the DOM approach will work with any browser that supports javascript. Therefore, it must be how your CMS can communicate with it. Please let us know if you make progress…

    • Brian Clifton

      Mark: If you have an external link, its href attribute must start with “http://”, right?

  12. MonaE

    The directions say to add:
    [body onLoad=”addLinkerEvents()”]

    My webpages use body id’s so can I add the onload to code? Here is what my webpages have now:
    [body id=”cityservices_pg”]

    Since my code did not show up in previous post, I made them “[” and “]” instead.


    • Brian Clifton

      MonaE: the id property is there for css formatting. It will not interfere with the onLoad event, so you can go ahead and add this.

  13. Keith

    Drachsi Says:
    > All I wanted to do was track pdf file views or downloads.

    If you don’t mind manually tagging these, then the approach described in (see “New Asynchronous Tracker Script for Google Analytics”) seems to work.

    In my case, I’m interested in tracking clicks on outgoing links. An example of this approach is shown at .
    I’m wondering if it is still desirable to add a delay when using the new asynchronous GA code — and, if so, are there any recommendations for the form that such a delay function should take when using the new asynchronous GA code?


Submit a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Share This