How to use Google Analytics with Phonegap without a plugin?

Check out the video to see it in action:

http://screencast.com/t/6vkWlZOp

After some research, I found a solution. I came across this thread on the Phonegap Google Group: https://groups.google.com/forum/#!msg/phonegap/uqYjTmd4w_E/YD1QPmLSxf4J (thanks TimW and Dan Levine!) In this thread I found that it is possible to use Google Analytics without a plugin. All you have to do is download the ga.js file from Google http://www.google-analytics.com/ga.js (just save the page into your www folder)

Then modify the ga.js file by adding one character to it. Search the ga.js file for the word "file:" and replace it with "_file:".

In the thread I linked to above, "TimW" explains the reasoning for this:

Essentially, Google Analytics won't work if its being used from a file:/// url. In iOS/PhoneGap this is the case. In order to solve this problem you must first download the ga.js file from google and include it as part of your local build. You'll notice the this file is obfuscated. Search the file for the string "file:" which should occur only once. When you find it, add an underscore to the beginning (so it becomes "_file:"). This prevents it matching the protocol of the page location (which is "file:").

After you added one character to the ga.js file, simply include this following in the top of your page:

<script type="text/javascript" src="ga.js"></script>
    <script>
 var _gaq = _gaq || [];
    _gaq.push(['_setAccount', 'UA-YOUR_ID_HERE']);
    _gaq.push(['_setDomainName', 'none']);
    _gaq.push(['_trackPageview', 'NAME_OF_PAGE']);
    </script>

I tested this on the simulator, and I got a proof that it was working using the Real-Time view in Google Analytics. The simulator was working on iOS 5.0. My phone is still on iOS 4.2, and when I tested it on my device, it didn't show up on the Real Time tracking.

In the thread, someone mentioned the same issues with Android 4.0+... Hopefully there will be a better solution for this in the future but for now this is the easiest and least complicated way to get basic analytics for my app. It can't do offline tracking, but that's kinda creepy anyways.

Even though iOS 4 and Android users are a minority in the market (see pie chart):

http://static7.businessinsider.com/image/4fd65fac6bb3f7925700000f/chart-of-the-day-ios-vs-android-june-2012.jpg

I would stil like to get data from all OS's.


I was using Ionic app (based on cordova) as a mobile website and GA was working for it. When I shipped the same app to native ios, it stopped working.

Issue 1.
On checking the logs of simulator, found that GA was not being loaded correctly. It was trying the load file://. To fix this, I prepended https: to GA url under

(window,document,'script','//www.google-analytics.com/analytics.js','ga')

Issue 2. Google by default aborts the request if the page protocol is not http or https. To fix this

ga('set', 'checkProtocolTask', null);

And you should be set. After making these changes, I was able to confirm the events on GA. Hope it helps you too.


[edit] Google Analytics now works with localstorage in hybrid apps.

Google Analytics now have an options explained here to use LocalStorage instead of cookies and there is also a hack to make it work in webviews (file:// urls). So instead of using the code I suggested before, you can just do this :

// THIS IS FOR LOCALSTORAGE
var GA_LOCAL_STORAGE_KEY = 'ga:clientId';
ga('create', 'UA-XXXXX-Y', {
  'storage': 'none',
  'clientId': localStorage.getItem(GA_LOCAL_STORAGE_KEY)
});
ga(function(tracker) {
  localStorage.setItem(GA_LOCAL_STORAGE_KEY, tracker.get('clientId'));
});

// THIS IS FOR FILE URL SUPPORT
ga('set', 'checkProtocolTask', function(){ /* noop */});

// And then as usual...
ga('send', 'pageview');

previous answer content :

The pokki solution suggested by Alex is working fine with a few adjustments to remove the need of Pokki.

I created a git project for this cleaned-up version here :

https://github.com/ggendre/GALocalStorage

Works great on android 4.1 and ios6, I will test more device very soon. Hope this helps ! :)


This is February 2017 and there is no need to edit analytics.js, nor for a library or plugin anymore, or at least I had no need for them. Many things that were said in the past years are deprecated or just obsolete, so here is my up-to-date comprehensive guide.

1. The config.xml file

In your config.xml, you must allow the cross-site request:

<access origin="https://www.google-analytics.com" />

2. The HTML

In your CSP meta tag, if you choose to have one, you must also allow calls to Google. It may look like:

<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: 'unsafe-inline' 'unsafe-eval' https://ssl.gstatic.com https://www.google-analytics.com;">

3. The javascript

Here is the commented code for a webapp that can run both in the browser and in a Cordova packaged app. You can ignore the else block if you don't care about the browser.

// the default GA code, nothing to change
(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');

var fields = {
  // note: you can use a single tracking id for both the app and the website,
  // don't worry it won't mix the data. More about this in the 3rd section
  trackingId: 'UA-XXXXXXXX-Y'
};

// if we are in the app (the protocol will be file://)
if(document.URL.indexOf('http://') !== 0){

  // we store and provide the clientId ourselves in localstorage since there are no
  // cookies in Cordova
  fields.clientId = localStorage.getItem('ga:clientId');
  // disable GA's cookie storage functions
  fields.storage = 'none';

  ga('create', fields);

  // prevent tasks that would abort tracking
  ga('set', {
    // don't abort if the protocol is not http(s)
    checkProtocolTask: null,
    // don't expect cookies to be enabled
    checkStorageTask: null
  });

  // a callback function to get the clientId and store it ourselves
  ga(function(tracker){
    localStorage.setItem('ga:clientId', tracker.get('clientId'));
  });

  // send a screenview event
  ga('send', {
    // these are the three required properties, check GA's doc for the optional ones
    hitType: 'screenview',
    // you can edit these two values as you wish
    screenName: '/index.html',
    appName: 'YourAppName'
  });
}
// if we are in a browser
else {

  ga('create', fields);

  // send a pageview event
  ga('send', {
    // this is required, there are optional properties too if you want them
    hitType: 'pageview'
  });
}

3. Your GA account

  • To monitor the traffic of the mobile app, create a view of the App type.

If you don't need to monitor the traffic of your web app from a website, you can stop reading here, otherwise read on. I assume you are using a single account for the tracking of both the website and the app.

  • Apply the custom filter named "Application? => yes" on the created view so that it will only show the screenview hits. There is an official guide here
  • Then, to track the traffic from the website, create a second view of the Website type. Apply a custom filter "Application? => no" on it.
  • If you want a merged view of your traffic online and in-app, create a third view of the App type. By default (without filter), it will show all data.

Additional notes

  • Everything goes over https now, no need for the http protocol anymore in your <access> and CSP
  • Be aware that writing *.google-analytics.com in the CSP would not work. Although that policy works in Chrome (56), it doesn't in Cordova (5.6.0)
  • Google analytics does not require any application permissions like ACCESS_NETWORK_STATE or ACCESS_WIFI_STATE like I've read elsewhere
  • All of this was tested with an Android app (I expect it to work in iOS apps as well), with the Crosswalk plugin installed