页面跳转时,统计数据丢失问题探讨

标签: 发现 | 发表时间:2016-03-02 00:09 | 作者:小胡子哥的个人网站
出处:http://www.blogread.cn/it/

标签:   统计   跳转

为了更好地了解用户对产品的使用情况,业务中,我们经常会收到埋点统计的需求,比如:

  1. 收集一段时间内用户光标在页面中的运动情况,包括光标移动、点击等行为

  2. 统计用户滚屏行为

  3. 统计用户在站点的停留时长

  4. 收集页面链接的点击数量等


无论是移动端还是 PC 端,相信很多朋友都遇到了这么几个十分让人头疼的问题:


  1. 统计某个链接的点击量,但是这个链接点击后直接跳转走了

  2. 统计页面时长问题,unload 的时候发送的统计丢失了

  3. 统计脚本还没有初始化,用户不感兴趣已经走人了等

如果我们把这样的数据交给了产品同学,可能会让他们对用户行为产生错误的认知,一定程度上影响产品的下一步改善。

传统解决方案

上面提到的问题,从技术角度可以归纳为两点:


  1. 用户关闭页面过早,统计脚本还未加载/初始化完成

  2. 用户关闭或者跳出页面的时候,请求未发出


针对第一点,概率较小,一般的处理方式就是,不要把统计脚本参合到其他脚本中,单独加载,并且放在前头,让它优先加载。很多公司的做法是,不让开发者关心统计脚本的加载,用户请求页面的时候,Nginx 会在 Body 开始标签位置注入一段脚本。

对于问题二,处理方案就有很多了。


1. 阻塞式的 Ajax 请求


还记得 XMLHttpRequest::open 方法的第三个参数吧,如果设置为 false 就是同步加载,


window.addEventListener('unload', function(event) {

 var xhr = new XMLHttpRequest(),

 xhr.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");

 xhr.open('post', '/log', false); // 同步请求

 xhr.send(data);

});


阻塞页面关闭,当然可以在 readState 为 2 的时候就 abort 请求,因为我们不关心响应的内容,只要请求发出去就行了。


2. 暴力的死循环


原理跟上面类似,只不过是使用一个空的死循环阻塞页面关闭,


window.addEventListener('unload', function(event) {

 send(data);

 var now = +new Date;

 while(new Date - now >= 10) {} // 阻塞 10ms

});


3. 发一个图片请求阻塞


大部分浏览器都会等待图片的加载,趁这个机会把统计数据发送出去


window.addEventListener('unload', function(event) {

 send(data);

 (new Image).src = 'http://example.com/s.gif';

});


以上提到的几个方案都是一个原理,让浏览器继续保持阻塞状态,等数据发送出去后再跳转,这里存在的问题是:


  1. 少量浏览器下可能不奏效

  2. 等待一会儿再跳转,用户体验上打了折扣,尤其是移动端上


是否有更好的方案解决这个问题呢,前端同学秉着「小强精神」也提出了两个可实践的方案。


优化方案


不就是埋点统计数据嘛,非得在当前页面发送出去?优化方案的思路具有一定的跳跃性,我们考虑将数据在下跳页中发送,那么问题就转换为,如何将数据传递给下跳页?


对于链接点击量的统计,我们可以将链接信息通过 url 传递给下跳页,传递思路如下:


1. url 传参


通过数组标识一个链接的位置信息,如 [站点id,页面id,模块id,链接index],通过四个参数可以惟一标识链接位置属性,使用 URL param 参数将数组数据传递给下跳页,等待由下跳页将数据发送出去。


这里存在的问题是,下跳页中必须部署同样的统计脚本,但对一个系统来说,这是很容易做到的。我们也不会在自己的网页上放其他网站的链接吧,所以整个数据的统计都在一个闭环内。


2. 通过 window.name 传递数据


window.name 是浏览器给我们开放的一个接口,设置该属性的值后,即便页面发生了跳转,这个值依然不会变化,并且可以跨域使用。


这里存在的问题是,该属性可能被开发者用于其他途径。我们可以限制开发者直接使用 window.name,封装接口,通过接口调用,如 aralejs 提供的 nameStorage,


nameStorage.setItem(key, value);

nameStorage.getItem(key);

nameStorage.removeItem(key);


储存形式为:


scheme                  nameStorage datas

 |                            |

------------           ------------------------

nameStorage:origin-name?key1=value1&key2=value2

-----------

|

window origin name


以上虽然基本解决了数据丢失和体验差的问题,但是这也很大程度依赖于开发者的编程习惯,如不能随便玩耍 window.name;也对系统有一定的要求,必须在所有页面上部署同样的埋点脚本。


这件事情应该交给浏览器来解决


上面提到的各种方案,不乏黑科技,然而存在的问题还是一大堆,如果团队的开发者执行力不够,中途容易出现各种麻烦。所以真正能够解决这个问题的,必然还是浏览器本身!


为什么不能给用户提供这样一个 API,即使页面跳转了,也能够将上个页面的请求发出去呢?庆幸的是,W3C 工作组也想到了这个问题,提出了 Beacon API 的 草案。


Beacon API 允许开发者发送少量错误分析和上报的信息,它的特点很明显:


  1. 在空闲的时候异步发送统计,不影响页面诸如 JS、CSS Animation 等执行

  2. 即使页面在 unload 状态下,也会异步发送统计,不影响页面过渡/跳转到下跳页

  3. 能够被客户端优化发送,尤其在 Mobile 环境下,可以将 Beacon 请求合并到其他请求上,一同处理


sendBeacon 函数挂在在 navigator 上,在 unload 之前,这个函数一定是被初始化了的。其使用方式为:


window.addEventListener('unload', function(event) {

 navigator.sendBeacon('/collector', data);

});


navigator.sendBeacon(url, data);,第一个参数为数据上报的地址,第二个参数为要发送的数据,支持的数据格式有:ArrayBufferView, Blob, DOMString, 和 FormData。


Beacon 的还有一个非常实用的移动端使用场景,当用户从浏览器切换到其他 app 界面或者 Home 屏的时候,部分浏览器默认会停止页面脚本的执行,如果在这个时候使用了 unload 时间,可能会让你失望,因为 unload 事件并不会触发,此时,Beacon 就派上用途了,它是不会受影响的。


最后


本文是对页面打点丢失问题的简单探讨,枚举了我们通常会用到的一些解决方案,可能不是很完善,如果你有更好的建议,可以提出来。


很多问题,我们绞尽脑汁,可能很少会考虑,这个问题是不是应该有我们来解决,或者说这个问题交给谁处理是最恰当的。本文的探讨可以看到,浏览器本身才是最好的问题解决方,当网站流量变大之后,上面提到的丢失问题就更加明显,这也迫使浏览器本身做了改善,自然也在情理之中。

您可能还对下面的文章感兴趣:

  1. APP调用Custom URL Scheme [2016-02-18 23:45:10]
  2. 安卓第三方应用调起常见问题 [2016-02-16 20:53:22]
  3. 苹果iOS系统下检查第三方APP是否安装及跳转启动 [2016-02-16 20:32:38]
  4. .htaccess的301跳转 [2009-12-09 16:45:58]

相关 [统计 数据 问题] 推荐:

页面跳转时,统计数据丢失问题探讨

- - IT技术博客大学习
标签:   统计   跳转. 为了更好地了解用户对产品的使用情况,业务中,我们经常会收到埋点统计的需求,比如:. 收集一段时间内用户光标在页面中的运动情况,包括光标移动、点击等行为. 无论是移动端还是 PC 端,相信很多朋友都遇到了这么几个十分让人头疼的问题:. 统计某个链接的点击量,但是这个链接点击后直接跳转走了.

Redis数据“丢失”问题

- - 今天
Redis大部分应用场景是纯缓存服务,请求后端有Primary Storage的组件,如MySQL,HBase;请求Redis的键未命中,会从primary Storage中获取数据返回,同时更新Redis缓存. 如果少量数据丢失,相当于请求”缓冲未命中“; 一般对业务的影响是无感知的. 但现在Redis用作存储的业务场景变多,数据丢失对业务是致命的影响.

再谈JavaScript的数据类型问题

- 茄 - aimingoo的专栏
 JavaScript的数据类型问题已经讨论过很多次了,但许多人还有许多书仍然沿用着错误的、混乱的一些观点,所以就再细讲一回. 提及这个讨论的原因在于argb同学在我的MSN博客(现在变成了wordproess,在这里)上的一段回复,又更早的起源则是两年前关于《JavaScript征途》一书的大讨论:.

Oracle数据库10个小问题

- - 数据库 - ITeye博客
Oracle 数据库 10 个小问题. Oracle的安装是出名的复杂,特别是在非windows系统中,在网上可以找到遍地的Oracle安装文档,但依然有很多人花了大量时间才安装成功,如果要搭建rac系统,那就更复杂了. 我们也看到Oracle公司也一直在降低安装的复杂度,11g的安装已经比8i,9i方便了一些.

有关大数据的误区:数据统计≠大数据

- - 钛媒体网
钛媒体注: 大数据太火了,被广泛应用到各行各业,而近阶段又有着明显的过热迹象. 大数据到底是一个营销词汇,还是一个方法论. 本文作者老李正是一家大数据服务提供商的资深员工,他所做的项目就是针对不同行业进行大数据分析. 他认为,关于大数据你首先必须有一个基本认识,那就是“大量的数据并非一定具有价值”.

MySQL数据库如何解决大数据量存储问题

- - 数据库 - ITeye博客
利用MySQL数据库如何解决大数据量存储问题. 各位高手您们好,我最近接手公司里一个比较棘手的问题,关于如何利用MySQL存储大数据量的问题,主要是数据库中的两张历史数据表,一张模拟量历史数据和一张开关量历史数据表,这两张表字段设计的很简单(OrderNo,Value,DataTime). 基本上每张表每天可以增加几千万条数据,我想问如何存储数据才能不影响检索速度呢.

对于数据分析与数据挖掘的数据10个问题

- - 乐无限-微信公众号内容聚合站
1,作为支付宝数据首席分析师,你怎么看待“数据挖掘”这个词. 所谓的“数据挖掘”是基于用户的行为挖掘出有价值的东西,以及这个东西被用到商业环境上. 比如非常著名的“啤酒与尿布”的案例,它的背景是在1992年的美国,每周四或者每周五下午5点-7点的时间形成的连锁销售. 但是这个联合销售的方法并不适合任何时间和任何场合,单纯地剥离其背景本身,谈数据挖掘就是一个很泛的事情.

转:面试中的海量数据处理问题

- friedvan - 丕子
终于找到了一份比较完整的,分享一下. 海量数据处理:十道面试题与十个海量数据处理方法总结. 作者:July、youwang、yanxionglu. 时间:二零一一年三月二十六日. 说明:本文分为俩部分,第一部分为10道海量数据处理的面试题,第二部分为10个海量数据处理的方法总结. 出处:http://blog.csdn.net/v_JULY_v.

网络身份安全中的数据策略问题

- - 技术改变世界 创新驱动中国 - 《程序员》官网
讲到破解对抗问题,要从攻防两方面所拥有的资源说起. 之前我们基于一台普通的戴尔笔记本进行了一个小测试:在笔记本里装了一个虚拟机进行相应的Hash次数计算,发现这么普通设备里的虚拟系统,大概每秒钟可以完成50万次以上的标准MD5散列计算,这个结果得益于摩尔定律. 我们要注意,这既是散列计算的速度,也是破解所需的数据资源生成的速度.

解决Android横竖屏切换数据丢失问题

- - CSDN博客推荐文章
Android横竖屏切换时,当前的Activity会被销毁,然后Activity上面的数据将会全部丢失. 如Listview上面每个item的checkbox,横竖屏切换时,复选框就丢失所有选中信息. 在Androidmanifest.xml的activity标签中加入. 强制限制activity在横屏状态或者竖屏状态,不让activity进行横竖屏切换.