Setting GA campaign tracking using JavaScript

Google Analytics offers two options for tracking your online campaigns (Google AdWords auto-tagging aside):

    • 1. Google’s built-in campaign tracking parameters (e.g., utm_source, utm_medium and utm_campaign).


    2. Your own specific campaign parameters, mapped to the correct keys in JavaScript (e.g., _setCampSourceKey and _setCampMediumKey, etc.)

Unfortunately, these two options are not always available. For example, your campaign management system often automatically creates links, with no easy way to set extra necessary campaign parameters. In addition, some of the traffic is sent from places where their targeted URLs cannot be controlled (such as posts and tweets). Such traffic appears under “Referrers” and not under the specific campaign.

As far as I know, Google Analytics does not have a way of dealing with this. The only way you can “force” your campaign details, and not through the campaign tracking parameters, is by using the _setAllownchor and setting the document.location.hash manually in JavaScript. (If anyone knows of a better solution, please let me know!)

Urchin provides a partial solution to these problems, whereby you only need to pass one parameter (utm_id), and this “Master Tracking Code” hides the campaign tracking variables. In the past, there were also several work arounds for both urchin.js and older versions of ga.js. However, these solutions do not work with the latest version of ga.js.

You can of course use the _setAllowAnchor method to set your campaign tracking, but then the user ends up with an extra page or two in his/her browser history. (This is because when you use _setAllowAnchor, you have to add the campaign tracking information with the anchor sign to the URL. Although the browser does not refresh the page, it does store the “new” URL in its history).

This is why I found myself looking for a better solution. The solution I was thinking of was quite simple. I wanted to change the __utmz cookie (which is where GA stores the traffic source information), prior to GA sending the pageview request to the server. My only problem was that in many cases, I wanted to add or change just one of the campaign’s attributes, and not completely override the default campaign tracking logic, so I had to first let Google Analytics do its thing and only then override the cookie.

If you remember, in one of the past versions of ga.js, you had to call the _initData before calling _trackPageview. This method identified the traffic source and set your __utmz cookie. GA later combined the _initData and _trackPageview, even though you can still just call _initData. This means that the only thing we have to do before changing the utmz cookie is call _initData to set it.

For example, let’s take the following scenario: I want to set up a “social” campaign in Google Analytics, and I want all traffic from Facebook and Twitter to be tracked under this campaign. (By the way, this can be achieved by setting the right filters in the GA profile, but let’s use Javascript just for the sake of this example):


// call _initData to set __utmz cookie based on GA own logic
_gaq.push(function() {
// if the referrer is facebook or twitter, change the campaign name to be "social" in __utmz
if (document.referrer.match(/^http[s]?:\/\/www\.(facebook|twitter)\.com/)) {
// get the current values from __utmz cookie
var utmz = readcookie("__utmz");
// check if __utmz holds already a campaign name (utmccn). Change or add utmccn accordingly
if (utmz.match(/utmccn/)) utmz = utmz.replace(/utmccn=[^\|]*/, "utmccn=social");
else utmz += "|utmccn=social";
// save __utmz
savecookie("__utmz", utmz, 365);


As you will need to have two methods for reading and saving the cookies, you can use the following:

function readcookie(name) {
var re = new RegExp("(?:^| )" + name + "=([^;]*)", "i");
var matches = document.cookie.match(re);
return matches && matches.length == 2 ? matches[1] : null;
function savecookie(name, value, days) {
var date = new Date;
date.setTime(date.getTime() + (typeof days != "undefined" ? days : 3) * 24 * 60 * 60 * 1000);
var expires = "; expires=" + date.toGMTString();
document.cookie = name + ("=" + value + expires + "; path=/; domain=." + document.domain);

By using this principal, I have created a more generic solution that extends the pageTracker object and adds the following methods:

  • _setCampValues(source, medium, campaign, term, content)
    Using this method you can override all of the campaign values at once.
  • Or you can change a specific campaign tracker field by using any of the following methods:
    • _setCampSource(value)
    • _setCampMedium(value)
    • _setCampContent(value)
    • _setCampName(value)
    • _setCampTerm(value)

I will put a reference to the code in one of my future posts – I have to first organize it and add some comments. If, however, you need it now and don’t care that it’s a bit messy, please drop me an email and I will send it to you.