如何精确统计页面停留时长?

前言

页面停留时间(Time on Page)简称 Tp,是网站分析中很常见的一个指标,用于反映用户在某些页面上停留时间的长短,传统的Tp统计方法会存在一定的统计盲区,比如无法监控单页应用,没有考虑用户切换Tab、最小化窗口等操作场景。基于上述背景,重新调研和实现了精确统计页面停留时长的方案,需要 兼容单页应用和多页应用,并且不耦合或入侵业务代码。


# 一. 页面生命周期

我们可以把一个页面生命周期抽象为三个动作:「进入」、「活跃状态切换」、「离开」:

动作 触发行为
进入 首次加载、页面跳转、刷新、浏览器前进后退
活跃状态切换 页面失去焦点/获得焦点、切换窗口最小化、切换浏览器 tab、电脑睡眠和唤醒
离开 关闭窗口、界面跳转、刷新、浏览器前进后退

如下图,计算页面停留时长既如何监控这三个动作,然后在对应触发的事件中记录时间戳,比如要统计活跃停留时长就把 active 区间相加即可,要统计总时长既 tn -t0 。


# 二. 监听页面进入和离开

对于常规页面的 首次加载页面关闭刷新 等操作都可以通过 window.onloadwindow.onbeforeunload 事件来监听页面进入和离开。

浏览器前进后退可以通过 pageshowpagehide 处理。

  • load / beforeunload
  • pageshow / pagehide

对于单页应用内部的跳转可以转化为两个问题:

  • 监听路由变化
  • 判断变化的URL是否为不同页面

# 1. 监听路由变化

目前主流的单页应用大部分都是基于 browserHistory (history api) 或者 hashHistory 来做路由处理,我们可以通过监听路由变化来判断页面是否有可能切换。注意是有可能切换,因为URL发生变化不代表页面一定切换,具体的路由配置是由业务决定的(既URL和页面的匹配规则)。

# a. browserHistory

路由的变化本质都会调用 History.pushState()History.replaceState() ,能监听到这两个事件就能知道。通过 popstate 事件能解决一半问题,因为 popstate 只会在浏览器前进后退的时候触发,当调用 history.pushState() 或者 history.replaceState() 的时候并不会触发。

# b. hashHistory

hashHistory 的实现是基于 hash 的变化,hash 的变化可以通过hashchange来监听。

# 2. 判断URL是否为不同页面

# 方案 a: 客户端定义

通过业务方在初始化的时候配置页面规则,然后JS通过URL匹配不同的规则来区分不同的页面,这种方案在客户端数据上报的时候就已经明确了不同的页面。

# 方案 b: 数据分析平台定义

假设我们最终上报后有一个数据分析平台来展现,我们可以在类似数据平台来配置页面规则,这样在客户端实现的代码逻辑就不需要区分页面,而是每次URL发生变化就将数据上报,最终通过数据平台配置的页面URL规则来求和、过滤数据等。

当数据展现平台不支持配置URL规则来区分页面的时候,可以采用方案a;当有数据平台支持的时候采用方案b更合理;

# 3. 整理

首次加载 关闭窗口 刷新 页面跳转 浏览器前进后退
browserHistory window.load beforeunload load/beforeunload pushState/replaceState popState
hashHistory window.load beforeunload load/beforeunload hashchange hashchange
多页 window.load beforeunload load/beforeunload load/beforeunload pageshow/pagehide

# 三. 监听页面活跃状态切换

可以通过 Page Visibility API 以及在 window 上声明 onblur/onfocus 事件来处理。

# 1. Page Visibility API

一个网页的可见状态可以通过 Page Visibility API 获取,比如当用户 切换浏览器Tab、最小化窗口、电脑睡眠 的时候,系统API会派发一个当前页面可见状态变化的 visibilitychange 事件,然后在事件绑定函数中通过 document.hidden 或者 document.visibilityState 读取当前状态。

document.addEventListener('visibilitychange', function (event) { 
	console.log(document.hidden, document.visibilityState)
})

# 2. onblur/onfocus

可以通过 Page Visibility API 以及在 window 上声明 onblur/onfocus 事件来处理。对于PC端来说,除了监听上述相关事件外,还可以考虑监听鼠标行为,比如当一定时间内鼠标没有操作则认为用户处于非活跃状态。


# 四. 上报数据时机

# 1. 页面离开时上报

对于页面刷新或者关闭窗口触发的操作可能会造成数据丢失。

# 2. 下次打开页面时上报

会丢失历史访问记录中的最后一个页面数据。

# 3. 总结

对于单页内部跳转是即时上报,对于单页/多页应用触发 window.onbeforeunload 事件的时候会把当前页面数据暂存在 localStorage 中,当用户下次进入页面的时候会把暂存数据上报。

有个细节问题,如果用户下次打开页面是在第二天,对于统计当天的活跃时长会有一定的误差,所以在数据上报的同时会把该条数据的页面进入时间/离开时间带上。


# 五. 思考

对于页面停留时长的定义可能在不同场景会有差异:

  • 比如内部业务系统或者OA系统,产品可能更关心用户在页面的活跃时长;
  • 对于资讯类型的产品,页面可见时长会更有价值

单一的数据对业务分析是有限的,所以在具体的代码实过程中我们会把停留时长分三个指标,这样能更好的帮助产品/运营分析:

  • active 页面活跃时长
  • visible 页面可见时长 //仅支持Desktop
  • duration 页面总停留时长



作者: 小黄鸭编程社区

来源: 小黄鸭编程社区

链接:https://mp.weixin.qq.com/s/zpjOpqhz_w3402BTu4QHeQ


著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。