Convert Google Analytics cookies to Local/Session Storage
Asked Answered
S

3

16

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.

Scratches answered 21/12, 2010 at 17:29 Comment(6)
+1 for the well described caseIdeography
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?Gastrolith
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. :-)Scratches
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.Brokenhearted
@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).Excusatory
Warning, this idea appears to be flawed: please read github.com/h5bp/html5-boilerplate/issues/…Sharpeared
O
20

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

Obstruct answered 6/10, 2013 at 8:45 Comment(11)
Great job. For most cases you'd want to feature-test for localStorage first (maybe using Modernizr, falling back to cookie storage if it doesn't exist.Scratches
Could you explain what the purpose of this code is? Is there something wrong with GA's cookies?Wistrup
@DavidMurdoch I see. I wonder why GA does not come with localStorage support built-in. (Btw, you have to mention me :). @S didn't trigger the auto-complete for my name?)Wistrup
@DavidMurdoch I added 'localStorage' detection for you!Obstruct
Unfortunately, just checking if window.localStorage is truthy is not enough. Modernizr has a stable feature test with comments explaining why it needs to be done the way they do it here: github.com/Modernizr/Modernizr/blob/master/feature-detects/…Scratches
A warning: HTML5 boilerplate is working on integrating this, but have experienced certain issues. The entire thread, but at least the comment github.com/h5bp/html5-boilerplate/issues/… is worth a read.Melodics
This might violate GA TOS! Here is a secondhand quote from a GA Team member, taken from this article: "Using HTTP State Management mechanisms" (read: localStorage) "to propagate cookie state is a circumvention of our privacy safeguards. Doing so violates the Google Analytics Terms of Service". My interpretation of this is that GA employs cookies and not localStorage because more users are familiar with the concept of cookies and how to clear them; thus, GA's use of cookies is a privacy feature.Sludge
While this is technically correct, the idea appears to be wrong: @DavidMurdoch please read github.com/h5bp/html5-boilerplate/issues/…Sharpeared
Thanks... But that github comment is actually directed at me. I am David Murdoch.Scratches
@smhmic It is officially supported by Google now! see: github.com/h5bp/html5-boilerplate/issues/…Scratches
@DavidMurdoch Well, that clears up one ambiguous aspect of the GA TOS clause "You must not circumvent any privacy features". Thanks for pointing this out!Sludge
B
2

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?

Brokenhearted answered 16/5, 2012 at 10:3 Comment(0)
I
0

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
Ideography answered 27/12, 2010 at 14:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.