This has been bugging me for a few days now and I have not found a way to get it to work. My site is using Jquery, Jquery-Mobile and RequireJS and I want to add Google Analytics to the mix.
My Analytics setup is like so (see also here):
<script type="text/javascript">
var _gaq = _gaq || [];
(function() {
... regular stufff
})();
// bind to pageshow event
$(document).on('pageshow', 'div:jqmData(role="page").basePage', function (event, ui) {
try {
_gaq.push(['_setAccount', 'ID';
_gaq.push(['_gat._anonymizeIp']);
var url = location.href;
try {
if (location.hash) {
url = location.hash;
}
_gaq.push(['_trackPageview', url]);
} catch(err) {}
});
</script>
So I’m listening for the JQM pageshow event to track for Analytics. This snippet is pasted into the end of all pages.
I have fiddled Analytics into requireJS like this:
Main.js:
require.config({
baseUrl: "../js/",
paths: {
"jquery": "libs/jquery/jquery.min",
"jqm": "libs/jquery-mobile/jquery-mobile.min",
"analytics": "https://www.google-analytics.com/ga"
}
require(['order!jquery', 'order!jqm', 'order!analytics', 'app'],
function(jquery, jqm, analytics, App){
App.start();
});
And in App.js:
var start = function() {
require(['order!jquery', 'order!jqm', 'order!analytics'],function() {
// do stuff
});
Problem is, the Analytics snippet is at the end of every page HTML markup, so although I think I have set it up correctly in requireJS with Jquery and Jquery Mobile loading before, I’m still getting an error:
$ is not defined
....ocument).on('pageshow', 'div:jqmData(role="page").basePage', function (event, ui...
when the first page loads.
I guess because HTML markup is outside the reach of require and is parsed before JQM is loaded. Still, there has to be a way to set this up properly.
Question:
Any idea why the error pops up and what I can do about it?
Thanks for help!
EDIT:
Ok. Doing it like this works:
Inside my page header I’m declaring the first part:
<script type="text/javascript">
var _gaq = _gaq || [];
(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>
Then inside my requirejs start function I’m calling the 2nd snippet:
var start = function() {
require(['order!jquery', 'order!jqm'],function() {
var analyticsHasBeenSet;
...
var analyize = function () {
if ( analyticsHasBeenSet != true ){
analyticsHasBeenSet = true;
require(['https://www.google-analytics.com/ga.js'], function (App) {
$(document).on('pageshow', 'div:jqmData(role="page"), function() {
_gaq.push(['_setAccount', '']);
_gaq.push(['_gat._anonymizeIp']);
var url = location.href;
try {
if (location.hash) {
url = location.hash;
}
_gaq.push(['_trackPageview', url]);
} catch(err) { // error catch }
});
});
}
}
analyize();
This way the 2nd snippet will only be executed once Jquery and Jquery Mobile have been loaded. By setting a global variable (I hope) the binding will only be initiated once. So far seems to work.
The problem is most likely around your use of the order! plugin. This should only be used with standard .js files, and not modules.
http://requirejs.org/docs/api.html#order
Your analytics path should be modified to be a traditional js file (as ga.js does not register itself as a module)
jQuery and jQuery mobile do register themselves as modules, so your config for those is correct.
In your require call, all you need is:
Seeing as the ga.js is the only file that isn’t a module, the order! plugin will probably be of little use as it only matters when you have multiple traditional scripts that need to load in a certain order.
However, it is worth noting that the code snippet provided by Google for using Google Analytics already accounts for async loading so it might be unnecessary to use Require at all.