O'Reilly

Track AJAX Link Clicks Using Google Analytics

By on  

4/22/2011: This blog post was completely rewritten to describe page tracking with Analytics' asynchronous loading method.

With more and more websites becoming completely AJAX-driven, the typical "do this every time a page loads" strategy isn't always enough. This is especially try if you're using Google Analytics or other analytics tracking software. Google is, of course, forward-thinking so they've provided a way to easily track page views of AJAX requests.

The Google Analytics JavaScript

The current standard for loading Google Analytics is the asynchronous method:

var _gaq=[["_setAccount","UA-#######-#"],["_trackPageview"]];
(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];g.async=1;
g.src=("https:"==location.protocol?"//ssl":"//www")+".google-analytics.com/ga.js";
s.parentNode.insertBefore(g,s)}(document,"script"));

That bit tracks the initial page load but not subsequent AJAX calls. Any time you want to track a page load, place add the following snippet:

// "_trackEvent" is the pageview event, 
_gaq.push(['_trackPageview', '/some-page']);

_trackPageview is used again but this time we provide the URL of the AJAX address that was loaded. Using the small JavaScript snippet above allows you to keep track of pageviews just as you would if the entire page reloaded. I'd recommend using this snippet with MooTools' History plugin.

The Old Method

If you're still using the synchronous method of loading Google Analytics, the following snippet will accomplish the same task:

pageTracker._trackPageview('/some-page');

It's great to know that Google Analytics is as dynamic as your web applications. Allowing developers to track AJAX page clicks prevents the need to code apps just to keep track of statistics.

Track.js Error Reporting

Upcoming Events

Recent Features

  • CSS Filters

    CSS filter support recently landed within WebKit nightlies. CSS filters provide a method for modifying the rendering of a basic DOM element, image, or video. CSS filters allow for blurring, warping, and modifying the color intensity of elements. Let's have...

  • Creating Scrolling Parallax Effects with CSS

    Introduction For quite a long time now websites with the so called "parallax" effect have been really popular. In case you have not heard of this effect, it basically includes different layers of images that are moving in different directions or with different speed. This leads to a...

Incredible Demos

  • Duplicate the jQuery Homepage Tooltips

    The jQuery homepage has a pretty suave tooltip-like effect as seen below: The amount of jQuery required to duplicate this effect is next to nothing;  in fact, there's more CSS than there is jQuery code!  Let's explore how we can duplicate jQuery's tooltip effect. The HTML The overall...

  • jQuery Link Nudging

    A few weeks back I wrote an article about MooTools Link Nudging, which is essentially a classy, subtle link animation achieved by adding left padding on mouseover and removing it on mouseout. Here's how to do it using jQuery: The jQuery JavaScript It's important to keep...

Discussion

  1. Christof Haemmerle

    you want to change want to check on the parent object(here window) if it has a function called pageTracker otherwise it will break your app.

    if(window.pageTracker)

  2. Chris Bowyer

    Interesting, but, the current (and it has been for some time) Google Analytics JavaScript (that should be placed immediately before the closing head tag) is as follows…

      var _gaq = _gaq || [];
      _gaq.push(['_setAccount', 'UA-XXXXX-YY']);
      _gaq.push(['_trackPageview']);
    
      (function() {
        var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
        ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
        var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
      })();
    
    • What is this in reference to?

    • In my view I think he only give refrence for puttinh google analytics codes in Head section,,, But don’t know what he exactly mean.

  3. nice tuts keep up sometimes i am viewing your tuts and it’s usefull.

  4. Hi David,

    To clarify – does this

    _gaq.push(['_trackPageview', '/some-page']);

    go on the page being loaded, or is it added to the main page which is doing the loading? If it goes on the page being loaded, does it replace the original trackPageview or get added to the original tracking code?

    Thanks!

    • Ryan Mac

      You would call the original GA Code your head when the page first loads. Then on completion of subsequent ajax calls use:
      _gaq.push(['_trackPageview', '/some-page']);
      Use jquery as an example:

      $.ajax({
        url: "test.html",
        context: document.body,
        success: function(){
          _gaq.push(['_trackPageview', '/text.html']);
        }
      });
      
  5. Hey, im not sure I get it. I have a 100% Ajax webapp and in google analytics I only get information for woojah.com/ But that page hardlly has anything. Everything is generated dynamically so my question is, do I have to put _gaq.push([‘_trackPageview’, ‘woojah.com/#mysubpage’]) for every subpage I have in my woojah.html?

    • You should never use # tags to control content/pages of your site. It’s really bad for SEO.

      change everything to use dynamic paths like woojah.com/mysubpage/

      It looks nicer and plays nicer.

  6. Hi Fernando,

    _trackPageView generates a virtual page but is otherwise similar to _trackEvent.

    Since it is just Javascript it can be called whenever an Ajax “page” loads. If, for example, you are using a WordPress site and want to track the loading of content on some plugins that use Ajax, you can modify the plugins Ajax calls to also call the _gaq.push() function. The “pages” that are recorded on Google Analytics are really just labels for the Ajax event (or any other event you like), so you should make the parameters obvious to anyone reading a GA report.

    Here is an example straight from Google Code in which a user plays a specific video using _trackEvent:

    _gaq.push([‘_trackEvent’, ‘Videos’, ‘Play’, ‘Gone With the Wind’]);

    See the similarity?

  7. _trackPageView generates a virtual page but is otherwise similar to _trackEvent. Since it is just Javascript it can be called whenever an Ajax “page” loads. If, for example, you are using a WordPress site and want to track the loading of content on some plugins that use Ajax, you can modify the plugins Ajax calls to also call the _gaq.push() function. The “pages” that are recorded on Google Analytics are really just labels for the Ajax event (or any other event you like), so you should make the parameters obvious to anyone reading a GA report. Here is an example straight from Google Code in which a user plays a specific video using _trackEvent: _gaq.push(['_trackEvent', 'Videos', 'Play', 'Gone With the Wind']);

    See the similarity?

  8. Matt

    Could _gaq.push(…)also be called with click event?

  9. bursinka

    Hi, Matt. Sure, there’s example at GA reference:
    onclick="_gaq.push(['_trackEvent', 'name', value]);"

    • I would advise against inline JS like that, instead take it to your js file:

          myLink.onclick = function (event) {
            //prevent normal link action
            event.preventDefault();
            _gaq.push(['_trackPageView', '/page/url']);
            //Your ajax loading code
          };
      

      You’ll probably only want to call the _gaq push part after you’ve loaded your new content though, otherwise you’re tracking pageviews that didn’t happen.

  10. I’m a bit puzzled by how this approach is meant to work. From what I’ve gathered, you normally first populate the _gaq array with whatever you want to track and with your account code, then ga.js is loaded which sends the information to Google’s servers.

    Now if I push an extra element onto _gaq.js after that happened without further ado, how would it actually know to send a new request to Google? Does ga.js check _gaq for changes with an interval or something?

    • Never mind that, I just fiddled a bit with the console and figured out that ga.js actually converts the _gaq array to an object with a push method in its prototype, which clearly takes care of it. Disregard my last comment! :-)

  11. Thanks for the info!

    Typo: especially try -> especially true

  12. I have another google analytics script code :

        (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
        (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
        m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
        })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
    
        ga('create', 'UA-#######-#', 'my web site');
        ga('send', 'pageview');
    

    any help ??

    • Hi Najih,
      I had the same problem, since the Goog is handing out that code currently and offering no alternatives. However if you insert the previous GA tracking code:

      var _gaq=[["_setAccount","UA-#######-#"],["_trackPageview"]];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];g.async=1;
      g.src=("https:"==location.protocol?"//ssl":"//www")+".google-analytics.com/ga.js";
      s.parentNode.insertBefore(g,s)}(document,"script"));
      

      And insert your tracking number, then in that case, I could get it to work. I attempted to get it to work with the “i,s,o,g,r,a,m” version as well without success.

      If anyone can get it to work with the “i,s,o,g,r,a,m” version, please reply.

    • That is the newer Google Universal Analytics, and you can find a tutorial here about how to apply it to Ajax pages:
      https://mjau-mjau.com/blog/ajax-universal-analytics/

  13. Mik

    According to the following documentation you no longer add to the array but call the function with the appropriate functions: https://developers.google.com/analytics/devguides/collection/analyticsjs/advanced

    So just add the tracking code google gives you and every time you want to log a pageview, instead of the old command:

    _gaq.push(['_trackPageview', '/some-page']);
    

    use the following code instead:

    ga('send', 'pageview', {
      'page': '/my-new-page',
      'title': 'My New Page Title'
    });
    

    So instead of adding to the array you just call the function with the extra options.

  14. Hi David!

    Thanks for sharing this trick.

    It seems that we have to use another syntax with the newer analytics.js API.
    The following code works:


    ga('send', 'pageview', '/some-page');

    Source: https://developers.google.com/analytics/devguides/collection/analyticsjs/pages

    Cheers,
    Thomas.

    • I’ll have a look, but the _gaq.push(['_trackPageview', '/some-page']); method does still work!

    • Sure!

      I wasn’t enough clear.
      It still work, but there is a different syntax if you use the Google Analytics API.

      It was just an additional information ;)

      Cheers,
      Thomas.

  15. For the Javascript I’m writing that might be deployed in various places, I use this:

          if (typeof _gaq !== 'undefined') {
            _gaq.push(['_trackPageview', location.pathname]);
          }
          else if (typeof ga !== 'undefined') {
            ga('send', 'pageview', {'page':location.pathname,'title':document.title});
          }
    

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!

Recently on David Walsh Blog

  • Free Download: Font Bundle Featuring 17 Incredible Typefaces

    The only thing we love more than a good font, is a good free font. So we’ve combed the Web for some of our favorite free fonts, and gathered them here in a single download. You’ll find a variety of useful typefaces, from highly geometric designs...

  • OâReilly Velocity Conference â Amsterdam

    My favorite front-end conference has always been O'Reilly's Velocity Conference because the conference series has focused on one of the most undervalued parts of client side coding:  speed.  So often we're so excited that our JavaScript works that we forget that speed, efficiency, and performance are just as important. The next Velocity...

  • CanIUse Command Line

    Every front-end developer should be well acquainted with CanIUse, the website that lets you view browser support for browser features.  When people criticize my blog posts for not detailing browser support for features within the post, I tell them to check CanIUse:  always up to date, unlike...

  • Generating Alternative Stylesheets for Browsers Without @media

    If your CSS code is built with a mobile-first approach, it probably contains all the rules that make up the "desktop" view inside @media statements. That's great, but browsers that don't support media queries (IE 8 and below) will simply ignore them, ending up getting the...

  • Serve a Directory with PHP

    Many developers have a giggle at PHP, even looking down at the language, but let's be honest:  most of our blogs are powered by it (WordPress) and it's a great language to dabble around with.  I cut my teeth on PHP, though I prefer to avoid PHP these days. But...