Stop Analytics Code from Blocking other Script Exe

2019-09-14 00:30发布

问题:

I am using the recommended implementation of the tracking code.

<script type="text/javascript">    
  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-XXXXX-X']);
  _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>

I often get this wait on load of my web pages as "waiting for www.google-analytics.com". Initially I thought it was my office firewall, but I guess it is common issue. search

My bigger concern is all the scripts on my page stop execution during this wait... which never goes away. How to fix this ?

I thought async means it will not interfere with other scripts on page.

回答1:

The solution

Since you are using Jquery, wrap the google analytics code in a jQuery's window load handler:

$(window).load(function(){
    var _gaq = _gaq || [];
    _gaq.push(['_setAccount', 'UA-XXXXX-X']);
    _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);
    })();
});

The explanation

In a comment, you pointed out that you use http://supersimpleslider.com/ and that it would not work as long as google analytics was hanging. A look at the source of that library shows this at line 86:

$(window).load(function() {

I decided to test event firing by simulating a hanging resource.

ga.php

<?php
sleep(5);
exit('content.log("ga.php available")');
?>

index.html

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    </head>
    <body>


        <script src="jquery-1.11.3.min.js"></script>


        <script type="text/javascript">
            window.addEventListener('load', function(){
                console.log('window-load');
            }, false);
            window.addEventListener('DOMContentLoaded', function(){
                console.log('window-DOMContentLoaded');
            }, false);
        </script>


        <script type="text/javascript">
            $(window).load(function() {
                console.log('window-jquery-load');
            });
            $(window).ready(function() {
                console.log('window-jquery-ready');
            });
        </script>


        <script type="text/javascript">
            document.addEventListener('load', function(){
                console.log('document-load');
            }, false);
            document.addEventListener('DOMContentLoaded', function(){
                console.log('document-DOMContentLoaded');
            }, false);
        </script>


        <script type="text/javascript">
            $(document).load(function() {
                console.log('document-jquery-load');
            });
            $(document).ready(function() {
                console.log('document-jquery-ready');
            });
        </script>



        <script type="text/javascript">
          (function() {
            var ga   = document.createElement('script');
            ga.type  = 'text/javascript';
            ga.async = true;
            ga.src   = 'ga.php';

            var s = document.getElementsByTagName('script')[0];
            s.parentNode.insertBefore(ga, s);
          })();
        </script>
    </body>
</html>

Console output

16:21:19.123   window-jquery-ready
16:21:19.124   document-jquery-ready
16:21:19.125   document-DOMContentLoaded
16:21:19.126   window-DOMContentLoaded
16:21:24.092   ga.php available
16:21:24.095   window-load
16:21:24.096   window-jquery-load

Conclusion

  • native DOMContentLoaded is not affected by hanging resources.
  • jQuery's ready is not affected by hanging resources.
  • window load will wait for all resources to complete.
  • document load will never fire (could be browser dependent though)

Since supersimpleslider is waiting for a load event on window, a hanging ga.js will impact its execution. This might also be the case for other scripts.

By inserting google analytics only at window load, we put all the scripts on the same level.

Console output after window load wrapping:

16:47:27.035   window-jquery-ready
16:47:27.036   document-jquery-ready
16:47:27.036   document-DOMContentLoaded
16:47:27.037   window-DOMContentLoaded
16:47:27.043   window-load
16:47:27.044   window-jquery-load
16:47:32.052   ga.php available


回答2:

there are two ways I know of for running non blocking js: 1- put your script tag before the closing tag of body 2- add 'async' attribute to the script, the end result will look like, note that this is for remote file inclusions:

<script src="script.js" async></script>

and the is the async you are finding in ga.aync=true, it prevents the blocking of the page rendering until the file is loaded, but it has no effect of what happens after the code is run, so, in other words, the created script tag (by running that code' allows the browser to do its job even while the file is being downloaded.

the code you provided, merely, creates a script tag to include ga.js before the first script tag in the page(which will be in the head normally).

so with that out of the way, the only option left is to run your script before the closing tag of the body, so that it runs after the page is parsed.

On another note, my advice to you is to learn about something called 'critical rendering path' of the browser, it explains why some stuff are blocking and best practices for using external files on your pages.

I hope this helped