前端 | Google Analytics加载失败导致的阻塞问题

Author Avatar
Ricardo Liu 11月 19, 2018
  • 在其它设备中阅读本文章

摘要:给网站配置了Google Analytics脚本后,在国内访问网站时,由于Google Analytics无法加载(一直处于pending状态),导致网页的整体渲染阻塞。本文提供了另一种异步加载Google Analytics脚本的方式来解决该问题。

01. 问题描述和原因分析

为了统计网站的访客情况,我是用了Google Analytics(下面简称GA)的服务。根据GA的文档,推荐插入跟踪代码的方式是使用全局网站代码,具体来说,是将下述代码插入要跟踪的每个网页的<HEAD>标记中(UA-XXXXX-Y需替换为要GA的媒体资源ID):

<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-XXXXX-Y"></script>
<script>
    window.dataLayer = window.dataLayer || [];
    function gtag(){dataLayer.push(arguments);}
    gtag('js', new Date());

    gtag('config', 'UA-XXXXX-Y');
</script>

插入上述代码后,网页渲染时执行的流程如下:

  1. 下载https://www.googletagmanager.com/gtag/js?id=UA-XXXXX-Y脚本(下面简称gtag.js),此过程不阻塞HTML的解析
  2. 下载完成后,立即执行gtag.jsgtag.js会在<HEAD>标签中插入异步执行的script标签<script type="text/javascript" async src="https://www.google-analytics.com/analytics.js"></script>
  3. 下载https://www.google-analytics.com/analytics.js脚本(下面简称analytics.js),此过程不会阻塞HTML的解析
  4. 下载完成后,立即执行analytics.jsanalytics.js会向https://www.google-analytics.com发送采集结果

上述过程需要从两个域名(www.googletagmanager.comwww.google-analytics.com)处下载脚本,而在国内,是无法访问上述两个域名的,ping的结果如下。

PING www-googletagmanager.l.google.com (6.6.6.6): 56 data bytes
Request timeout for icmp_seq 0
Request timeout for icmp_seq 1
Request timeout for icmp_seq 2
Request timeout for icmp_seq 3
Request timeout for icmp_seq 4
^C
--- www-googletagmanager.l.google.com ping statistics ---
6 packets transmitted, 0 packets received, 100.0% packet loss

PING www-google-analytics.l.google.com (6.6.6.6): 56 data bytes
Request timeout for icmp_seq 0
Request timeout for icmp_seq 1
Request timeout for icmp_seq 2
Request timeout for icmp_seq 3
Request timeout for icmp_seq 4
^C
--- www-google-analytics.l.google.com ping statistics ---
6 packets transmitted, 0 packets received, 100.0% packet loss

由于无法访问域名,更无法下载脚本,脚本会一直处于pending状态,在非常长的等待时间(默认状态约1min)后变为failed状态。

虽然GA提供的代码已经使用了script标签的async,使得脚本时异步执行的,下载脚本的过程不会阻塞HTML解析,但是由于下载迟迟没有完成,而下载的等待时间又远远长于页面加载时间,所以等待脚本下载失败的这个过程仍然会阻塞页面的最终渲染完成(包括部分图片和CSS渲染效果等),浏览器也会一直显示网页处于加载中,造成很差的用户体验。

GA还提供了另一种直接将analytics.js添加到网站中的方式,但由于www.google-analytics.com无法访问,所以问题是一样的。

02. 解决办法

首先想到的解决方式是将gtag.jsanalytics.js两段脚本存储到本地,这样就不需要从GA的服务器端获取脚本了。这种办法可以解决下载脚本造成pending的问题,但是由于analytics.js需要向https://www.google-analytics.com发送采集结果,这一步骤无法完成,仍然会造成阻塞。

更彻底的解决方案是,在网页完全渲染完成之后,再开始下载和执行GA相关的脚本。我们可以将这一过程与网页渲染分隔开来,这样在用户看来,浏览器上呈现出的网页已经渲染完成了,渲染速度只取决于网页本身。至于GA的脚本加载成功与否,对用户的体验没有影响。

基于上述思路,只要我们在网页元素load事件完成之后,再插入script标签并执行即可。插入的代码如下。经过试验,按照如下方式插入的GA脚本,能够正常进行统计。

<!-- Global site tag (gtag.js) - Google Analytics -->
<!-- Modified By Ricardo (Tongtong) Liu -->
<!-- <script async src="https://www.googletagmanager.com/gtag/js?id=UA-XXXXX-Y"></script> -->
<script>
    window.dataLayer = window.dataLayer || [];
    function gtag(){dataLayer.push(arguments);}
    gtag('js', new Date());
    gtag('config', 'UA-XXXXX-Y');

    window.addEventListener('load', function(){
        var s = document.createElement('script');
        s.src = "https://www.googletagmanager.com/gtag/js?id=UA-XXXXX-Y";
        document.body.appendChild(s);
    });
</script>

当然从用户的角度来看,将www.googletagmanager.comwww.google-analytics.com添加到默认走代理的list中,是更普适的解决办法…

03. 参考资料