16
votes

UPDATE http://jsfiddle.net/musicisair/rsKtp/embedded/result/


Google Analytics sets 4 cookies that will be sent with all requests to that domain (and ofset its subdomains). From what I can tell no server actually uses them directly; they're only sent with __utm.gif as a query param.

Now, obviously Google Analytics reads, writes and acts on their values and they will need to be available to the GA tracking script.

So, what I am wondering is if it is possible to:

  • rewrite the __utm* cookies to local storage after ga.js has written them
  • delete them after ga.js has run
  • rewrite the cookies FROM local storage back to cookie form right before ga.js reads them
  • start over

Or, monkey patch ga.js to use local storage before it begins the cookie read/write part.

Obviously if we are going so far out of the way to remove the __utm* cookies we'll want to also use the Async variant of Analytics.

I'm guessing the down vote was because I didn't ask a question. DOH!

My questions are:
Can it be done as described above?
If so, why hasn't it been done?


I have a default HTML/CSS/JS boilerplate template that passes YSlow, PageSpeed, and Chrome's Audit with near perfect scores. I'm really looking for a way to squeeze those remaining cookie bytes from Google Analytics in browsers that support local storage.

3
+1 for the well described caseWolph
I'm wondering, local storage cookies is bound to one browser session right? So if the user, for an example, visits the same page in two different tabs (in the same browser) she will count as two visitors?bskard
The data in LocalStorage is persistent and doesn't expire. Also, I see that you are pretty new here... comments like the one you posted above should be posted as a comment on the question, not as an answer. :-)David Murdoch
This seems like a really good idea. One use case I can think of is if you have a reverse proxy / CDN in front of your site that falls back (origin pull) if the page is not static. Such a proxy might see a unique cookie, and therefore pull from origin, rather than use the cached copy of the page it already has.rjmunro
@DavidMurdoch What would be the simplest way in your JSfiddle of testing if Google Analytics has worked? I'd like to see if this approach can be adapted to get GA working on content that has been embedded into 3rd party iframes on browsers that by default block cookies for 3rd party domains (Safari and Internet Explorer).user56reinstatemonica8

3 Answers

20
votes

Use this:

(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');

if(window.localStorage) {
    ga('create', 'UA-98765432-1', 'www.example.com', {
      'storage': 'none'
      , 'clientId': window.localStorage.getItem('ga_clientId')
    });
    ga(function(tracker) {
      window.localStorage.setItem('ga_clientId', tracker.get('clientId'));
    });
}
else {
    ga('create', 'UA-98765432-1', 'www.example.com');
}
ga('send', 'pageview');

First, I check if localStorage is supported. If it is supported then the 'storage': 'none' option will disable cookies. Now we can set the clientId from localStorage. If it is empty, Google Analytics will generate a new one for us. We save the new (or existing) clientid in localStorage after the tracker loads.

If localStorage is not supported, I just use the regular analytics method. After the initialization I send a pageView via ga('send', 'pageView').

Also, check out this plunk: http://plnkr.co/MwH6xwGK00u3CFOTzepK

2
votes

Some experimentation in chrome shows that it may be possible to use getters and setters to patch document.cookie for this, something like:

document.__defineGetter__('cookie', function () {
    // Replace this with code to read from localstorage
    return "hello";
});
document.__defineSetter__('cookie', function (value) {
    // Replace this with code to save to localstorage
    console.log(value);
});

ga.js (or any other javascript) could run and access cookies as normal, they just would never get passed to the server.

Obviously this will only work in some browsers. Browsers in which it doesn't work will have to fall back to normal cookies.

There's some related ideas in this question: Is it possible to mock document.cookie in JavaScript?

0
votes

Yes it can be done. You only have to request the __utm.gif with the parameters. The rest of the data is just used for keeping track of the source, session start time and/or previous visits.

You can easily transfer the cookies both ways, so your first approach should work fine.

If your second approach works... not sure. I don't know the ga.js code good enough to estimate wheter that would or would not be easily possible.

There is also a third option, run your own version of ga.js. You are not required to use the Google version.

Can it be done as described above? Yes

Why hasn't it been done?

  1. the cookies are small, there isn't that much benefit if you use cookieless domains for all your static content
  2. it's less convenient since a lot of browsers don't support it yet