Using Google Analytics with jQuery Mobile

I upgraded Crossword Tracker to use jQuery Mobile at the end of November and while it has proven popular, I had a sneaking suspicion my Google Analytics reports were off. The Pages/Visit statistic was quite low (very close to 1 in fact). It turns out that jQuery Mobile requires a little extra effort to execute Javascript on every page load. I broke up the Analytics code into two pieces and now every page view is being tracked.

In the head (which is executed only on the first page load) I load the required Javascript file from Google, using the async loader which means it won’t block page loading:

Originally I had the whole snippet from Google there and it counted just one view, no matter how many pages the user actually viewed. That’s because it’s not actually loading the whole other page, but requesting it with AJAX and then replacing parts of the page with new content. The trick to getting all page views counted is splitting up the part that tracks the page view. Here’s what I tucked in before the closing body tag:

The pageshow event is triggered by jQuery Mobile on every page load (including the first), so we’re now calling the _trackPageview() method on every load. Handy. After just a day and a half’s worth of use, you can tell what a difference it made:

This all may change before jQuery Mobile hits 1.0, but for now I’m safely on the bleeding edge and have the analytics to back it up.

Update: jQuery Mobile falls back to using hashes to designate pages and that doesn’t get picked up by GA so / and /#/contact would both appear to be a hit on the homepage. You can easily get around this by checking for the hash and then sending the portion after the # symbol. I have updated the code above to account for this as well as moving to the asynchronous loader which makes a decent difference over 3G.

Update 2: I’m no longer using jQuery Mobile on Crossword Tracker because the way it works conflicts with Google Adsense. Mobile traffic has been steadily increasing and now makes up close to 50% of Crossword Tracker’s traffic.

Jon,
For whatever reason, GA is not seeing the code. Never getting a good status on it. If I do a view source, I can see it. I think originally I had my GA set up wrong, was under my main domain. Just created a new account for the different subdomain. I also mis-read your post on how to set up, but have corrected that. So, I have placed the 1st script in the head section, then the last script right before the closing end tag. For a single html, with multiple pages defined, do you get every unique page logged with this?

Do you have a link I can check out? I am getting every page view logged (previously I was getting just one per visit because jQuery Mobile was not triggering the JS on subsequent loads because it’s actually just an AJAX call).

Jon,
Just looked at my GA site and it says, it’s been successfully installed and is collecting data. Must have been a delay in getting updated. Will watch to see how things are collected now. Thanks for all of your help.

Are you actually seeing accurate results here? Is Google Analytics smart enough to figure out the special hash stuff done w/ the AJAX loading? It seems to me that the first page the user visits will continue to be reported for every “new” page visited by AJAX… am I wrong?

Jon,
It appears I’m getting traffic now. Wondering how you have your’s defined. I have one html page, with really a number of #pages internally. I would like to see “individual” page views withing the main page. Wondering if you have come across this. Looks like there are some additional logging you can do with GA. You have to pass some logging details. Just curious if you had this need.

For testing I would add a alert or console.log to make sure that your are not getting multiple hits for one page when viewing the same page multiple times fist time one alert second time 2 third time 3 etc…, I am looking into fixing that is what brought me here.

I have updated the page with what I am using now, it tracks all page views. The trick is to check for a hash and then attach it along with the trackPageview request. I also go ahead and strip out the # so that the paths all line up with the desktop based stats. jQuery Mobile beta 3 uses HTML5 history push state, which means the URL actually changes and not just a hash, so this will probably be a moot point here shortly (Mobile Safari and Browser on Android both support the feature).

Hi Jon, thanks for the code. I was wondering if I need this since I don’t use pages with a hash? Or if the last comment about HTML5 push states affects this now that RC1 is out? I mostly use separate single pages for everything, but realize those could still be loaded through AJAX. I just don’t want to go the other way where page views are being recorded multiple times.

The hash bit only helps in that you don’t have to jump through hoops to tell Google which page is being visited (anything after the hash isn’t sent in the referrer, so in that case you need to send it manually). The code is still needed though to tell Google about the page load. Since the code I posted is triggered through an event from jQuery Mobile, it won’t be run when viewed outside of an AJAX jQuery Mobile request–you should not have double counts. However I’d still recommend testing first by using some console.log() entries and watch your network log just to make sure.

Could you elaborate a little on where to put the $(‘[data-role=’page’]).live(‘pageshow’) handler? You casually mention putting it “before the closing body tag.” So does this mean I can put it anywhere inside the body tag? Can I not put it in the header right after the jQuery(Mobile) scripts?

I originally had it in scripts that were loaded after the body, and that didn’t work. Today I followed your advice, and now I’m waiting for Analytics data to show up.

The idea of having it far down in the body (before the close but after your stuff) is because it will execute after your other stuff and not block loading. For something like stats you really don’t want to slow the user down. With jQuery Mobile you are going to have the same page loaded for the duration of the visit, so there is really no rush to creating the event handler.

You can test that it’s working by turning on developer tools in your browser and seeing if requests are being sent to Google on each page load. I use Chrome and that’s viewable in the Network panel of Developer Tools.

Fabulous! I didn’t even know what we were missing until I stumbled upon this. Fired up the GA real time beta, watched what was happening as I browsed mobile. Nada… only first page or refreshes. Put in your changes and bam! So this is working with the released version of JQM just in case anyone else is wonder.

Yes, that technique is to track low-end feature phones (“WAP-based phones or other low-end mobile devices that can’t execute JavaScript”). The above technique is for Javascript apps that don’t have normal page views and load stuff in and out of the DOM.

Sure, the way jQuery Mobile works is by manipulating the DOM to add to content. You stay on the same “page”, but the page changes with new content loaded in. The way AdSense works is by targeting advertising to the specific page. If you don’t change pages, you don’t change ads. The embed code does not work with JQM’s “soft” page loads (say your ad is in the new content fetched and replaced into the DOM–that ad won’t load). Or at least that’s how it worked when I wrote this post years ago.