JS统计页面访问时长

以vue单页面项目为例

1、在路由的meta属性中,给需要记录访问时长的页面添加hasViewTime属性,以便全局处理页面,代码如下:

{
	path: '路由地址',
	name: '页面模块名称',
	component: '页面模块',
	meta: {
		hasViewTime: true/false
	}
}

2、在页面主入口文件App.vue文件中,记录访问页面的初始数据,同时初始化页面隐藏/关闭时监听事件,代码如下:

data () {
	return {
		systemEnv: '' // 移动设备类型
	}
},
watch: {
	$route (to, from) {
		// 进入页面时,记录当前访问页面的浏览数据
        if (to.meta.hasViewTime) {
          localStorage.setItem('recordPageData', JSON.stringify({
            viewId: '', // 访问记录id
            name: to.name, // 访问页面名称标识
            startTime: new Date().getTime() // 本地访问页面的开始时间(时间戳)
          }))
        }
	}
},
mounted () {
	let userAgent = window.navigator.userAgent
	this.systemEnv = (userAgent.indexOf('iPhone') > -1 || userAgent.indexOf('iPad') > -1) ? 'iPhone' : 'Android'
	// 页面访问时长统计
    this.viewPageTimeFun()
},
methods: {
	addViewTime () {
		// 具体的记录页面访问时长的接口,就不附代码了
	},
	// 页面访问时长统计
     viewPageTimeFun () {
       // ******下次进入页面时,判断条件,发送请求,记录页面浏览数据******
       let recordPageData = localStorage.getItem('recordPageData') ? JSON.parse(localStorage.getItem('recordPageData')) : null

       if (recordPageData && recordPageData.viewId && recordPageData.viewTime) {
         // 发送请求
         this.addViewTime({
           VIEW_ID: recordPageData.viewId,
           VIEW_DURATION: recordPageData.viewTime
         }).then(res => {
           if (res.status === 'success') {
             let recordPageDataChange = localStorage.getItem('recordPageData') ? JSON.parse(localStorage.getItem('recordPageData')) : null
             if (recordPageDataChange && recordPageDataChange.viewId !== recordPageData.viewId) return
             localStorage.removeItem('recordPageData')
           }
         })
       }
       // ******下次进入页面时,判断条件,发送请求,记录页面浏览数据******

       // ******对页面的不可视状态(如:关闭、隐藏等)进行监听******
       // 为IOS设备监听做兼容
       if (this.systemEnv === 'iPhone') {
         window.addEventListener('pagehide', () => {
           let recordPageData = localStorage.getItem('recordPageData') ? JSON.parse(localStorage.getItem('recordPageData')) : null

           // 判断是否存在需要处理的页面
           if (recordPageData && recordPageData.viewId) {
             let startTime = recordPageData.startTime // 本地访问页面的开始时间(时间戳)
             let endTime = new Date().getTime() // 本地访问页面的结束时间(时间戳)
             let viewTime = endTime - startTime // 页面的访问时长(时间戳)

             localStorage.setItem('recordPageData', JSON.stringify({
               viewId: recordPageData.viewId, // 访问记录id
               name: recordPageData.name, // 访问页面名称标识
               viewTime // 页面的访问时长(时间戳)
             }))
             if (this.addViewTime) {
               this.addViewTime({
                 VIEW_ID: recordPageData.viewId,
                 VIEW_DURATION: viewTime
               }).then(res => {
                 if (res.status === 'success') {
                   localStorage.removeItem('recordPageData')
                 }
               })
             }
           }
         })
       }
       // 通用监听
       let hidden
       let visibilityChange
       if (typeof document.hidden !== 'undefined') {
         hidden = 'hidden'
         visibilityChange = 'visibilitychange'
       } else if (typeof document.msHidden !== 'undefined') {
         hidden = 'msHidden'
         visibilityChange = 'msvisibilitychange'
       } else if (typeof document.webkitHidden !== 'undefined') {
         hidden = 'webkitHidden'
         visibilityChange = 'webkitvisibilitychange'
       }
       document.addEventListener(visibilityChange, () => {
         let recordPageData = localStorage.getItem('recordPageData') ? JSON.parse(localStorage.getItem('recordPageData')) : null

         // 判断是否存在需要处理的页面
         if (recordPageData && recordPageData.viewId) {
           if (document[hidden]) {
             let startTime = recordPageData.startTime // 本地访问页面的开始时间(时间戳)
             let endTime = new Date().getTime() // 本地访问页面的结束时间(时间戳)
             let viewTime = endTime - startTime // 页面的访问时长(时间戳)

             localStorage.setItem('recordPageData', JSON.stringify({
               viewId: recordPageData.viewId, // 访问记录id
               name: recordPageData.name, // 访问页面名称标识
               viewTime // 页面的访问时长(时间戳)
             }))
             if (this.addViewTime) {
               this.addViewTime({
                 VIEW_ID: recordPageData.viewId,
                 VIEW_DURATION: viewTime
               }).then(res => {
                 if (res.status === 'success') {
                   localStorage.removeItem('recordPageData')
                 }
               })
             }
           }
         }
       }, false)
       // ******对页面的不可视状态(如:关闭、隐藏等)进行监听******
     }
}

以微信环境为例,这一部分的监听,主要是处理处理以下情况:
(1)点击微信左上角自带的关闭按钮;
(2)微信程序进入后台、或是通过手势滑动关闭微信程序;
(3)超链接跳转;

不能监听的情况
(1)页面超链接跳转;

设备差别说明和处理:
(1)安卓设备可通过visibilityChange监听以上情况;
(2)IOS设备通过visibilityChange监听以上情况,会时灵时不灵的,如果有效的话,以上情况都能监听;如若失效的话,以上情况皆不能监听(个人测试如此),故为IOS设备添加pagehide监听(这个能保证监听到点击微信左上角自带的关闭按钮)
(3)安卓设备的监听中能发送请求,IOS设备不能,故为兼容,做了下次进入发送请求的处理
监听方法说明详见:https://blog.csdn.net/mx_csdn/article/details/101674708

3、由于上面的监听无法监听到超链接跳转之类的页面离开,以及页面之间的路有跳转,故对具体的页面做处理,代码如下:

mounted () {
	this.addViewRecor().then(data => {
		let recordPageData = localStorage.getItem('recordPageData') ? JSON.parse(localStorage.getItem('recordPageData')) : null
		if (data.data.data && data.data.data.VIEW_ID && recordPageData) {
          recordPageData.viewId = data.data.data.VIEW_ID // 访问记录id
          // 缓存记录
          localStorage.setItem('recordPageData', JSON.stringify(recordPageData))
        }
	})
},
methods: {
	addViewRecord () {
		// 具体的请求,为页面生成一条访问记录,并返回记录id(),就不附代码了
	},
	addViewTime () {
		// 具体的记录页面访问时长的接口,就不附代码了
	},
	// 由于超链接跳转时,ios设备无法检测到,故对超链接跳转时,对页面浏览时长做单独处理
    hyperlinkJump (cb) {
      let recordPageData = localStorage.getItem('recordPageData') ? JSON.parse(localStorage.getItem('recordPageData')) : null
      let startTime = recordPageData.startTime // 本地访问页面的开始时间(时间戳)
      let endTime = new Date().getTime() // 本地访问页面的结束时间(时间戳)
      let viewTime = endTime - startTime // 页面的访问时长(时间戳)

      // 判断是否为微信环境,并发送请求
      if (recordPageData.viewId) {
        this.addViewTime({
          VIEW_ID: recordPageData.viewId,
          VIEW_DURATION: viewTime
        }).then(res => {
          if (res.status === 'success') {
            localStorage.removeItem('recordPageData')
          } else {
            localStorage.setItem('recordPageData', JSON.stringify({
              viewId: recordPageData.viewId, // 访问记录id
              name: recordPageData.name, // 访问页面名称标识
              viewTime // 页面的访问时长(时间戳)
            }))
          }
          cb && cb()
        }).catch(() => {
          localStorage.setItem('recordPageData', JSON.stringify({
            viewId: recordPageData.viewId, // 访问记录id
            name: recordPageData.name, // 访问页面名称标识
            viewTime // 页面的访问时长(时间戳)
          }))
          cb && cb()
        })
      } else {
        cb && cb()
      }
    }
},
beforeRouteLeave (to, from, next) {
    let recordPageData = localStorage.getItem('recordPageData') ? JSON.parse(localStorage.getItem('recordPageData')) : null
    let startTime = recordPageData.startTime // 本地访问页面的开始时间(时间戳)
    let endTime = new Date().getTime() // 本地访问页面的结束时间(时间戳)
    let viewTime = endTime - startTime // 页面的访问时长(时间戳)

    // 发送请求
    if (recordPageData.viewId) {
      this.addViewTime({
        VIEW_ID: recordPageData.viewId,
        VIEW_DURATION: viewTime
      }).then(res => {
        if (res.status === 'success') {
          localStorage.removeItem('recordPageData')
        } else {
          localStorage.setItem('recordPageData', JSON.stringify({
            viewId: recordPageData.viewId, // 访问记录id
            name: recordPageData.name, // 访问页面名称标识
            viewTime // 页面的访问时长(时间戳)
          }))
        }
        next()
      }).catch(() => {
        localStorage.setItem('recordPageData', JSON.stringify({
          viewId: recordPageData.viewId, // 访问记录id
          name: recordPageData.name, // 访问页面名称标识
          viewTime // 页面的访问时长(时间戳)
        }))
        next()
      })
    } else {
      next()
    }
 }

说明:hyperlinkJump 方法是在超链接跳转前调用的,安卓能检测得到超链接跳转,但IOS不能,故做此兼容

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章