06月08, 2018

埋点统计的一些补充

最近同事在用我之前写的js,然后出现了一些问题。包括后面新加了两个需求,踩了一些坑,在此做一个简单的笔记。

用法出错?

因为我之前用rollup导出了一个umd的文件,理论上使用es6 import的语法是没什么问题的。

然而同事告诉我,在他用我的js文件后,出现如下的错误:

alt

然而我在本地测试了一下,却怎么也还原不出来。

直到后面和另外一个同事调试相同的情况,我才发现在他的babel配置中用了’transform-runtime‘这个插件,导致了这个问题。

要解决这个问题,倒也容易,在loader的js配置中,把这个文件剔除掉,或者用npm包的形式,然后exlude整个node_modules

然而这让我想到了另外一个之前看的文章(关于优化 前端代码的):Deploying ES2015+ Code in Production Today

在文中有提及:

The main gotcha for this technique currently is most module authors don’t publish ES2015+ versions of their source code, they publish transpiled, ES5 versions.

给了一个解决方案:

alt

那么就跟我上面说的有冲突了。其实我个人还是推荐在业务的项目中使用babel-polyfill,而不是transform-runtime。(毕竟有毒)

统计手机型号

业务方的同事提出需要统计一下手机型号。他们给我看了一份excel清单,看到里面能统计出华为荣耀,红米等,都我看蒙了。

我一问,原来之前是后端java实现,根据useAgent来请求一个接口,然后拿到数据。

和他们沟通一下,就是像安卓机的话,只要拿到带有Build/的那一段就行了,如:

alt

苹果机最好能分析出相应的型号,如iphone5 iphone6这样的。

在网上看到一篇文章JS获取手机型号和系统

获取iphone型号的思路清奇,利用了canvas,也是屌。不过在实际测试中,发现他给的设备对应的屏幕大小有些些问题,且没有iphone8、iphoneX这些数据。

这里感谢下我的同事,整理了一份新的出来:

var devices = {
    "PowerVR SGX 543": {
        1136: ["iphone5c"]
    },
    "Apple A7 GPU": {
        1136: ["iPhone 5", "iPhone 5s"]
    },
    "Apple A8 GPU": {
        1334: ["iPhone 6"],
        2208: ["iPhone 6 Plus"],
    },
    "Apple A9 GPU": {
        1136: ["iPhone SE"],
        1334: ["iPhone 6s"],
        2208: ["iPhone 6s Plus"]
    },
    "Apple A10 GPU": {
        1334: ["iPhone 7"],
        2208: ["iphone 7 Plus"]
    },
    "Apple A11 GPU": {
        1334: ["iphone 8"],
        2208: ["iphone 8 plus"],
        2436: ["iphone X"]
    }
};

计算页面停留时间

说真,现在越来越多的SPA项目出现,所以在路由里面计算一下,已经是相当容易了。

但是之前的老系统,用的还是多页,然后业务方需要计算一下页面停留时长。

业务方在邮件中提及:

之前尝试在页面关闭或跳转前上传统计代码,浏览器关闭、页面跳转都有可能导致请求的丢失,丢失率比较大。所以只统计过程中的页面,最后一个访问页面(包括关闭浏览器,没有下一步页面操作等)不采集。

说人话,就是统计上一个页面的时间。

解决思路似乎很简单:记录当前页的访问时间到cookie,然后下一个页面进去后,取出cookie,用当前时间-cookie,就是上一个页面停留时间。

说到cookie的存取,前阵子这边页面刚好出了一个问题,就是取不到cookie,最后排查到的原因是在www二级域名下写进去cookie,但跳的时候,变成了没有www(即主域),这样就拿不到了。所以设cookie的时候,最好能加上domain(主域)。

在网上看到有一段获取主域的js代码:

function getMainHost() {
    let key = `mh_${Math.random()}`;
    let keyR = new RegExp(`(^|;)\\s*${key}=12345`);
    let expiredTime = new Date(0);
    let domain = document.domain;
    let domainList = domain.split('.');

    let urlItems = [];
    // 主域名一定会有两部分组成
    urlItems.unshift(domainList.pop());
    // 慢慢从后往前测试
    while (domainList.length) {
        urlItems.unshift(domainList.pop());
        let mainHost = urlItems.join('.');
        let cookie = `${key}=${12345};domain=.${mainHost}`;

        document.cookie = cookie;

        //如果cookie存在,则说明域名合法
        if (keyR.test(document.cookie)) {
            document.cookie = `${cookie};expires=${expiredTime}`;
            return mainHost;
        }
    }
}

写完这个需求之后,我想了一下,发现两个问题:

  • 从A页面跳到B页面,然后B页面刷新,这时候是不应该上报数据了
  • 从A页面跳百度,再通过浏览器的后退回到A页面,这时候也不应该上报数据

针对第一种情况,我想出的方案是通过sessionStorage,然后对比当前的location.href,来判断是新进入还是刷新。

其实这个判断有点小问题,比如说www.a.com/a/bwww.a.com/a/b?a=1&b=2,这两个在我看来,如果用户手动加了一些参数或者减了一些参数,也不应该上报数据。

针对第二种情况,我一时半会儿想不出啥方案,有点头大。

另外,我发现我之前对cookie的过期时间是session有一个认知上的错误:

它不是指tab关闭了,cookie就会清除掉,而是指整个浏览器关闭才会清除。

还有,像chrome现在表示过期时间是session的情况,都是用1969年12月31号来替代了,截图如下:

alt

总结

一个东西看似做出来了,还是需要别人不断地帮你踩坑,给你提建议,提需求,才能把东西越做越好。

本文链接:www.my-fe.pub/post/collection-js-sdk-supplement.html

-- EOF --

Comments

评论加载中...

注:如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理。