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

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

  • 收集一段时间内用户光标在页面中的运动情况,包括光标移动、点击等行为
  • 统计用户滚屏行为
  • 统计用户在站点的停留时长
  • 收集页面链接的点击数量等

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

  • 统计某个链接的点击量,但是这个链接点击后直接跳转走了
  • 统计页面时长问题,unload 的时候发送的统计丢失了
  • 统计脚本还没有初始化,用户不感兴趣已经走人了等

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

传统解决方案

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

  • 用户关闭页面过早,统计脚本还未加载/初始化完成
  • 用户关闭或者跳出页面的时候,请求未发出

针对第一点,概率较小,一般的处理方式就是,不要把统计脚本参合到其他脚本中,单独加载,并且放在前头,让它优先加载。很多公司的做法是,不让开发者关心统计脚本的加载,用户请求页面的时候,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';});

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

  • 少量浏览器下可能不奏效
  • 等待一会儿再跳转,用户体验上打了折扣,尤其是移动端上

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

优化方案

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

对于链接点击量的统计,我们可以将链接信息通过 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 允许开发者发送少量错误分析和上报的信息,它的特点很明显:

  • 在空闲的时候异步发送统计,不影响页面诸如 JS、CSS Animation 等执行
  • 即使页面在 unload 状态下,也会异步发送统计,不影响页面过渡/跳转到下跳页
  • 能够被客户端优化发送,尤其在 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 就派上用途了,它是不会受影响的。

最后

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

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

转载自:http://taobaofed.org/blog/2016/04/01/lose-statistics/

作者:阎王

时间: 2024-07-28 13:39:08

页面跳转时,统计数据丢失问题探讨的相关文章

cgi-html登陆页面跳转时出错

问题描述 html登陆页面跳转时出错 html登陆页面里用action调用login.cgi(用来判断用户名和密码是否正确),等登陆的时候,服务器提示the connetion was reset.请问各位大侠是哪里出了问题.急!!!

html5-请问JavaScript如何隐藏页面跳转时地址栏的参数

问题描述 请问JavaScript如何隐藏页面跳转时地址栏的参数 页面里不是form表单 button按钮的函数如下: setPass: function() { window.location.href="setpass.vue?tel=" + this.user.phone; } 每次点击按钮时跳转页面地址栏都有参数信息,请问用window.location.href 如何隐藏参数?谢谢 解决方案 get的话肯定是没办法隐藏参数,自己动态创建一个表单,表单method改为post,

数据-实现页面跳转时的等待效果

问题描述 实现页面跳转时的等待效果 页面A发送请求 然后后台查询数据 查询比较慢 大概两三秒 然后 跳转到B页面 也就是说 在页面A发送请求后 有三秒多的时间 什么都不错的 这个时候能不能做 做一个 等待效果 等 后台数据完以后 再去跳转 不然的话 页面A 发送请求后 有一段时间 像是没有反应了 解决方案 在中间加一个加载用的菊花呗,请求成功后隐藏

JS控制页面跳转时未请求要跳转的地址怎么回事_javascript技巧

其实,想表达的仅仅是,在js中通过window.location.href控制页面跳转时,有时会跳转至缓存页面,并没有真正去请求要跳转的地址,导致页面数据未能及时加载刷新. 直奔code... 解决办法: 在HTML中埋入隐藏from,通过js调用from进行请求链接地址 <form id='hidden_submit_info' method="post" enctype="multipart/form-data" action="test.php

Angular 页面跳转时传参问题_javascript技巧

首先,你需要已经配置过你的rout,比如: $stateProvider .state('firstPage',{ url:'/Page/firstPage', templateUrl: 'Page/views/firstPage.html', controller: 'firstPageCtrl' //dependencies: ['service/vipSeachService'] }) .state('secPage', { params:{'message':null}, url: '/

【转】iframe页面跳转时,导致父页面滚动!该怎么解决?

HTML code <body> <form id="form1" runat="server"> <iframe id="topFrame" width="800px" height ="140px;" style=" margin:0px 0px 0px 0px" frameborder="0" scrolling="no&

在母版页里制作登录界面,如何解决当页面跳转时,登录信息的保存

问题描述 母版如图:下面是我写的登录的代码:protectedvoidPage_Load(objectsender,EventArgse){if(Session["UserInfo"].ToString()==""){Paneldl.Visible=true;Panelxs.Visible=false;Panells.Visible=false;}else{if(Session["Status"]=="学生"){Paneldl

jsp页面跳转时的异常...java.lang.IllegalStateException!求解中....

问题描述 其他项目用<body><c:redirect url="register.jsp"></c:redirect>这么一代码就没错,但是就当前的项目出现问题....项目技术:S2SH+jquery+FCKeditor.不知道是不是配置时产生的问题...不懂问题出在哪,又因为代码量太大...未能贴出具体代码....错误打印如下:信息: Server startup in 24854 ms2010-12-6 12:32:26 org.apache.

PHP Header用于页面跳转时的几个注意事项_php技巧

前言 本文介绍的是在PHP中用header("location:test.php")进行跳转要注意以下几点,有助于解决一些新手经常遇到的问题 一.location和":"号间不能有空格,否则会出错. 二.在用header前不能有任何的输出. 三.header后的PHP代码还会被执行. 下面是和asp中重定向response.redirect的比较: 例1: response.redirect "../test.asp" header("