Google Analytics from a file:// url

OK, I think I have this one solved. It's been dogging me for a few days.

According to Google Analytics Help Center,

Visitors must have JavaScript, images, and cookies enabled in their browsers in order for Analytics to report their visit.

Here's my theory: In my tests on Mac OS X Snow Leopard, documents run from file:// are not able to set cookies. This is because cookies are proprietary to HTTP, and when you run something from file://, you're not using the HTTP protocol.

Since you're not able to set cookies, ga.js refuses to send the _utm.gif request to Google's servers. No cookies get set; no request is sent to google, so nothing is logged in GA.

Solution: Use a development environment where you can set your domain as http://localhost (something like MAMP, if you're on a Mac and need a LAMP stack)

(Weird footnote: I observed some weird behavior where the GA cookies would set as third-party cookies of the domain of an unrelated imported script from a third party non-CDN domain. This could be because since the server sends HTTP cookies with the file, ga.js is attaching itself to that domain. However, this won't serve as a backdoor, since it still won't send the _utm.gif hit to Google's servers ).

========

EDIT:

You could try one of the various work arounds people have created for cookie-less GA tracking.

You might get some success out of this tool: http://code.google.com/p/google-analytics-js/downloads/list, explained here: http://remysharp.com/2009/02/27/analytics-for-bookmarklets-injected-scripts/

Instead of all of that GA code, you would include the script, and then call it using the following code:

gaTrack('UA-XXXACCOUNTID-XX', 'myfake.domain.com', '/some/path/here');

Its designed for bookmarklet/injected script tracking, but if I put in a file:// type setup, its able to successfully send the __utm.gif hit, meaning it SHOULD track successfully in GA.

The drawback is that cookieless means that it won't be able to track visits accurately, just page-view level data.


A couple of tweaks are necessary:

Disable cookie storage

Cookies cannot be used as there's no domain in action, so we need to prevent GA from trying to use them. This is done by setting 'storage': 'none' in creation config (documentation).

Disable file protocol check

By default, GA aborts if the protocol (in our case file) is not http or https. Disable this check using the corresponding task: ga('set', 'checkProtocolTask', null)

Set active page manually

Since there is no domain, GA fails to derive a path denoting the active page. It can be configured manually by using the page URL modification feature: ga('set', 'page', 'foobar')

A subsequent ga('send', 'pageview') will then show up in data as a visit on /foobar.

Track user identity using localStorage (optional)

With cookies disabled, users are not tracked across page loads, so each refresh will trigger detection of another unique visitor. However, we can provide custom client ids on create by setting 'clientId': localStorage.getItem(someKey), which looks for previously stored client ids.

Storing ids is done by

ga(function(tracker) {
  localStorage.setItem(someKey, tracker.get('clientId'));
})

Everything combined

Combining all above steps, we end up with something like the following:

(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','https://www.google-analytics.com/analytics.js','ga');

ga('create', 'UA-XXXXXXXX-Y', {
    'storage': 'none',
    'clientId': localStorage.getItem('ga:clientId')
});
ga(function(tracker) {
    localStorage.setItem('ga:clientId', tracker.get('clientId'));
});
ga('set', 'checkProtocolTask', null);

ga('set', 'page', 'myPage');
ga('send', 'pageview');

Google now supports disabling the protocol check task by setting it to null, allowing you to track analytics from a file:// url:

ga('create', 'UA-XXXXX-Y', 'auto');
ga('set', 'checkProtocolTask', null); // Disable file protocol checking.
ga('set', 'checkStorageTask', null); // Disable cookie storage checking.
ga('set', 'historyImportTask', null); // Disable history checking (requires reading from cookies).
ga('send', 'pageview');