5

I have to use a local analytics.js that I serve from my server. I just want to use the local version if necessary - so is there a solution for checking if the call for analytics.js has failed?

I thought about checking it with a global window.onerror, but I don't think a failed call for an external file causes an error. I've tried checking if ga() is available, but it is even if analytics.js isn't loaded.

Any ideas? If you are wondering, not all users of this site has internet access, that's why I'm serving a local version. There is more things happening in this case, like adding a sendHitTask to redirect the answer from analytics.js to the local server.

EDIT A solution where you check if the user has Internet access would also be OK. But I have not found any solution for this either that works on all modern browsers.

Tony Gustafsson
  • 828
  • 1
  • 7
  • 18
  • What does console.log(window.ga) print when analytics.js isn't loaded? – Steven Wexler Mar 26 '15 at 15:25
  • Probably undefined, like yahoo.com – Huangism Mar 26 '15 at 15:26
  • @Huangism that's what I'd think too, but OP claims it exists even when analytics.js hasn't loaded. Are you defining ga somewhere else in your project? – Steven Wexler Mar 26 '15 at 15:28
  • 1
    It's not undefined in either case. ga() is defined in the GA snippet, and the ga() then loads the analytics.js. – Tony Gustafsson Mar 26 '15 at 15:30
  • 1
    The ga object is set up in the bootstrap code that is included in the page. It exists even when the analytics.js file is not loaded (which is kind of the point, it stores the interactions until they can be processed). So testing t his will not help. – Eike Pierstorff Mar 26 '15 at 15:31

3 Answers3

9

There's a function to track if the library has loaded. From the docs:

ga(function(tracker) {
   var defaultPage = tracker.get('page');
});

The passed in function is executed when the library is loaded, so you could set a variable to keep track of whether or not it has loaded. You'd have to put it on some sort of timer to decide when you want to consider it failed:

var loaded = false;
ga(function() {
   loaded = true;
});

// after one second do something if the library hasn't loaded
setTimeout(function(){
    if (!loaded){
        //do something
    }
},1000);
KTibow
  • 495
  • 6
  • 18
maembe
  • 1,270
  • 1
  • 13
  • 25
  • Awesome! I will try this tomorrow and let you know if it works! – Tony Gustafsson Mar 26 '15 at 16:57
  • Works great! First I use the normal snippet, run a ga('create') and requireing displayfeature and ecommerce. I than run this function to set gaIsLoaded to true (and also setting a sendHitTask), then i run the ga('send'). All this is queued if I understand this correctly... and when my normal snippet fails, it will load a local one a second later, and run all previous commands. – Tony Gustafsson Mar 27 '15 at 08:09
  • when I rename the tracker to something else, sometimes the callback function retrieves the tracker as undefined any idea why it happens? – Alfredo Esteban Hernndez Dvalo Apr 30 '20 at 17:55
  • @AlfredoEstebanHernndezDvalo When there's no default tracker, it will always include undefined in the callback. That still means that the library is loaded, so this code will still work just fine and you can still access your custom trackers within that callback, you just have to do it by name. – maembe Apr 30 '20 at 20:14
  • Hi @maembe thanks for your answer, but I tried also to get the custom trackers with the method ga.getAll(), and it is also not defined, so I think the method is executed when the library is still loading, I opened a ticket for it. Could you please have a look at it? https://stackoverflow.com/questions/61530268/analytics-js-callback-executed-before-library-is-loaded – Alfredo Esteban Hernndez Dvalo Apr 30 '20 at 22:07
6

instead of waiting for a callback, you can easily get it with

if(window.ga && ga.loaded) {
    // yeps... it is loaded!
}

you can easily see this in the Firefox documentation

same trick can be applied if you want to see if the tracker is blocked (by any plugin for example)

if(window.ga && ga.q) {
    // yeps... blocked! >:o
}
balexandre
  • 73,608
  • 45
  • 233
  • 342
1

A particularly elegant solution would be to use RequireJS and leverage its support for fallback paths. I do this on my site to load a stub version of analytics.js if loading GA fails because the visitor uses a privacy tool blocking the request:

http://veithen.github.io/2015/02/14/requirejs-google-analytics.html

Your use case is similar, except that you want to fallback to a complete local copy. You also probably don't want to change all calls to GA as described in that article. If that's the case then you could use a hybrid approach where you only use RequireJS to load analytics.js (Google's version or the local copy), without changing any other code.

Setting this up would involve the following steps:

  • Add RequireJS to your site and configure it as follows:

    require.config({
        paths: {
            "ga": [
                "//www.google-analytics.com/analytics",
                "local-copy-of-analytics"
            ]
        }
    });
    
  • Use the alternative version of the tracking code, but replace <script async src='//www.google-analytics.com/analytics.js'></script> with the following JavaScript code:

    require(["ga"]);
    
Andreas Veithen
  • 8,868
  • 3
  • 25
  • 28