Blast Analytics and Marketing

Analytics Blog

Supporting Leaders to EVOLVE
Category: Google Analytics

How to Track Downloads & Outbound Links in Google Analytics

March 22, 2013

It has been almost 2 years since we published our wildly popular post, How to Track Downloads in Google Analytics. Since Google Analytics does not track file downloads, email, telephone or other outbound link clicks automatically, we saw an opportunity to File Downloadsprovide this code to the community. In our original post, we provided some explanations and code examples for tracking file downloads in Google Analytics using event tracking.

We decided to revisit our original post and provide a valuable code update that improves performance, makes tracking downloads more manageable and easier to extend.

Dynamically Track Downloads & Other External Links

For those who have a lot of links and would like to dynamically detect clicks on links to file downloads, we have provided updated code below. As before, this code requires the jQuery JavaScript library to be set before the code.

We have updated the code to make it more manageable and easier to extend. In addition, we are using the jQuery on() method for attaching the click event handler to links. Since we are using the on() method you will need to use jQuery v1.7+. If you are using an earlier version of jQuery the .live() method can be used instead.

The primary benefit of using the on() method is performance. Instead of looping through all ‘a’ elements on a page after the page loads (takes processing power on pages with lots of links), we instead listen for any clicks on the ‘a’ elements and invoke our custom JavaScript on the fly.

Again, feel free to customize this code to suite your needs. It can be placed in its own .js file and should be placed in the <head> of your pages. This script automates the following:

  • Tracks file downloads as events for the following extensions: .zip, .exe, dmg, .pdf, .doc, .docx, .xls, .xlsx, .ppt, .pptx, .mp3, .txt, rar, wma, mov, avi, wmv, flv, wav (again feel free to modify the list)
  • Tracks outbound clicks as events if the href value contains http:// or https:// and the domain value doesn’t match the current domain
  • Tracks mailto email clicks
  • Tracks Tel telephone clicks

The script sets download, email and tel link clicks as interaction events while the external site clicks are non-interaction which can be adjusted if desired.

As before, the script will detect if the link is opening in a new window or not and automatically uses setTimeout() for 400ms if you are not. This is to allow time for the hit request to process before taking the user to the new page.

Inline Download & Other External Links Tracking

If you’d rather not use the above method to place a single javascript file on your site and automate the tracking for all link elements, you can use the manual inline approach by tagging each link element individually. The inline approach can be time consuming and is not scalable.

The original syntax for adding the code inline remains the same.

New window/tab
For links that open a new window or tab (such as using target=”_blank” for example) you will want to use the code below:

In current window
For links that open within the same window, replacing the current page, you will want to use the code below:

These type of links require a slight delay to allow time for the hit request to process before taking the user to the new page.

Detailed Download & External Link Reports

After all of your hard work you will have event tracking reports with neatly organized data around file downloads, external link, email link, and telephone link clicks. From these reports you can gauge the usage and usefulness of your file downloads and various links.

By diving into the download category and selecting event label as the primary dimension you are able to see a report on all of the individual files downloaded from your site.

Lastly, since events are associated with the page they were fired on, you are able to apply a secondary dimension of page to find out which page contained the download or external link click that occurred.

If you need assistance with outbound link analysis, setup of this tracking code or any other analytics help, don’t hesitate to comment below or contact our Google Analytics Consulting Experts.

  • Cool! So this would be faster than a plugin like Yoast or Google Analyticator?

    • @adrielmichaud:disqus We prefer the method used in this blog post because it doesn’t loop through all of the ‘a’ link elements on the page to add the onclick attribute. Instead, we listen for any click and at the time of the click perform the event tracking. If you have hundreds of links on your page, this will make a big difference in performance.

      It appears that the Google Analyticator plugin uses the looping method. See

      For Yoast, I believe this is all handled server side as the WordPress page renders. This is a great method.

      Additionally, keep in mind that the above mentioned WP plugins do a great job of doing other things that we didn’t include above. For most users, the plugins mentioned (especially Yoast’s) may work quite well and be very easy to install. For non-WP sites or advanced users who want to customize things further, use ours as a base 🙂

  • Would this work for a link contained inside an iframe that loads from an external site? Specifically, I use an iframe to load an Amazon widget, and would like to be able to track clicks to it.

    • @twitter-14594815:disqus

      No it would not work for that scenario. To the best of my knowledge, the browser views the contents of an iframe as a separate content instance and the parent window is not going to be able to listen for those clicks.

      This StackOverflow post will shed some light on an alternative technique:

      Of course, if you controlled the contents of the iframe, you could call a function in the parent window. That won’t be the case with your Amazon widget. Some things that render in an iframe, like the YouTube player will have an API that allows you to listen for certain events.

  • Excellent post! Thanks
    I was wondering if this would work for password protected pdf files. The way my website is setup is that if a visitor clicks the pdf link, it takes her to the login screen, and only those who are authenticated are able to view/download the pdf. But for the successive files, it won’t ask the password (as the session is active).
    Thank you

    • @twitter-18159257:disqus Great question! One option to handle this would be to put a data attribute or a rel attribute on the link when you know the visitor is not authenticated. Then, you could modify our script to ignore clicks when that attribute exists on the link element.

      There are other ways of course, but those techniques depend on more of the technical details with how this works on your site.

      Hope that helps!

      • Thanks Joe. This sure gives me a hint.

  • Thanks a lot for this. I’m moving from WordPress to a static blog and was looking for a way to track download counts. This is perfect!

    Just one question – in line 30 one of the conditions is ‘!isThisDomain’. This gives me ‘Uncaught ReferenceError: isThisDomain is not defined’ in Chrome’s console. What would be the best way to set the value of isThisDomain?

    • Got it – I found that adding

      var isThisDomain = ( ==;

      after line 7 sorted it.

      Is there a better way?

      • @se0siris:disqus Thanks so much for pointing this out. We’ve updated the post to correct this code issue. Please use the latest version.

  • Naters

    Thanks! but where do I find the analytic information? I’ve looked all through my Google analytics and I don’t see where it would be. I have a Joomla! site and I’m using the inline “onclick”.

    • @disqus_6URiQgcbiq:disqus This data would be under Events. Content > Events > Top Events

      • Naters

        Ah! Thank you!

      • Kevin Harter

        Thank you so much for sharing this! I have implemented the code but don’t see any Events in my GA account. When I click on a download, it should show as an Event in the Real-Time Events, right?

  • bettye

    Can anyone refer me to a site that gives simple, easy-to-follow
    instructions on how to track downloads on my website? Everything I’ve
    seen is either jibberish, requires a degree from MIT, or is user
    unfriendly. I am offering free downloads on my site of files in PDF,
    MOBI, and EPUB formats, and I can’t find ANY information out that that I
    can understand.

    • @google-e15425ff3e361ab6523174eacce9b9a3:disqus If you are using WordPress as your platform, you may want to check out Yoast’s plugin: This just requires a simple install and then you can configure the options via a user-interface.

      The solution we’ve provided here is certainly tailored towards a technical audience; though we’ve greatly simplified things so that users with minimal technical experience can use what we’ve provided. Typically, you can forward this blog post to the person/company that built your website and they can get it added.

      Another option is to work with Blast directly and we can provide more hands-on support to get this implemented correctly.

      Hope that helps!

  • I’ve tried to implement this with no luck. I have JQuery first, your script next, then the GA all in the . Manual tagging works fine, but the script doesn’t seem to be “listening” for the clicks. Pageview data passes, but not click data according to GA Debugger. I know this isn’t support per se, but your implementation is pretty straight forward I thought.

    • Ryan Chase

      @twitter-9402882:disqus If you provide me with a link I can take a quick look at your site to see if anything stands out. It sounds like something is interfering with the click event handler.


    • Hy Ryan – the site is Thanks for looking into this.

  • Can anyone help? I entered the script but after 4 days I still get no results.

    • Ryan Chase

      Ernie Natera I would recommend changing the following:
      _gaq.push(['_trackEvent', 'Download', 'Pdf', '20130301',, false]);

      _gaq.push(['_trackEvent', 'Download', 'Pdf', '20130301']);

      Since you didn’t specify an event value before the non-interaction flag it is breaking. Also, it is not necessary to specify false for the non-interaction flag since it is set to false by default. You should also add taget=”_blank” for this link to follow the format of the others.

      For the other links you will want to remove � from before and after the _gaq.push call to get them to work properly.


  • *Great* info; thanks so much for sharing!

  • Emily Graham

    Thanks for the useful blogs, really good stuff. One question though – should you be able to see the results instantly, i.e. you add the code (inline download) and download the file – would this appear instantly in Google Analytics Events?

    • I have the same question. I’m looking in the Real-Time>Events beta as well as Content>Events and there’s nothing yet. My site is

      • Ryan Chase

        @emily_graham:disqus @twitter-15922572:disqus

        If the code is implemented properly you should see the events appear in the Real-Time > Events report right away. The events should show up in the normal Content > Events report within 24 hours, provided the code has been implemented properly.

        Michael, I checked your site and the code appears to be implemented properly. I was able to see that the events were being fired when clicking on the file download links.


        • Thanks! I found a bad reference to my script in a nested HTML. BAM! Beautiful!

  • Hello Ryan,

    Thanks for the good and clear post. I’m only tracking 2 or 3 PDF downloads so I opted for tagging each link individually. I copy and pasted the code but there’s nothing coming up in Analytics.

    Any idea why this would not be working? My site is

    Thanks in advance!


  • Ryan Chase


    I took a look and It appears that some javascript errors further up on the page are causing the script not to work. If you check your javascript console you should see the specific errors that need to be fixed. Once you get those resolved the click tracking should start working.


  • disqus_ORYseND2Xx

    Will the inline script work if the PDF is being called with a ‘’ command rather than a simple href=? Can I simply add the inline code after the, separated with a semicolon?

    • Ryan Chase

      @disqus_ORYseND2Xx:disqus The inline code will work by adding it after the command.

  • Andrew Hawken


    Thats really useful. However, if you have content generated dynamically, the ‘on’ hook below, will add tracking to content created after this code has run.

    jQuery(document).on(‘click’,’a’ ,function (event) {

    • Ryan Chase

      @Andrew Hawken Thanks for the tip! You are correct in that you will have to adjust the click event to the format you provided in order to detect clicks on Ajax loaded content.

  • Ivan

    Thanks for this code. I can’t get it to work though. I implemented the previous code before I saw that it was updated. I have the code in its own .js file.

    • Ryan Chase

      @Ivan It looks like you will need to move your tracking.js file below the jQuery reference in order to get it to work.

  • Hi,

    Great code, thanks for the post, but I’ve noticed an error. For domains that have more than one suffix (e.g., or, the isThisDomain variable only picks up the suffix, and not the domain name. That means any external links with the same double suffix will be missed (any from UK to UK basically). I’ve modified it to look for if it matches my domain, and it now works fine. I know it’s a lot of work to correct the code for this, but it might be worth adding a note for that.


    • emarbee

      Hi James
      I have exactly the same problem. Could you please give me advice where and what I need to change in the script?
      Thanks very much

    • Nick S

      Hi James,
      I’m having the same problem. I manage a site with suffix and external links to other sites with suffixes are not recorded as external links. Just wondered if you could share your code for the isThisDomain variable that takes account of domains that have more than one suffix.

  • Ryan Chase

    @Louis I took a look at your site and the event is being fired. There might be a filter applied to your profile that is preventing the data from coming through. Are you still not seeing any data for the pdf clicks?

  • I’be been looking to replace an old tracking perl script for years,

    Unfortunately, it fails for internal links that have the full absolute URL. It seems to add a slash before “http”. I use subdomains and sometimes I need to have links that way. Would there be an easy fix for this?

    • I’d be inmensely grateful if you could find a fix for this

      • Paul Lear

        Hi Martin,

        Feel free to paste a snippet of what your HTML code looks like with the extra slash rendered. It might be as simple as adjusting the RegEx you need to use in the tracking code.


  • Where exactly am I supposed to go in the Google Analytics to find the tracked PDFs? Please give me the exact menu items I have to click into. “By diving into the download category and selecting event label as the primary dimension” is too vague for me…… thanks.

    • Ryan Chase

      Hi Grant,

      Within your GA account go to Content > Events > Top Events. That report will show the Event data by categories. The pdf downloads would be under the ‘download’ category. If you drill down into the ‘download’ category you should see the action of ‘click-pdf’. If you drill down into ‘click-pdf’ you should get a list of your pdf downloads and the related data.

      Hope that helps.

      • Ryan, thanks but it’s not working. I keep trying to post the code that I’m using for it… but the moderator won’t approve my message. Could I email you the code instead?

    • Hello Grant,

      On the left side menu, go to Behavior > Events > Overview or Top Events. Here you’ll see a list of Categories coming in from the tracking code. If you implemented the code exactly as it appears above, you’ll see a category called “download”, click on that and you’ll see a new list with file extensions. Click on “pdf” to get a list of the pdf document links.

  • Francisco

    Hi Ryan,

    I found a problem in the script for my use. If somebody right-clicks and save as the pdf links on my website, they are not counted with your script.

    I fixed this by changing the ‘click’ event by ‘mousedown’. That way, I capture both left-clicks and right-clicks.

    The only inconvenient is that right-clicks do not always mean downloads.

    Is there any way to specifically capture right-click, save as?

    Thank you!!

    • @disqus_0XEtDdvna6:disqus unfortunately not that we know of. Once the user clicks the right mouse button, it’s up to the operating system to capture what happens next. One thing you should think about though, is that not many people would right click on a .pdf document with an intent other than saving the doc so it’s a fairly good guess to say that right clicks are also downloads. I would think the 3 most “alternate” options with a right click would be Open ( including open in new tab/window ), Save and Print. Although you cannot print directly from the link, some users may not know this and try it. You could perform a print check. Look up onbeforeprint to know if the print dialog box has been activated – this would help cancel out that option from the right clicks. An Open or Save of the document is essentially the same thing since they’re most likely to save the document after opening it.

      I hope that helps!

  • Jean Paul

    Thanks Ryan. Do you know if this works for tracking clicks on outbound links with the new Universal Analytics script? If so, how does one do this?

    • @disqus_lxftEOH6aB:disqus Since Universal Analytics uses a different syntax, you would need to replace all of the _gaq.push methods with the appropriate UA syntax. Aside from that, nothing else would need to be changed. The script only contains one call to the _gaq so it’s fairly simple, however, if you’re using any inline calls, you’ll need to replace those as well.

      • Eric Erlebacher

        Hey Olaf, thanks for the help. I actually tried replacing _gaq.push with ga(‘send’… (the analytics.js syntax), and I get the following error in the debug console:

        Command ignored. Unknown target: undefined

        This could also be confounded by the fact that we are running both async and UA on our site. I noticed when attempting the original version, the UA-ID was XXXXX-X

        Thanks again!

        • Hello Eric,

          There’s no problem with running Classic and UA at the same time, you just need to make sure you have the snippets for both and that the settings are correct so that Classic ‘_set’s the account and UA ‘create’s the account.

          If you post a link I could take a quick look for you –

  • Cade

    Thanks, however this does not appear to work with Google Tag Manager?

    • confirm, it doesn’t work, either placing in the head or as a custom html tag. i want to try changing it using datalayer instead of the ‘old’ ga method… but yes, the concept behind such solution is great and it’s really useful as for gtm there’s nothing made (yet)

      • update: it works also on GTM, with a little adaption…

        • Cade

          Could you please share your adaption to get it to work?

        • Mike Betts

          Yes, please share this adaptation with us.

        • Mike Betts

          I would like to get the adaptation made as well…

    • @disqus_7WXkQViOqq:disqus There is no problem implementing this via Google Tag manager. The only issue is that if you’re using the Google Analytics Tag template, you’ll have to namespace the tracker in both the GA tag and within the script for it to work properly. This assuming that there is no problem with jQuery and/or that jQuery is version 1.7 or higher as well.

  • Harmeet Gabha

    I have this sort of tracking working on my site but I want to display the number of events count on the page. For example I have a download button on a page which is tracked in Analytics but on my same blog page, i want to display a counter to visitors that this item has been downloaded X number of time. Is there such options using Analytics to retrieve the value, in addition to push the event counter?

    Any help would be appreciated.

    • Paul Lear

      Great question, and possibly a difficult road to travel to get to what you want. Google does make available a data export API to extract data from your analytics account. This would require some pretty heavy lifting to make it happen if you were starting from scratch. I would first look into available plugins for your CMS system to see if any cool download counting widgets already exist before investing too much time.

      • Harmeet Gabha

        Thanks Paul, I’m now using WP Download Monitor to track the count. Also modified one of its templates to push data into Google Analytics dynamically.

  • Mia Gelles

    Thank you so much for this post. I’ve been looking for a solution for months and this works perfectly!

  • Gael

    Hi Joe,
    Thanks a lot for this great post. I have one question to be sure it could help me.
    I would like to be able to know each month :
    – Number of downloaded of “myfile.exe”
    – Number of downloaded of “myfile.exe” from websiteA
    – Number of downloaded of “myfile.exe” from websiteB
    – Number of downloaded of “myfile.exe” from websiteC

    I dont have access to websiteA, websiteB, websiteC etc. They all pointed directly to mysite/myfile.exe. So, in that case, would it be possible to get those informations using your code ? (or would I ‘just’ have the total number of downloaded ? )
    Thank you

    • Paul Lear

      Hi Gael,

      Unfortunately the code we developed and other similar solutions only track upon the “click” event, and if that event happens on a website you don’t control, we lose the ability to track it.

      As it sounds today, you won’t even get a count of file downloads as Google does not track file downloads, they track clicks.

      Knowing this, the right solution might be to wrap each download file in an individual page, where on that page you can include a redirect trigger script to essentially wait a few seconds (long enough to trigger the standard GA code to log your page view) then redirect the browser to the actual download file. This only counts the downloads from your site so you will need to contact the web masters who are referencing the files directly.

      Hope this helps.


  • Paul Lear

    Great suggestion!

  • Paul Lear

    Hi David,

    Currently your site uses a local reference to jQuery 1.6. You should replace the library with a 1.7 or greater version, however it also sounds like there may be additional issues if the inline version didn’t work either. It may be related to another javascript conflict if it continues to not track properly for you.

  • Paul Lear

    I took a quick look at your site and it may be that you’ve moved on from this approach as I didn’t see the tracking code in place, but when you are ready to try again, be sure to include the jQuery library reference in your section before the call to the tracking code.


  • Paul Lear

    Nice solution! Sounds like the key change was to ensure the consistent extraction of the isThisDomain variable. Thanks for the follow-up!

    • Peter Crackenberg

      Yep, I think all I ended up doing was adding one line and slightly changing how isThisDomain got calculated.

      Other than that, it’s worked great for us, thanks for the awesome tool!

  • Paul Lear

    Hi James,

    I took a quick look and didn’t see the inline test links in your footer, though I found your post on PyMOL B-factor visualisation immensely fun. Try adding this in your footer:

    %lt;a onclick=”var that=this;_gaq.push([‘_trackEvent’,’Download’,’PyMOL’,this.href]);setTimeout(function(){location.href=that.href;},400);return false;” href=””%gt;PyMOL with the blue_white_red palette%lt;/a%gt;

    • James Tolchard

      Hi Ryan,

      Sorry – I forgot to update my post. I fixed my problem. It turns out I was being stupid and trying to test the links in my site myself – whilst having “DoNotTrackMe” enabled in chrome. Turning this off instantly fixed my problem.

      Thanks for your reply though!

  • Tracey

    Thanks so much for this code! But, I have a question. I manage a large intranet site and use events for tracking things that happen on the site that I would like to know about like clicks on certain buttons, certain menu items, etc. I was using the inline code for tracking links to PDF documents but using the trackPageview instead of events. Is there any reason you track with events instead of just pageviews? Thanks!

    • Hello Tracey,

      You bring up a great point. Sometimes you want to track an action and report based on how many times it was performed. Additionally, you want to be able to pass it additional values so that you can identify the type of action taken. For this reason you want to use Events since you have 3 variable to populate, Category, Action, label. For example, with tracking links to PDF docs, you can set a Category to “download”, Action to “pdf” and label to the actual link of the pdf. Likewise other file types would fall under different Actions and would also carry the link. However, this doesn’t treat the “PDF” view as a pageview and will not allow for you to see it as a goal path or part of funnel. Perhaps your goal is the “PDF” download and you want a funnel leading up to it, in this case you MUST do it using a virtual pageview and you can pass the url of the file as the “page” value.

      So as you can see, it all depends on what you’re trying to do.

  • @disqus_kCZ2kwh4wn:disqus I took a look at your site but did not find this script implemented. I imagine you must have removed at some point in time. However, I did notice that you have the Universal Analytics snippet. Please be aware that the download tracking script as outlined above is for use with Classic Google Analytics. Universal Analytics no longer uses the _gaq object and has a different syntax so you would need to replace all of the _gaq.push calls with the appropriate UA method calls.

  • Mangara

    The script as is breaks middle-click behaviour for external links in Chrome. Instead of opening in a new tab, they get a time-out and open in the original window.

    A possible fix is checking for the left mouse button before setting the time-out:
    if (event.which == 1 && (…)) { /* Set time-out */ }

    • Hello Mangara, you do bring up a good point. I went and dished out an old microsoft mouse with that middle button but I wasn’t able to reproduce the problem you’re describing, do you happen to have a link I could take a look at?

      • Mangara

        Hi Olaf, I compressed my site to the smallest example that still exhibited the behaviour:

        Using the current version of Chrome (v 28) on Windows 7, when I click the link with the scroll-wheel or when I Ctrl-click it, it opens in the same tab instead of a new tab. Right-click and open in a new tab does work as expected. Both Firefox and IE work correctly (i.e. do not have the bug). It seems to be linked to and

        • Thank you Mangara, I was able to take a look. Something odd happens however. When I go to your link and I middle click, the link opens on the same tab, so then I downloaded the page Source and opened the file from my desktop. I middle clicked and the link opened on a new tab. Could you try that yourself? open it locally or at least with a non-aliased url?

          • Mangara

            Did you download the ga.js file as well? It includes the tracking code. I first noticed the behaviour when building a site locally, so I can confirm that it still happens.

  • Will Belden

    Would LOVE to see an update to this, based on the Google UNIVERSAL analytics. Because with the syntax like this (provided by Google for UA):
    ga(‘create’, ‘UA-327146……
    ga(‘send’, ‘pageview’);

    The code above doesn’t work. Clearly I’m not smart enough to rewrite the “push” line at the end of this suggested code to what it SHOULD be. Bear in mind that “_gaq” isn’t a valid variable anymore, it’s just “ga”.

    Would love to see an update, guys, awesome work!

    • Try replacing the _gaq.push line with this;

      ga('send', 'event', elEv.category.toLowerCase(), elEv.action.toLowerCase(), elEv.label.toLowerCase(), elEv.value, elEv.non_i);

      that *should* add send the events with the new Universal Analytics.

      • Will Belden

        Seems to be working! No errors at least. Haven’t actually checked the Analytics site for it.

        • coolio, I did it on my own site this afternoon and just checked GA, there’s two different events logged so it works on mine. thus far.

          hope it works for u 2, take care.

          • Thanks for helping out Matt!

            We’ve fallen a little behind on some replies, it’s hard to keep up but yeah, if you follow the UA syntax, you just need to pass the values into the new syntax in the same way. I’ll see what I can do about updating this post to include a UA version –

      • drgs100

        Thanks for this, been trying it out and seems to be working. No need to test if it will balls up the manual Event Tracking currently running…

  • Olivier

    Thanks a lot, it works well !
    I just have problems with double clicks. When a user double clicks on a link, the click event is fired twice (so two events sent to Google Analytics) and the document is downloaded twice. Any solution for that ?

    • Hello Olivier,

      I had this problem once, what I did is I have the click event increment a variable that is initially set to zero and then check the value prior to firing the GA event. This allows for the first click to trigger but then the second will have incremented the value and be cancelled out.

  • Angela Lindsey

    Can this be done via Google Tag Manager too?

    • Hello Angela,

      Yes, this can be done via GTM. However, the implementation can get a bit tricky unless you’re doing all of your GA code via a customHTML tag in GTM.

      As of late, they’ve come out with click events in GTM and this can be handled equally as easy within GTM. However, the current setup would require you to setup a separate event tag for each of the event types you’re trying to track and each would need a rule/macro to go with it.

      I’ve developed a method of having a single event with macro based dynamic values that is fired from within a customHTML tag and allow you to fire multiple events, pass custom values and all with one Event tag. I’ll be posting a blog on that soon, email me if you want a peek. 🙂

  • Dany Giguere

    Hi Ryan. Ignore the message I sent you on Monday. I figured it out. Thanks for sharing !!!

  • Ben McCarty

    Thank you SO much for this incredible post, Ryan. I’ve run into an issue when implementing this via Google Tag Manager and I was hoping you (or another reader) would have a suggestion.

    When I debug the Events using GA Debug for Chrome, I see the Events firing but with an Account ID of UA-XXXXX-X (see attached screenshot). Any ideas why this might be happening and how to fix?

    Thanks in advance!

    • Hello Ben,

      Please make sure that the GA tag you’re using is for Classic and not Universal Analytics otherwise this event will not track properly. Aside from that, I’ve had instances where GTM namespaces the tracker so that when you fire a _trackEvent, it actually has no account associated with it. The namespace may be t0._trackEvent and thus you’d need to use that namespace throught out your code. The best way to ensure that your trackers are all synched is to namespace it yourself via the template UI, you can pas a “a” value to the name and then ensure all your GA code within customHTML tags use that namespace as such:

      _gaq.push([‘a.trackEvent’, ‘cat’, ‘act’, ‘lbl’ …

  • Altabear

    Very nice post! We have a bunch of sites with contact forms. When someone fills one it, they’re redirected temporarily to a central asp page which determines where they came from, what they’re doing, grabs the lead information and then redirects back to the site they came from and it’s “thanks” page.

    We are in control of the sites and the one central asp page that they all connect to.

    Is there a preferred way to use your code for that? They are never actually downloading a file of any kind.

    Thanks in Advance

    • Hello Altabear,

      There are two ways to do this. You can track the form submittal and pass the information to Google just prior to the DOM being dumped, or you can place some code on that central asp page that would pass the data to Google just before the redirect. It all depends on how you want to do it, the first scenario may require a delay, the second will require generating a response for the http request –

      A third way is to set a cookie an modify the values as the user clicks on the items you want to track. When the user submits, the latest version of the cookie will remain. Then you set code on the next page that checks for the cookie, parses it, fires tracking code as necessary prior to the initial pageview for the new page and then expires the cookie. This method has come in handy when forms have server side validation which makes it difficult sometimes to differentiate a form page from a submitted form page, from an error page after form submittal.

  • Hello Simon,

    Thank you for bringing this point up.

    While the TOS states that you will not collect any PII, the email address that is being tracked with the script is the email address that is posted on the website. The fact that it’s published by the website owner disqualifies it as PII.

    If you had a form box where the user inputs their email address and submits, as is with most subscription widgets, then you need to make sure you don’t capture that and send it to GA since in that case the email address IS considered PII.

  • Awesome! It takes only 10 seconds to setup and works perfectly, thanks a lot!!

  • nsherif

    would this hurt SEO in anyway? would the robot be still able to read and list links in my page?

  • Manish

    Waste of time to post here, did not recieve any response from here even my question was not posted by admin very annoying!! will never advice anyone to visit here.. Google forums is best place to get your query answer.. Bingo to Google

    • @disqus_jmO8gms41s:disqus As you can see, there are currently over 107 comments on this blog post. Just about all of them have a response from us. I don’t see a question from you on this thread… I do agree with you that Google help forums is the best place to ask general questions about GA. If you have a question about this free script we’ve provided, please let us know and we’ll do our best to answer it or point you in the right direction.

  • Bunnyslippers

    Works beautifully. Thank you!

  • Brett Burridge

    Thanks that looks a really awesome piece of code!

  • Art Thompson, Jr.

    Thanks for updating this, Ryan. Quick question, does this work as-is with the newer Universal Analytics embed code?

    • Art Thompson, Jr.

      Anyone? Anyone?

  • Mike

    How long should it take for event data to start showing up in google analytics after the above code has been added?

  • Josh C

    I have been using this for a bit, but noticed it breaks my lightbox pop-up script. Basically it loads youtube videos, pictures and audio files in a pop-up on the page when the link has rel=”lightbox” associated with it. Any ideas on how to add this exception?

  • Mat Leduc

    What can I input if I only want mail to and telephone tracking??

    Thank you very much for your help ; )

  • Excellent post! Thanks

  • Samantha

    Really interesting post. Do you have any idea if this can be used in a webpart on a Sharepoint website? I am familiar with adding jquery to a sharepoint html webpart so I may give this a go. Just curious if anyone has experience with this. Thank you.

  • Sarah

    Hi all, I came across this and recently used parts of the JQuery code to use on a project. I would recommend that instead of using a regex to detect external urls to use the filter method in JQuery:

    var anchor = $(‘a’);

    var external = anchor.filter(function() {
    return this.hostname && this.hostname !== location.hostname;

    This is a much more reliable method. Using regex properly to cover all URL scenarios is a bit more difficult and as many of you in the comments found, there were errors.


  • Ron Wright

    I implemented this code about a year ago – good stuff. After switching to Universal code, I noticed it doesn’t work anymore. Does this code work for anyone else using Universal Analytics code?

  • L_X_L

    This is excellent script that tracks everything, works out of the box! Google’s pushing the Tag Manager now – should we be switching to the Tag Manager and removing this script?

  • Crimson Diva

    Thanks! Do I add this code below my standard Google universal tracking code?

  • Div & Conquer

    Hi, I’ve been using this code a while but took it off back in March. At almost the exact same time my website traffic seemed to fall. It seems the code was attaching itself to internal links. Could it be possible GA has been counting them as extra traffic?

  • Wouter van der Heijden

    Thank you! Is there already a Universal Analytics version available?

    I changed

    _gaq.push([‘_trackEvent’, elEv.category.toLowerCase(), elEv.action.toLowerCase(), elEv.label.toLowerCase(), elEv.value, elEv.non_i]);


    ga(‘send’, { ‘hitType’: ‘event’, ‘eventCategory’: elEv.category.toLowerCase(), ‘eventAction’: elEv.category.toLowerCase(), ‘eventLabel’: elEv.label.toLowerCase(), ‘eventValue’: elEv.value, ‘nonInteraction’: elEv.non_i });


    elEv.non_i=false / true into elEv.non_i=0 / 1

    Would that be sufficient?

    • Daniel Maier

      I changed to:

      ga(‘send’, ‘event’, elEv.category.toLowerCase(), elEv.action.toLowerCase(), elEv.label.toLowerCase(), elEv.value, elEv.non_i, {‘nonInteraction’: 1});

      What do you mean with:

      elEv.non_i=false / true into elEv.non_i=0 / 1

  • Daniel Maier

    elEv.value = 0, elEv.non_i = false;

    is triggering:

    Expected an assignment or function call and instead saw an expression.

    Is it necessary to set elEv.value = 0?

    Thanks for the great code!

    • Daniel Maier

      Changed this:

      var elEv = []; elEv.value=0, elEv.non_i=false;

      To this:

      var elEv = [];
      elEv.value = 0; <<< added semi-colon
      elEv.non_i = 0; <<< replaced with zero (for Universal Tracking, instead of 'false' – shooting a little in the dark here…)

      Using Universal Analytics and it seem to be working.

      ga('send', 'event', elEv.category.toLowerCase(), elEv.action.toLowerCase(), elEv.label.toLowerCase(), elEv.value, {'nonInteraction': elEv.non_i});

  • Chris

    Hi there.

    Really looking forward to using your code, however im running into a quite weird problem. When copying the code into a .js file (which i just call downloads.js) and add it on my homepage, i get following error in Google developer tools: “Uncaught SyntaxError: Unexpected token <".

    What could be the problem here?

  • Thanks for this guys, I wonder if it would a) to track downloads of podcast files that are syndicated through iTunes, and b) work with Squarespace (and how do we add the jquery in a Squarespace site)?
    The SS stats for podcasts leaves a bit to be desired, so it would be good to work out how many podcast episodes are being downloaded.

  • Daniel Maier

    If you are using Responsive Lightbox plugin this code will crash with it. You can use the following to bypass the Responsive Lightbox:

    $(‘a’).on(‘click’, function() {
    // Place right after the onclick function.
    if ($(this).data(‘rel’) && $(this).data(‘rel’).indexOf(‘lightbox’) > -1) {

  • Daniel Maier

    Here’s my entire code, if anybody needs it:

    if (typeof jQuery !== ‘undefined’) {

    jQuery(document).ready(function($) {

    var filetypes = /.(asx|avi|doc.*|flv|gif|jpg|jpeg|m3u8|mov|mp3|mp4|mpg|mpeg|pdf|pls|png|pps.*|ppt.*|ram|rar|txt|wav|wma|wmv|xls.*|zip)$/i;

    var baseHref = ”;

    if ($(‘base’).attr(‘href’) !== undefined) { baseHref = $(‘base’).attr(‘href’); }

    $(‘a’).on(‘click’, function() {

    // The code below interfers with the responsive lightbox code

    if ($(this).data(‘rel’) && $(this).data(‘rel’).indexOf(‘lightbox’) > -1) {



    var el = $(this);

    var track = true;

    var href = (typeof(el.attr(‘href’)) !== ‘undefined’) ? el.attr(‘href’) :””;

    var isThisDomain = href.match(document.domain.split(‘.’).reverse()[1] + ‘.’ + document.domain.split(‘.’).reverse()[0]);

    if (!href.match(/^javascript:/i)) {

    var elEv = [];

    elEv.value = 0;

    elEv.non_i = 0;

    if (href.match(/^mailto:/i)) {

    elEv.category = “email”;

    elEv.action = “click”;

    elEv.label = href.replace(/^mailto:/i, ”);

    elEv.loc = href;


    else if (href.match(filetypes)) {

    var extension = (/[.]/.exec(href)) ? /[^.]+$/.exec(href) : undefined;

    elEv.category = “download”;

    elEv.action = “click-” + extension[0];

    elEv.label = href.replace(/ /g,”-“);

    elEv.loc = baseHref + href;


    else if (href.match(/^https?:/i) && !isThisDomain) {

    elEv.category = “external”;

    elEv.action = “click”;

    elEv.label = href.replace(/^https?:///i, ”);

    elEv.non_i = 1;

    elEv.loc = href;


    else if (href.match(/^tel:/i)) {

    elEv.category = “telephone”;

    elEv.action = “click”;

    elEv.label = href.replace(/^tel:/i, ”);

    elEv.loc = href;


    else { track = false; }

    if (track) {

    ga(‘send’, ‘event’, elEv.category.toLowerCase(), elEv.action.toLowerCase(), elEv.label, elEv.value, {‘nonInteraction’: elEv.non_i});

    if (el.attr(‘target’) === undefined || el.attr(‘target’).toLowerCase() !== ‘_blank’) {

    setTimeout(function() { location.href = elEv.loc; }, 400);

    return false;







  • Amiad

    I convert your script to ga.
    I replaced the line:
    _gaq.push(['_trackEvent', elEv.category.toLowerCase(), elEv.action.toLowerCase(), elEv.label.toLowerCase(), elEv.value, elEv.non_i]);

    ga('send', 'event', elEv.category.toLowerCase(), elEv.action.toLowerCase(), elEv.label.toLowerCase(), elEv.value);

  • Hi!
    Is there any way You can see which logged in user downloaded which files?

  • Daniel Maier

    I started getting the following error when I click on a link on my website:

    Uncaught TypeError: ga is not a function

    Is anyone experiencing the same?

  • vikram

    Need some help here 🙂
    Great article! I used the inline method to track the download of my eBook (EPUB format). I’m able to see users on my website, but I’m not able to get the download count.
    Any help would be appreciated!

  • Yuriy Eduardovich Tereshchenko

    Hi! Thank you very much for your work. Please help me to set it up for my situation because it is not working. My download link is not directly to the zip file but to the php file that redirects to the zip file (this php file has simple count function). So actually I need GoogleAn to: track clicks to this php file OR track downloads inside this php file. How can this be done? Thank you for any suggestions.

    • Hello Yuriy,

      You would need to add a section for your php type downloads.

      else if ( ( /nameofphpfile.php/gi).test(href) ) {
      elEv.category = “download”;
      elEv.action = “php”;
      elEv.label = href.replace(/ /g,”-“);
      elEv.loc = baseHref + href; // use this if your link opens on the same window

    • Daniel Maier

      Hi Yuriy,

      This is what I have to track events such as several file types, email links, external links and telephone links:


      if (typeof jQuery !== ‘undefined’) {

      jQuery(document).ready(function() {

      var filetypes = /.(asx|avi|doc.*|flv|gif|jpg|jpeg|m3u8|mov|mp3|mp4|mpg|mpeg|pdf|pls|png|pps.*|ppt.*|ram|rar|txt|wav|wma|wmv|xls.*|zip)$/i;

      var baseHref = ”;

      if (jQuery(‘base’).attr(‘href’) !== undefined) { baseHref = jQuery(‘base’).attr(‘href’); }

      var hrefRedirect = ”;

      jQuery(‘body’).on(‘click’, ‘a’, function() {

      var el = jQuery(this);

      var track = true;

      var href = (typeof(el.attr(‘href’)) !== ‘undefined’ ) ? el.attr(‘href’) : ”;

      var isThisDomain = href.match(document.domain.split(‘.’).reverse()[1] + ‘.’ + document.domain.split(‘.’).reverse()[0]);

      if (!href.match(/^javascript:/i)) {

      var elEv = [];

      elEv.value = 0;

      elEv.non_i = false;

      if (href.match(/^mailto:/i)) {

      elEv.category = ’email’;

      elEv.action = ‘click’;

      elEv.label = href.replace(/^mailto:/i, ”);

      elEv.loc = href;


      else if (href.match(filetypes)) {

      var extension = (/[.]/.exec(href)) ? /[^.]+$/.exec(href) : undefined;

      elEv.category = ‘download’;

      elEv.action = ‘click-‘ + extension[0];

      elEv.label = href.replace(/ /g,’-‘);

      elEv.loc = baseHref + href;


      else if (href.match(/^https?:/i) && !isThisDomain) {

      elEv.category = ‘external’;

      elEv.action = ‘click’;

      elEv.label = href.replace(/^https?:///i, ”);

      elEv.non_i = true;

      elEv.loc = href;


      else if (href.match(/^tel:/i)) {

      elEv.category = ‘telephone’;

      elEv.action = ‘click’;

      elEv.label = href.replace(/^tel:/i, ”);

      elEv.loc = href;


      else { track = false; }

      if (track) {

      var ret = true;

      if((elEv.category === ‘external’ || elEv.category === ‘download’) && (el.attr(‘target’) === undefined || el.attr(‘target’).toLowerCase() !== ‘_blank’) ) {

      hrefRedirect = elEv.loc;

      ga(‘send’,’event’, elEv.category.toLowerCase(),elEv.action.toLowerCase(),elEv.label.toLowerCase(),elEv.value,{

      ‘nonInteraction’: elEv.non_i,

      ‘hitCallback’: gaHitCallbackHandler


      ret = false;


      else {

      ga(‘send’,’event’, elEv.category.toLowerCase(),elEv.action.toLowerCase(),elEv.label.toLowerCase(),elEv.value,{

      ‘nonInteraction’: elEv.non_i



      return ret;




      gaHitCallbackHandler = function() {

      window.location.href = hrefRedirect;




  • Curran

    Very cool. I am relatively new to this so please bear with me…
    I am using WordPress as my platform and I have a few questions:

    Where do I insert the code? I read that it can be placed in its own .js file but I also read that it should be in the of all pages. Can I paste the code into its own, new .js file in the admin Editor? Or does it need to be within every single page of the site?

    You mention that the code requires the jQuery JavaScript library to be set before the code. When I clicked on your link, I was redirected to the jQuery library page. What part of this needs to be set before the code? Do I download the library and it will provide me with code? Is it all fairly intuitive and I’m just making things more difficult/confusing for myself??
    I hope someone can help!

  • Andreas Zimmermann

    Hi Ryan. I was able to add this code to our sharepoint site, however I am not able to view the results anywhere within GA – I’ve tried creating a custom report, and I have read through comments stating where the results should be found (Events), but I have not been able to locate the results anywhere. Is this code old enough now that it doesn’t work with the current version of GA?

  • johnhuh

    Awesome post! Thanks for posting the awesome tip!
    I’ve read this post 4years ago, but still am reviewing back again since I bookmarked it. But one question!
    Is there any way that we can track the file by adding the code on the file itself?
    The code on here is for the website’s download link button. Isn’t it?
    I’m wondering whether if we can add the tracking code in MP3 file itself.
    So I’d like to see how well my song is being listened by the worldwide people when it’s released..

  • Jillaine Smith

    For those of us who are not coders or programmers, but use, say Muse (as long as we can) to create and maintain web sites, a few questions:

    1. Re: “this code requires the jQuery JavaScript library to be set before the code.” – what does that mean for someone like me who uses Muse to maintain our web site?

    2. Similarly, how do we create a “.js” file if we use something like Muse?

    3. Does the “Dynamic” code (first option) need to be placed (in the … section of every page of our web site? Or just the home page?

    ADDED: 3b. Do we just paste the code as it is above, or do some elements have to be edited to work on OUR web site?

    4. How do we access the analytics related to downloaded files? Or does this somehow get incorporated into our Google Analytics account we have set up?


    • @disqus_3xmbsWSYQ5:disqus I’d recommend posting these questions on a Muse-specific forum/community. There are so many platforms out there and unfortunately, I don’t have any experience with Muse to advise on this topic. Most content management systems/platforms that are hosted on a webserver that you pay for should allow for javascript files (.js files) to be placed on a server. Keep in mind that this blog post is quite old now and the more current method of achieving what is described in this blog post would be to use a Tag Management System, such as GTM (Google Tag Manager).

      • Jillaine Smith

        Thank you, Joe. (Your site came up in first set of results when googling how to track downloads…) We’ll go check out Google Tag Manager

  • Elena Politi

    Hi, I am a beginner with analytics, but I need to implement a solution like yours, hence I need some advise from you. I am using wordpress and I tried to add the code to my web site. I saved it as a single js file in my child theme and registered + enqueued through functions.php. I can see it loaded, but I don’t see the script in my page (don’t know if it should be visible or not). I actually created the event on analytics (2 types, unless there’s the possibility of dealing with one only) as you can see from teh images attached. It doesn’t seem to work though. Any suggestions?
    Thanks very much!

Ryan Chase
About the Author

Ryan is a Senior Analytics Consultant at Blast Analytics & Marketing. He is passionate about helping businesses improve their usage of data to make better decisions. He has experience across industries and analytics platforms to help set and meet long term business goals.

Connect with Ryan on LinkedIn. Ryan Chase has written on the Web Analytics Blog.

HIPAA and Analytics White Paper CTA

Featured White Paper

Healthcare Analytics and HIPAA: Ways to Minimize Risk and Ensure Compliance

The rise in digital data and analytics adds complexity and risk for healthcare organizations. Those that don’t comply with data privacy requirements, including Health Insurance Portability and Accountability Act (HIPAA), could face heavy fines, civil action lawsuits, and even criminal charges. Not to mention loss of patient trust.

Download the White Paper

Ready To Do More With Your Data?

If you have questions or you’re ready to discuss how Blast can help you EVOLVE your organization, talk to an Analytics Consultant today.

Call 1 (888) 252-7866 or contact us below.