天涯论坛

 找回密码
 立即注册
搜索
查看: 69|回复: 5

捉捕用户在该页面停留的时长,我是这般做的(前端监测)

[复制链接]

2992

主题

220

回帖

9909万

积分

论坛元老

Rank: 8Rank: 8

积分
99099168
发表于 2024-9-2 10:30:47 | 显示全部楼层 |阅读模式

前言

为何要做这个监测用户停留的呢?原由很简单,倘若咱们要分析这个页面对咱们制品价格,那样用户浏览的时长是一个很关键的点,倘若每一个用户平均每日在这个页面停留两个小时以上,那样咱们会觉得这个页面的价值很高;倘若一个页面一月没几个用户去浏览,那咱们就会有疑问,这个页面对咱们制品还有价值吗?咱们制品后续还要保存它的?这些需要都是能够咱们思虑是不是要去获取用户停留时长这个功能的。

针对那些应用?

多页面应用单页面应用(本文以vue为例子)

怎样去获取用户停留的时长?

在监测功能的时候,咱们首要思虑便是咱们的监测代码不可影响咱们此刻的业务代码,和以后的业务代码。

多页面应用

在多页面应用,要获取用户的停留时间还是挺简单的,瞧瞧下面几个Api

onload[1] (页面加载完后)onbeforeunload[2] (页面卸载前,便是点击叉的时候)onpageshow[3] (页面表示的时候)onpagehide[4] (页面隐匿的时候)

经过自己的一点小测试,发掘无论在关闭的时候(便是点击叉),还是隐匿的时候(便是点击上下箭头)都会触发onpagehide;无论是在首次加载,还是刷新的时候,都会触发onpageshow,然则刷新的时候会先触发onpagehide,在触发onpageshow。其他两个API是类似,最后,个人选取了用onpageshowonpagehide这个两个API获取用户停留的时长,你能够用其他两个API做。只要在onpageshow初始时间值,在onpagehide的时间求出差值,而后上传到后台就行。

let stopTime window.onpageshow = ()=>{ stopTime = new Date().getTime() } window.onpagehide = ()=>{ stopTime = new Date().getTime() - stopTime let record = localStorage.getItem(data) let data = record && JSON.parse(record) || [] localStorage.setItem(data,JSON.stringify([...data,{user:new Date().getTime(),path:window.location.href,stopTime}])) }

完整代码就那样点,这儿我只是测试,就把模拟的用户id,真实的路径,真实的停留时长存储了在localStorage,在项目中能够传到后台,而后经过分析,再可视化展示出来。

上面效果图(录得GIF就那AV画质,没钱开VIP,将就看吧,有点AV感觉好,哈哈),第1次点击的是,点击叉那能够理解为离开了页面,第二次a链接,第三次刷新,刷新能够理解为一次离开吧,一共存了三条数据,有兴趣自己试试更好理解。

单页面应用

单页面应用可能,会繁杂一点,然则繁杂不到哪里去。

单页面应用的路由,都是基于 H5的History API(browserHistory)Hash(hashHistory)实现的。

browserHistory

单页面的browserHistory路由是基于H5的History API实现的,咱们只要监听popstate能够晓得,点击前进后退按钮改变的url变化,url出现变化,咱们就能统计用户在该页面待了多长期,代码如下

let timeStr window.addEventListener(onload,(e)=>{ timeStr =new Date().getTime() }) window.addEventListener(popstate,()=>{ let t = new Date().getTime() - timeStr timeStr = new Date().getTime() console.log(待了时长:+ t) })

然则pushState和replaceState(便是,点击router-view,$router.push,$router.replace,window.history.pushState,window.history.replaceState不会触发,能够自动试试)不会触发popstate,那咱们就统计不了用户待在该页面的时长的了;可是处理办法还是有的,只需要重写pushState和replaceState而后监听两个自定义事件就行,看下面代码

// 对原函数做一个拓展 let rewriteHis = function(type){ let origin = window.history[type] // 先将原函数存放起来 return function(){ // 当window.history[type]函数被执行时,这个函数就会被执行 let rs = origin.apply(this, arguments) // 执行原函数 let e = new Event(type.toLocaleLowerCase())// 定义一个自定义事件 e.arguments = arguments // 把默认参数,绑定到自定义事件上,new Event返回的结果,自己上是arguments的 window.dispatchEvent(e) // 触发自定义事件,把载荷传给自定义事件 return rs } } window.history.pushState = rewriteHis(pushState) // 覆盖原来的pushState办法 window.history.replaceState = rewriteHis(replaceState) // 覆盖原来的replaceState办法 // 监听自定义事件, pushstate事件是在rewriteHis时注册的,不是原生事件 // 当点击router-link window.history.pushState this.$router.push 时都会被该事件监听到 window.addEventListener(pushstate,()=>{}) // 监听自定义事件, replacestate事件是在rewriteHis时注册的,不是原生事件 // 当点击window.history.replaceState this.$router.replace 时都会被该事件监听到 window.addEventListener(replacestate,()=>{})

rewriteHis函数,这个函数重点是对原函数做了一个拓展,上面代码的注释应该说了很清楚了。

browserHistory路由变化监听完整代码

let timeStr let rewriteHis = function(type){ letorigin =window.history[type] return function(){ let rs = origin.apply(this, arguments) let e = new Event(type.toLocaleLowerCase()) e.arguments = arguments window.dispatchEvent(e) return rs } } window.history.pushState = rewriteHis(pushState) window.history.replaceState = rewriteHis(replaceState) window.addEventListener(onload,(e)=>{ timeStr = new Date().getTime() }) window.addEventListener(popstate,()=>{ let t = new Date().getTime() - timeStr timeStr =new Date().getTime() console.log(待了时长popstate:+ t) }) window.addEventListener(pushstate,()=>{ let t = new Date().getTime() - timeStr timeStr = new Date().getTime() console.log(待了时长pushstate:+ t) }) window.addEventListener(replacestate,()=>{ let t = new Date().getTime() - timeStr timeStr = new Date().getTime() console.log(待了时长replacestate:+ t) })

这儿的演示就不做任何存储了,爱好的话,自己做一下

hashHistory

hashHistory就简单得不行了,直接监听hashchange就行

window.addEventListener(hashchange,()=>{ let t = new Date().getTime() - timeStr timeStr = new Date().getTime() console.log(待了时长:+ t) })

这儿为止,单页面应用,多页面应用怎么去获取用户待在该页面的时长就说完了。不是很理解,挺简单的。

后续

你以为这就完事了吧,还有一个奇怪的问题。

const router = new VueRouter({ mode:hash, routes:[...] })

我在测试hash路由切换的时候,看会不会触发window.addEventListener(hashchange,()=>{}),奇怪的事情出现了,它触发,却触发了自定义window.addEventListener(replacestate,()=>{}和window.addEventListener(pushstate,()=>{})等History API到底为何?我明明把它设置为hash路由了,为何还会触发History API?带着这个疑问,我忍不住的去看了vue-router的源码,最后,解开了自己的疑问,看下面:

在vue-router的hash路由实现文件

有这么一段代码,在 supportsPushStatefalse时,才会走else规律,else规律才会触发window.addEventListener(hashchange,()=>{}),那它为何不走?supportsPushState又是什么?pushState,replaceState又是怎么实现的?为何它会触发自定义事件?

supportsPushState

瞧瞧supportsPushState是什么

上面是supportsPushState的规律,看到这规律,是不是瞬间就明白了为何不走else规律的hash语句了。当满足这些要求才会走else语句(ua.indexOf(Android 2.) !== \-1 || ua.indexOf(Android 4.0) !== \-1) && ua.indexOf(Mobile Safari) !== \-1 && ua.indexOf(Chrome) === \-1 && ua.indexOf(Windows Phone) === \-1,否则其他都是走基于History API实现的Hash-router

pushState , replaceState

再来瞧瞧这两个api的实现

原来它们都是调用了 History API实现,这就解开了为何它会触发自定义事件的原由了。

看源码指引

倘若你不相信,我比比的话,能够自动瞧瞧源码。





上一篇:什么是页面停留时间?怎么样增加停留时间可读性
下一篇:用户拜访停留时间的重要性与加强停留时间的7个策略
回复

使用道具 举报

0

主题

1万

回帖

1

积分

新手上路

Rank: 1

积分
1
发表于 2024-9-7 17:24:40 | 显示全部楼层
我赞同你的看法,你的智慧让人佩服,谢谢分享。
回复

使用道具 举报

2942

主题

2万

回帖

9997万

积分

论坛元老

Rank: 8Rank: 8

积分
99979441
发表于 2024-10-2 09:08:13 | 显示全部楼层
这篇文章真的让我受益匪浅,外链发布感谢分享!
回复

使用道具 举报

3066

主题

3万

回帖

9915万

积分

论坛元老

Rank: 8Rank: 8

积分
99158945
发表于 2024-10-12 13:10:59 | 显示全部楼层
对于这个问题,我有不同的看法...
回复

使用道具 举报

3066

主题

2万

回帖

9913万

积分

论坛元老

Rank: 8Rank: 8

积分
99138962
发表于 2024-11-5 17:24:19 | 显示全部楼层
楼主听话,多发外链好处多,快到碗里来!外链论坛 http://www.fok120.com/
回复

使用道具 举报

3066

主题

3万

回帖

9915万

积分

论坛元老

Rank: 8Rank: 8

积分
99158945
发表于 5 小时前 | 显示全部楼层
感谢楼主分享,祝愿外链论坛越办越好!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

站点统计|Archiver|手机版|小黑屋|天涯论坛 ( 非经营性网站 )|网站地图

GMT+8, 2024-11-22 06:09 , Processed in 0.119050 second(s), 22 queries .

Powered by Discuz! X3.4

Copyright © 2001-2023, Tencent Cloud.