「前端页面停留时长」统计上报方案

2023-04-22 16:39:32 浏览数 (1)


背景

为了解用户在我们H5页面的行为习惯,我们需要统计和上报用户在H5具体某个页面的停留时长。

当我们的H5页面是一个vue单页面应用,我们需要具体统计到每个路由的停留时长。

本文记录的是,我们自己实现的一套页面停留时长统计上报的方案,最后具体落地实施也是按这个方案走的。

当然市面上也有很多现成的方案,如果没有特殊的需求,现成的方案应该是可以满足大多数的场景的。

方案设计

问题一:停留时长的统计

通过调研,单页面应用统计页面时长,有以下这几种方案:

(1)页面在打开状态下,每隔一段时间给服务端发一个请求,由服务端计算页面时长;

(2)在页面打开和关闭的时候,分别给服务端上报一个请求,由服务端计算页面时长;

(3)前端监听页面的打开和关闭,计算出页面停留时长,直接上报服务端。

结合我们的应用场景,第3种方案是比较合适的,接下来主要需要解决的问题是如何监听页面的打开和关闭事件,对于单页面应用,就是下面这两个问题。

1.如何监听全部的路由跳转事件?

路由跳转事件相对来说是比较明确的,vue-router给我们提供了很多路由守卫可以使用。我们用beforeEach做拦截,除了首次进入,后面每次beforeEach都是前一个页面的结束。同时在beforeEach中,我们可以记下即将进入的路由和被退出的路由名称,供上报使用。

2.是否能够监听全部的关闭事件?

首先,判断回退事件是否可以监听到,我们考虑这三个事件:pagehide、onunload、onbeforeunload。

pagehide

当页面隐藏的时候触发,跳转到新页面和关闭浏览器或者webview退到后台,都会触发这个事件。

pagehide兼容性比较好,几乎可以不考虑兼容性的问题。

onunload

该事件在关闭窗口资源和内容的时候触发。页面资源的清除工作会在 unload 事件之后进行。

值得注意的是,MDN上对onunload有这样一段描述:

onunload 特性(乃至 unload 事件本身) 并非使用 sendBeacon()的正确途径,要调用 sendBeacon() 接口,应当使用 visibilitychange 和 pagehide 事件。 参见 Beacon API is broken。

浏览器兼容情况,这里需要试验的浏览器太多,我们直接找到网上的一个结论:

  • IE浏览器 页面跳转、刷新页面能执行,但关闭浏览器不能执行;
  • firefox 页面跳转能执行,但刷新页面、关闭浏览器不能执行;
  • Safari 刷新页面、页面跳转,关闭浏览器都会执行;
  • Opera、Chrome任何情况都不执行。

IE, Firefox, 和 Safari 支持 onunload 事件, 但是 Chrome 或者 Opera 不支持该事件。

onbeforeunload

当窗口即将被卸载(关闭)时,会触发该事件.此时页面文档依然可见,且该事件的默认动作可以被取消.

可用于弹出对话框,提示用户是继续浏览页面还是离开当前页面。

为了更好的验证这些事件的可用性,测试一下兼容性,我们对这些事件做一个小实验。验证事件是否触发的过程,需要用localStorage存储来实现,因为alert无效,console.log来不及看(其实也是无效的,即使Preserve log了也是不会输出的)

代码语言:javascript复制
window.addEventListener('pagehide', () => {
   window.localStorage.setItem('pagehide', dateFormat(new Date(), 'MM-dd hh:mm:ss'));
  });

window.addEventListener('unload', () => {
   window.localStorage.setItem('unload', dateFormat(new Date(), 'MM-dd hh:mm:ss'));
  });

通过在我们页面常用的几个浏览器中测试,可以得到这样的结果。

可以看到除了onunload事件在游戏内的slugsdk浏览器没有触发,其他环境下都是有触发的,这个其实跟兼容性关系也不大,应该是sdk或者游戏对webview做了优化,关闭webview的时候其实是去隐藏webview,下次打开还是复用这个window,从sessionStorage不被清除也可以看出来确实是这样的。

iOS微信

iOS QQ

iOS Slugsdk

安卓微信

安卓QQ

安卓Slugsdk

pagehide

onunload

我们比较pagehide和onunload在不同浏览器和环境下的兼容性,发现优先使用pagehide事件,onunload事件作为兜底,来记录关闭事件,是比较合适的方案。

总结一下,单页面的路由跳转用beforeEach做拦截记录,对于关闭窗口的情况,用上面说到的两个事件pagehide|onunload,来做记录。

问题二:统计数据的上报

时长统计完成后,就是对于数据的上报了,我们可以考虑两种上报方案:

1.每次页面结束就上报

2.把时长数据存本地,批量上报

对每次页面结束就上报,可能存在关闭窗口导致页面上报请求未发送的问题,解决这个问题有一些解决方案,比如Beacon API,但我们这边暂时不会用到,就不展开讨论了。

实际上,结合我们业务的应用场景,其实批量上报的方案更符合我们的需求,实现起来也更简单。

我们可以把时长数据存储在localStorage,启动一个定时器,定时取出数据做上报,上报完成再清除本地已上报的数据。

到这里页面停留时长统计上报的方案就大致确定了,如果有发现可以改进的地方,欢迎评论。

0 人点赞