Using Multiple Trackers in Google Analytics

Using Multiple Trackers in Google Analytics

Posted by on Wed, Apr 17, 2013
Filed Under | Google Analytics


Why would you want to use multiple trackers?

In case you didn’t know, there are ways to put tracking code on pages that will track to two or more Google Analytics accounts or web properties. It can get kind of tricky but once you understand the concept, it’s a breeze.

Let’s start with having a reason to put multiple trackers on your site’s pages. I’ll give you two:

  1. Tracking for affiliates – Suppose you have an e-commerce site and the vendor you use for transactions requires tracking transaction information to their own Google Analytics account.
  2. Your company has multiple sites – Perhaps your company has several locations, each with its own domain, and you want both an individual look at each domain and an aggregate look for all domains combined. This is referred to as a “roll-up tracker.”  A roll-up tracker could be Profile based, Property based or even Account based.  Each domain would then track on its own plus to the roll-up.

What if you have multiple sites AND also track for affiliates, would you need to have 3 trackers on some pages? YES

Is it possible to track to more than two Google accounts or web properties? the good news is YES!

Do I need a Profile, Property or Account Rollup?

Account Roll-up:
In the case of an affiliate, the need for a separate tracker is more like a requirement.  The affiliate company will be tracking to their account and your site tracks to your own account.

Property Roll-up:
A Property roll-up as opposed to an Account based roll-up offers the advantage that since all Properties within an Account share users, filters and data sources, it’s much easier to configure these items and assign them to the appropriate Properties without the need to create them multiple times.

Having each site on its own Property allows you to easily report only on that specific site without the need for filtering out traffic outside of the specified domain or sub-domain.  This comes really handy when you have a large collection of sites.  Imagine having to create Include and Exclude filters for 24 sites?

However, this advantage presents the disadvantage of not being able to report aggregate data. That’s where a roll-up account comes in. Implementing multi-tracking code on the sites to track to separate Properties, will let you see aggregated traffic on your roll-up Property while maintaining the singularity of your site’s own Property.  Add a filter to show the full domain on your roll-up Property and now you’re able to see traffic to all sites within your content reports. Add cross domain tracking to your roll-up account and you’re able to see the flow of visitors across the sites.

Profile Roll-up:
Profile roll-ups don’t require multi-tracking code, simply because profiles share their parent Property ID so the code would be the same on all sites.

If you have 2 or 3 domains, setting up a Profile roll-up may be the best solution since you don’t have to change your code and handling filters is not that complicated. Creating multiple profiles is a lot easier than creating multiple Properties since copying a profile also copies assigned filters, goals and settings while there’s no option to copy a Property.  Your roll-up Profile would still need to have a filter to show the full domain.

Now that we know what we want, how do we do it?

Although it can get a little tricky when you start thinking about cookie sharing and such, the key to the solution is namespacing your trackers.  This presents a little more work for your development team and unfortunately introduces room for error.

Multiple Trackers, The Standard Method

Google provides some brief guidelines into how the code needs to be structured in the “One Push, Multiple Commands” section of their development guidelines – however, they don’t really tell you much so here’s a good example:

_gaq.push(
  ['_setAccount', 'UA-XXXXX-1'],
  ['_trackPageview'],
  ['rollup._setAccount', 'UA-XXXXX-2'],
  ['rollup._trackPageview']
  ['affiliate._setAccount', 'UA-YYYYYY-1'],
  ['affiliate._trackPageview']
);

The formula is simple, add a prefix to the Google Analytics command for your additional trackers and duplicate your code for every tracker you need.  If you put two and two together, you see how this can be tedious work.  You would need to duplicate every _gaq.push you have throughout your site.  All Events, Pageviews, Custom Variables, and any other standard tracking commands but worst of them all, your e-commerce code complete with every _addItem command listed.  That’s where it really gets heavy.

Multiple Trackers, The Blast Method

We believe in simplicity and automation.  Eliminating development time and lowering the potential for errors is what drove us to develop this multi-tracker script.  The benefits of the script include:

  • Easy to configure web property numbers and tracker names
  • Automated setAccount for all trackers
  • Ease of use by maintaining current method structure
  • Option to specify tracking on only specific trackers
  • Ability to modify how data is sent to Google

The Script

To start, we’re going to set some array variables at the beginning of your code:

var GA_Account_IDs = ['UA-XXXXXX-1','UA-XXXXXX-2','UA-YYYYYY-1'];
var GA_Tracker_Names = ['main','rollup','affiliate'];
var GA_Trackers = [];

You’ll want to enter the actual web property numbers for GA_Account_IDs.  For the tracker names, we’ve set a pretty accurate default set of names.  Feel free to change them as you please. The values can be either hard coded or populated servers side.  In the example of an affiliate solution, you may be interested in capturing e-commerce transaction pages but not necessarily every page of your site.  A server-side script could determine whether or not to populate the affiliate information.  Make sure that you always match the position of the UA# with the position of the Name.  For example, if you didn’t want to track to the roll-up on a specific page, you would enter the first and third UA#s along with “main” and “affiliate” names in the same order.

The following configuration is the star of the show:

var GA_Track = function() {
  // check to see if list of trackers is set, otherwise set to blank
  var trackers = (typeof(GA_Tracker_Names) === 'undefined') ? ['']: GA_Tracker_Names;
  // grab function arguments and put into array args
  var args=[].slice.call(arguments), c = [], p = [], d;
  // check for 'bam' for specifying tracker names
  if(args[0][0]==='bam'){
    // if 'bam' is the first item of the first argument, grab the supplied tracker names and put into array trks
    c.trks=(trackers.length>1) ? args[0].splice(1): trackers;
    // drop first argument and put the rest into args
    c.args=args.splice(1);
  } else { // if no 'bam' is present, use trackers and args as supplied
    c.trks=trackers;
    c.args=args;
  }
  for (d=0; d<c.trks.length; d++) { p[d] = [];
    for (var a=0; a<c.args.length; a++) { p[d][a] = [];
      for ( var i=0; i<c.args[a].length; i++ ) { p[d][a][i] = [];
        // if not main tracker and if first argument, insert tracker name, otherwise if main tracker leave blank, if not first argument, skip
        var r = ( i != 0 ) ? '_': ( c.trks[d] == trackers[0] ) ? '': c.trks[d]+'.';
        p[d][a][i] = (r!='_') ? r+c.args[a][i] : c.args[a][i];
      }
      // console.log( p[d][a] ); // debug:
      _gaq.push( p[d][a] ); // push to _gaq object for GA only
    }
  }
};
// initiates the GA accounts and populates the Trackers
for ( var id=0; id < GA_Account_IDs.length; id++ ) {
  GA_Trackers.push(GA_Tracker_Names[id]);
  GA_Track(['bam',GA_Trackers[id]],['_setAccount', GA_Account_IDs[id]]);
}

More on the script will follow, but we have one more step before the task is done.

Code Replacements

As Google officially starts introducing Universal Analytics, moving forward we need to take steps to minimize the amount of work for future migrations.  Since Universal Analytics uses a different syntax than Google Analytics, a migration to Universal Analytics would require you to change all existing tracking code and adjust it to the new syntax.  However, Universal Analytics is a developing technology and not all existing features of Google Analytics (GA) are fully supported.  So the best solution is to implement tracking code via a function that will collect the necessary data throughout the site and then reformat the way the data is sent to Google within that function.

The basis of the script is to replace the _gaq.push method with the GA_Track function on the initial Google Analytics code implementation.  Right at the very end of the GA_track function, you determine how data is formatted and sent to Google.  A sweet bonus is that you can enable the debug console.log and you’ll see exactly what is getting sent to Google.

On existing implementations, we will take the first step towards a smooth Universal Analytics migration now by changing all the push methods on the site as follows:

Example code case:

_gaq.push(['_setCustomVar',1,'Customer Type','member',1],['_trackPageview']);
_gaq.push(['_addTrans',
   '1234',           // transaction ID - required
   'Womens Apparel', // affiliation or store name
   '28.28',          // total - required
   '1.29',           // tax
   '15.00',          // shipping
   'San Jose',       // city
   'California',     // state or province
   'USA'             // country
]);
_gaq.push(['_addItem',
   '1234',           // transaction ID - necessary to associate item with transaction
   'DD44',           // SKU/code - required
   'T-Shirt',        // product name
   'Olive Medium',   // category or variation
   '11.99',          // unit price - required
   '1'               // quantity - required
]);
_gaq.push(['_trackTrans']);
_gaq.push(['_trackEvent','page-interaction','cart confirmation','print page', 0, true]);

With the standard method, you would need to duplicate the code above for each of the trackers.  On a site with a roll-up tracker and an affiliate tracker, the code would need to be placed 3 times as shown on the previous example.

Instead, all you need to do is replace _gaq.push with GA_Track as shown below: (you’ll thank us later!)

GA_Track(['_setCustomVar',1,'Customer Type','member',1],['_trackPageview']);
GA_Track(['_addTrans',
   '1234',           // transaction ID - required
   'Womens Apparel', // affiliation or store name
   '28.28',          // total - required
   '1.29',           // tax
   '15.00',          // shipping
   'San Jose',       // city
   'California',     // state or province
   'USA'             // country
]);
GA_Track(['_addItem',
   '1234',           // transaction ID - necessary to associate item with transaction
   'DD44',           // SKU/code - required
   'T-Shirt',        // product name
   'Olive Medium',   // category or variation
   '11.99',          // unit price - required
   '1'               // quantity - required
]);
GA_Track(['_trackTrans']);
GA_Track(['_trackEvent','page-interaction','cart confirmation','print page', 0, true]);

Choosing Your Trackers

Using the example of tracking for an affiliate, you would only be interested in tracking transactional pages.  The account tracker does not need to be present on all pages of your site. This would be easily handled by simply omitting the tracker UA# and “affiliate” name.  However, on the completion page, you want to track if the user prints the page and the affiliate does not care about this data.

You would then make a function to listen for the “print” option, or a click on the “print” button and then fire off an event tracker.  However, since there have been 3 items already defined on the page; doing a simple GA_Track() call would go to all three.

To send only to the “main” and “rollup” trackers, you’ll need add an initial array whose first item is “bam” and is followed by the names of the desired trackers.  Be sure your names here match exactly how they were initialized.

GA_Track(["bam","main","rollup"],['_trackEvent','page-interaction','cart confirmation','print page', 0, true]);

So what if we only have 1 tracker?  No problem, just enter 1 UA# and 1 tracker name.  The functionality remains exactly the same.  The difference being that you can go from 1 tracker to 3 trackers by simply adding the additional numbers/names.  You can also go from standard GA to Universal or both, from one location.

Limits

So exactly how many trackers can you send to simultaneously?  Well, that all depends.  It’s hard to imagine a scenario needing more than 4 trackers per site.  We would love to hear from anyone who has needed to do so!

Limits are set by how many hits can be done in a burst.  For regular Google Analytics, this is set to 10 and then it replenishes at a rate of 1 per second.  In Universal Analytics, this limit is 20, replenishing at 2 per second.  Anything above that will be ignored.  Read more about that on Google’s Developers pages.

Keep in mind, these limits are set for hits, regardless of what type of hits they are.  If you initialize your page with 3 trackers, you’ll start off with 3 pageviews.  If you fire off an Event immediately after, you’ll have 6 hits.  A burst is any number of hits sent within a second.  If you have to send several hits to several trackers, you may need to add some delays.

Use this Free Script

Feel free to use our script on your next project.  If you have any questions about implementation, simply post them as comments below.  Be sure to share, like and +1 if you enjoyed this post.

Enjoy this post?

Join the discussion below, subscribe to our RSS feed or share it on the web.

This post was written by:

has written 5 posts on the Web Analytics Blog.

Olaf is a Google Analytics Consultant at Blast Analytics & Marketing. He spends the majority of time developing tracking code and finding more efficient ways for our clients to read and analyze their data He loves the challenges that every project presents and is always trying to develop tools or methods to make everyone's life easier.

Add Olaf to your circles on Google+


Tags: , ,
  • http://twitter.com/JulienCoquet Julien Coquet

    Ah yes, JS Arrays. Nice and simple.

  • http://www.spinxwebdesign.com/ Alan Smith

    Nice tricks… thanks a ton for sharing with us.

  • Nicholas Blexrud

    Gorgeous! Thanks for the share.

  • Yehoshua Coren

    Hi Olaf,

    This is a really good article explaining a very clear and understandable method for managing multiple trackers. A +1 as always to good stuff coming from the Blast blog.

    One comment regarding limits, the burst rates that you mentioned are only for events, not for the other hit types. Pageview, commerce, social etc hits are not subject to the 10 hit per second limitation. As such, people need to be mindful of the number of hits they are rattling off with events, but not so with the other hit types. It is also worth mentioning that there is a 500 hit / session limit, which can also become an issue with 3 to 4 trackers per page.

    Yehoshua

  • James Carroll

    Hi, very interesting post! But it looks like the javascript got a bit messed up when you made the code/syntax highligher divs. In particular these for loops don’t look valid..

    for (d=0; d p[d] = [];
    for (var a=0; a p[d][a] = [];

  • http://www.blastam.com/ Olaf Calderon

    @disqus_A2cavbWRTT:disqus thank you for pointing that out – I did update the script on there now – not sure what happened but I’m glad you caught it!

  • http://www.blastam.com/ Olaf Calderon

    @yehoshuacoren:disqus Great point. Yes, the hit limitations are subject to Events on Classic GA with a replenishment rate of 1 hit per second. The point on the 500 hit per session is also VERY important if you have any pages that have several events sent on page load and you have multiple trackers. It is important to plan these things out prior to development to ensure that they are efficient and accurate.

  • Massimo Como

    Hi Olaf – This is great but as I’m not quite experienced in creating scripts and tracking, I was wondering if you can guide me in the best method to use for the following scenario:

    I need to add GA tracking to one of our subdomains (flyer.domainname.com) which is managed by a third party and they have their own tracking code set in place and we need to add ours. We also want to eliminate referral tracking from the subdomain to main domain (www.domainname.com) and keep it as a single entity.

    Since the third party has to implement the tracking functionality I’m not sure if the script would be overkill. Therefore, Google’s “One Push, Multiple Commands” may be enough.

    This is my attempt at the code is the following:

    _gaq.push(
    ['_setAccount', 'UA-XXXXX-1'],
    ['_setCampaignCookieTimeout', 0],
    ['_trackPageview'],
    ['rollup._setAccount', 'UA-XXXXXX-2'],
    ['_setDomainName', 'domainname.com']
    ['rollup._trackPageview']
    );

    UA-XXXXXX-1 is subdomain (third party)
    UA-XXXXXX-2 is main domain (ours)

    Plus, just placing it within the subdomain template file good enough or on every single page?

    Thanks for you help.

    Cheers,

    Massi

  • http://www.blastam.com/ Olaf Calderon

    Hello Massimo,

    Google’s “One Push, Multiple Commands” only refers to the fact that you can piggy back several sets of commands within a single .push(). So instead of this:

    _gaq.push([ ... set 1 ... ]);
    _gaq.push([ ... set 2 ... ]);
    _gaq.push([ ... set 3 ... ]);

    You can simply do this:

    _gaq.push([ ... set 1 ... ],[ ... set 2 ... ],[ ... set 3 ... ]);

    Personally, I like doing that myself, however whenever a third party is involved it may be better to keep things separate in case either side needs to make changes to their set.

    Namespacing is critical in your situation. If you’re coming in as the “second” tracker and you set the account as “rollup” any tracking you want coming into your account should be prefixed with “rollup.”

    In your example, the first 3 items are the third party and the last three are yours. All of yours should be namespaced as such:

    _gaq.push(
    ['_setAccount', 'UA-XXXXX-1'],
    ['_setCampaignCookieTimeout', 0],
    ['_trackPageview'],
    ['rollup._setAccount', 'UA-XXXXXX-2'],
    ['rollup._setDomainName', 'domainname.com']
    ['rollup._trackPageview']
    );

    Another thing you need to consider is timing. On any links that load on the same window, there will not be enough time to consistently fire off two pixels in time prior to dropping the document so you need to implement a delay ( about 300ms ).

    As far as placement, you need the code to be on Every page of the site, so if the subdomain template gets used on every page, that’s where you want it to be. Depending on the third party and whatever framework they’re using, this may present a challenge. You would need to contact them to see if they’re open to changing their template for you.

    Your case sounds like it can be a little complicated. You’re always more than welcome to purchase some consultation time and we will provide you with the necessary code and direct guidance for implementation as well as instructions to provide to that third party.

  • Massimo Como

    This is great, thx Olaf.

    Is there a difference who’s ‘first’ or ‘second’ tracker? Could ‘second’ tracker lose data because of placement if there’s enough time?

  • http://www.blastam.com/ Olaf Calderon

    It makes a difference when you have different settings for the trackers, that’s the whole purpose of name spacing. Which one you actually place first as in the order of the syntax, doesn’t really matter. Timing WILL come into the picture if you don’t have a delay on links which cause a page reload. Both trackers may not always come through. Since it’s asynchronous code, the “first” tracker may not always be the first tracker in code order, although code order matters, how long it takes the first tracker, in code order, to get a response may vary from the second and thus may cause it to tracker after. I hope that’s not too confusing to understand?

  • Fede Pikholc

    Hi Olaf,

    Let me ask you about cookies. It Is not a problem using multiple trackers while trying to construct a roll up? Is it possible to get two sets of cookies?

  • http://www.blastam.com/ Olaf Calderon

    Hello Fede,

    Depending on how you have the rollup configured, you don’t have any issues with cookies. If you are doing crossdomain tracking on the main account but none on the rollup, or vice-versa, then you would need to make sure that each tracker is set on a different cookie and you can simply specify the cookie for it. Otherwise, sharing the cookie is ok for both accounts.



Goal Driven Online Marketing & Analytics
Copyright © 1999-2013 Blast Analytics & Marketing