解决 instantclick 与网站统计工具的矛盾问题

in 网站优化 with 0 comment

博客使用了 instantclick.js,整体上成为了单页应用,此时一般的统计工具无法使用,或是新页面不发送统计数据,或是出现单个页面多次发送统计数据的问题。

首先,说明一下,我使用了三种统计工具(其实一个就够了),包括著名的 Google Analytics,国内常用的 Baidu 统计以及自建的 matomo 统计工具。

统计原理

matomo 是一个著名的开源统计工具,这里就以它为例,简单说明一下统计的原理。

<!-- Matomo -->
<script type="text/javascript">
  var _paq = window._paq || [];
  /* tracker methods like "setCustomDimension" should be called before "trackPageView" */
  _paq.push(['trackPageView']);
  _paq.push(['enableLinkTracking']);
  (function() {
    var u="//matomo.onesrc.cn/";
    _paq.push(['setTrackerUrl', u+'matomo.php']);
    _paq.push(['setSiteId', '1']);
    var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
    g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
  })();
</script>
<!-- End Matomo Code -->

三个统计工具的原理类似,都是异步引入脚本,同时脚本外引入一个统计变量(通常为数组,上例中为 paq)。如果脚本先完成引入,其后才是定义统计变量,根据代码也可以看出来,此时的统计变量则直接使用定义好的 paq,否则则是先定义 paq,引入的脚本直接使用这个变量。猜想引入的统计脚本里面应该也有一句 var _paq = window._paq || [],这样,无论二者哪个先执行,都能保证最后数据和属性的互通。

如何改进

根据上面的原理可以知道,把二者分离就可以了。但遗憾的是,分离后的代码也不能直接使用,必须将它们分为两部分,脚本的使用和脚本的引入。就像之前提到的那样,二者的顺序不影响使用,我个人习惯把脚本的引入放到后面。

Matomo

根据官方文档,大致可以这样配置。

//初始化部分,调用一次即可
window._paq = window._paq || [];
_paq.push(['setTrackerUrl', 'https://matomo.onesrc.cn/matomo.php']);
_paq.push(['setSiteId', '2']);
//统计部分,调用该部分会发送数据
_paq.push(['setCustomUrl', window.location]);
_paq.push(['setDocumentTitle', document.title]);
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);

setCustomUrl 和 setDocumentTitle 必须调用,如果没有这两条而仅仅使用 trackPageView,就会导致所有发送的网站信息都是初始化页面的信息。猜测是在脚本引入时把初始页面的信息保存了下载,此后发送统计信息时直接发送这些信息,而不是发送时重新自动获取,所以每次发送统计数据前都必须重新设置该项。

Baidu

百度处理起来比较简单,提供了供单页应用使用的脚本(使用前需要在百度统计>管理>单页应用打开设置),自动监测路由变化,智能的根据 history 自动发送统计信息。

//初始化一次即可,此后无需手动调用
window._hmt = window._hmt || [];
_hmt.push(['_requirePlugin', 'UrlChangeTracker', {
    shouldTrackUrlChange: function(newPath, oldPath) {
        newPath = newPath.split('#')[0];
        oldPath = oldPath.split('#')[0];
        return newPath != oldPath;
    }
}]);

Google Analytics

//初始化部分
window.dataLayer = window.dataLayer || [];
function gtag() {
    dataLayer.push(arguments);
}
gtag('js', new Date());
//统计部分
gtag('config', 'UA-132229115-2', {
    'page_path': window.location.pathname + window.location.search
});

最终结果

初始化部分:

<script data-no-instant>
    //<!-- Matomo -->
    window._paq = window._paq || [];
    _paq.push(['setTrackerUrl', 'https://matomo.onesrc.cn/matomo.php']);
    _paq.push(['setSiteId', '2']);
    //<!-- End Matomo Code -->

    //<!-- Baidu -->
    window._hmt = window._hmt || [];
    _hmt.push(['_requirePlugin', 'UrlChangeTracker', {
        shouldTrackUrlChange: function(newPath, oldPath) {
            newPath = newPath.split('#')[0];
            oldPath = oldPath.split('#')[0];
            return newPath != oldPath;
        }
    }]);
    //<!-- End Baidu Code -->

    //<!-- Global site tag (gtag.js) - Google Analytics -->
    window.dataLayer = window.dataLayer || [];

    function gtag() {
        dataLayer.push(arguments);
    }
    gtag('js', new Date());
    //<!-- End Google Analytics -->

    InstantClick.on('change', function(isInitialLoad) {

        _paq.push(['setCustomUrl', window.location]);
        _paq.push(['setDocumentTitle', document.title]);
        _paq.push(['trackPageView']);
        _paq.push(['enableLinkTracking']);

        gtag('config', 'UA-132229115-2', {
            'page_path': window.location.pathname + window.location.search
        });

    });
    InstantClick.init('mousedown');
</script>

脚本引入部分:

<script type="text/javascript" async defer src="https://matomo.onesrc.cn/matomo.js" data-no-instant></script>
<script type="text/javascript" async defer src="https://hm.baidu.com/hm.js?821e8537385c0051552f4b6be4556e0c" data-no-instant>
</script>
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-132229115-2" data-no-instant></script>

同样附上改进后的截图

image-20200312224950195.png

可以看到三个统计工具都有正确发送统计数据。

参考链接

Matomo und AJAX Requests

Single-Page Application Tracking

单页应用跟踪

上一篇: 结合 bootstrap-vue 实现一个全局 confirm 方法
下一篇: js 表单错误:form.submit() is not a function
Responses