Here is my first experiment in integrating Google Analytics and jQuery Mobile. I've been trying to get this working off and on the last week or so, but I finally figured out my mistake this morning. Please consider this a proof of concept. It seems to be working ok now, but I bet there are about ten different ways to do this better. That being said - let's look at the code.
First, here is the page without any analytics code at all.
<div data-role="page"> <div data-role="header">
<h1>Home</h1>
</div> <div data-role="content">
<ul data-role="listview" data-inset="true">
<li data-role="list-divider">Options</li>
<li><a href="products.html">Products</a></li>
<li><a href="members.html">Members</a></li>
<li><a href="#about">About</a></li>
</ul>
</div> <div data-role="footer">
<h4>Page Footer</h4>
</div> </div> <div data-role="page" id="about"> <div data-role="header">
<h1>About</h1>
</div> <div data-role="content">
<p>
This is demo content.
</p>
</div> <div data-role="footer">
<h4>Page Footer</h4>
</div> </div> </body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>Analytics Demo</title>
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0a4.1/jquery.mobile-1.0a4.1.min.css" />
<script src="http://code.jquery.com/jquery-1.5.2.min.js"></script>
<script src="http://code.jquery.com/mobile/1.0a4.1/jquery.mobile-1.0a4.1.min.js"></script>
</head>
<body>
It's a simple page with 3 links. As you can see, the About page is included in the same source, and products and members are separate pages. As they are very similar, I'll show one of them:
<div data-role="header">
<h1>Products</h1>
</div> <div data-role="content">
<ul data-role="listview" data-inset="true"> <div data-role="footer">
<h4>Page Footer</h4>
</div> </div>
<div data-role="page">
<li><a href="apples.html">Apples</a></li>
<li><a href="oranges.html">Oranges</a></li>
<li><a href="cherries.html">Cherries</a></li>
</ul>
</div>
This page leads to 3 more - all of which are the same except for their names. Here is apples.html:
<div data-role="header">
<h1>Apples</h1>
</div> <div data-role="content">
<p>
This is for apples.
</p>
</div> <div data-role="footer">
<h4>Page Footer</h4>
</div> </div>
<div data-role="page">
Ok - so now to the analytics. I knew I was going to use asynchronous tracking which is described in Google's docs here: Tracking Site Activity. This involves placing the core tracking code in the head of your document. So in my initial file I did so:
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-70863-15']);
_gaq.push(['_trackPageview']); (function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})(); </script>
<script type="text/javascript">
Now for the tricky part - and the part I screwed up on. According to the docs, I needed to make use of trackPageview, a function that allows you to asynchronously register a page view event. jQuery Mobile fires an event when pages are loaded. I made use of that event to wrap a call to trackPageview:
$("div").live("pagebeforeshow",function(event,ui) {
var header = $("div[data-role='header'] h1",$(this));
var title = $.trim(header.text());
modtitle = "/" + title + ".html";
console.log(modtitle);
_gaq.push(["_trackPageview",modtitle]);
});
What this code does is listen for the pagebeforeshow event. This is one of many events you can listen to. (More information on events may be found in the docs.) When a page is shown, I use jQuery to grab the text out of the header. If you look at the page example above, you can see I include a title there that represents the page. With that I create a URL of the form: "/" + title + ".html." Here is where I screwed up. See the push event? It takes an array. My eyes missed that the first 10 times I looked at the code. Simply add [ and ] around the arguments seemed to fix everything:
Any comments on this technique? You can see the full code here: http://www.coldfusionjedi.com/demos/gajqm/ Although obviously you won't be able to view my analytics.
Archived Comments
May be worth noting that the page events in jQuery mobile need to be defined between the jquery script and the jquery mobile script (lines 6 & 7 in your first example). Anywhere else and it MIGHT fire, but can be a bit unpredictable.
Interesting. Is that in the doc? I'm not seeing it.
Eric might talking about "Also, for these handlers to be invoked during the initial page load, you must bind them before jQuery Mobile executes. This can be done in the mobileinit handler, as described on the global config page."
documented under
http://jquerymobile.com/tes...
You might also want to remove _gaq.push(['_trackPageview']); from the initialization block, otherwise first page is counted twice - pagebeforeshow event fired for it as well.
Yes, exactly what Pritesh said, probably should have included the link myself.
Actually, to clarify a bit more, assuming the code was not between jQuery and jQuery Mobile it would still work on every page except the first, possibly explaining why it appeared to be working in your tests. The jQuery mobile code executes immediately not onDocumentReady, so the pagebeforeshow handler needs to be defined before the jQuery mobile code executes and shows the first page. If it's defined after, since it is a "live" event, it will still fire before every other page show.
Bam - Pritesh - thank you. Not sure how I missed that.
@Jura - very good point.
Guys - going to rebuild this and report a follow up.
this is cool stuff...is there any recommended IDE for developing and simulating Jquery Mobile apps?
Thanks
Consider jQuery Mobile is -very- simple (90% of it is just HTML!), any editor would do. I use ColdFusion Builder. Adobe has announced good support for jqm in Dreaweaver CS 5.5 though. As soon as I can publicly blog about it, I will.
Oh - if you google for Dreamweaver CS 5.5 you can find a few articles out there already - from Adobians - with screen shots. Even a video on Adobe TV I think.
thanks i will check it out!
Guys, I've posted an update here:
http://www.coldfusionjedi.c...
You can view source obviously. ;) Any comments? I think this is "more proper" but before I blog it I'd like a second (third, etc) set of eyes.
Hi Raymond,
May I ask you please to confirm if my code below is correct for subdomain:
Source: http://www.coldfusionjedi.c...
I should replaced:
_gaq.push(['_setAccount', 'UA-xxxxxxxx-x']);
with:
_gaq.push(['_setAccount', 'UA-xxxxxxxx-x']);
_gaq.push(['_setDomainName', '.myDomainName.com']);
/*_gaq.push(['_trackPageview']);*/
Thank you,
It seems ok. Please test and let us know. When things 'worked right' for me, I saw results in about 4 hours. If you test in the morning and then check at lunch, you should be able to confirm. Just note that - at least for me - Google Analytics defaulted to having it's date filter end on yesterday I believe. You may have to tweak it to include today ("today" being the day you test).
Code above for subdomain seems to work fine on Google Analytics.
Thank you Raymond (apologize for delay)
No problem on the delay. Thanks for letting us all know.
Thanks for the great write up! Have a related philosophical question about this. If you have your mobile site off a separate subdomain "m." would you recommend creating a separate analytics profile or combining (http://code.google.com/apis... it with the desktop web version? I wonder if there could be useful data from having the subdomains combined, or if doing so will foul up historical data.
Wow, would "I have no idea" be an acceptable answer? :) Maybe someone else in the thread here will know. I'd guess that it would make sense to use the same account, but I don't have any real proof to back that up.
Thanks for the post. Its a good one