vue项目afterEach中统计页面pv,vv,uv

586 阅读3分钟

首先我们先明确pv,vv,uv的概念

PV:用户在网站或应用程序上浏览页面的次数。每次用户访问或刷新页面,都会增加页面浏览量的计数。

VV:访客访问的次数,用以记录所有访客一天内访问网站的次数。用户打开网页到关闭网页算作一次。以档次会话session为依据。

UV:独立访客数,指一天内访问某站点的人数,以用户唯一标识为依据。

如何统计pv

进入页面之后,记录当前页面信息和时间,也许你觉得持久化数据没必要,听我娓娓道来。

function afterEnterPage(router) {
  // 持久化当前页面信息和时间
  const currentPagePath = {
    time: Date.now(),
    router,
  }
  window.sessionStorage.setItem(
    '_t_currentPagePath',
    JSON.stringify(currentPagePath),
  )
}

离开页面之前,计算停留时长和当前页面信息

function beforeLeavePage() {
  try {
    // 获取缓存信息
    const currentPagePath = JSON.parse(
      window.sessionStorage.getItem('_t_currentPagePath') || '',
    )
    // 计算停留时长
    const stayDuration = Date.now() - currentPagePath.time
    return {
      stayDuration,
      router: currentPagePath.router,
    }
  } catch (e) {
    console.log('session开启')
  }
}

使用router.afterEach替代组件内部钩子函数

因为vue-router全局钩子中不存在,进入页面和离开页面的钩子函数,我们可以借用router.after来实现方法调用。

router.afterEach(to => {
    // 因为新开tab页from会变成根路径,from信息不可靠
    // 信息全部从sessionStorage中获取,获取不到的情况必然是用户第一次开启会话
    const data = beforeLeavePage()
    console.log('上报页面信息data', data)
    // 先执行上个页面上报,再持久化当前页面数据,以供下次使用
    afterEnterPage(to)
})

实现思路梳理

  • 进入新页面,从sessionStroage中获取上一个页面的信息,完成上报,统计页面PV。
  • 统计VV,自然要加上会话id,依然存储在sessionStroage。
  • 统计UV,添加上用户的唯一标识,后端就可以分析了。

为什么要持久化上一个页面的信息

我们在afterEach中统计上一个页面信息,如果当前页面是新开页面,from会变成项目根路径。造成统计错误。借用sessionStroage持久化上一个页面信息。

什么情况下sessionStroage会在不同tab页面共享

// 共享sessionStroage的情况
window.open('/about')
<a href="/about" class="" target="_blank" rel="opener">打开新窗口About</a>
// 不共享session的情况
<a href="/about" class="" target="_blank">打开新窗口About</a>

sessionStroage共享问题是chrome 89版本的变动后带来的,可以参考:前端 - Chrome更新89版本后,sessionStorage丢失a标签跳转丢失sessionStorage - 个人文章 - SegmentFault 思否

最后贴上完整代码

packages/tracker · weihua/wh - 码云 - 开源中国 (gitee.com) 此项目基于pnpm构建,packages/tracker是基于vue、阿里云日志服务的sls开发的前端埋点系统。上文中不明白的可以留言或者看完整代码。

至于为什么要自建前端埋点系统,因为目前的三方要么贵,要么不好用。

百度统计和阿里云ARMS,SPA应用都pv、uv都需要手动在router中统计。索性直接在埋点系统中做了。 至于sentry是前端的监控系统,对于业务分析并不是很友好,至少我不知道如何使用sentry做业务分析,有知道的小伙伴可以评论区留言。

import type { Tracker } from '../main'

function afterEnterPage(router: any) {
  // 持久化当前页面信息和时间
  const currentPagePath = {
    time: Date.now(),
    router,
  }
  window.sessionStorage.setItem(
    '_t_currentPagePath',
    JSON.stringify(currentPagePath),
  )
}

function beforeLeavePage() {
  try {
    // 获取缓存信息
    const currentPagePath = JSON.parse(
      window.sessionStorage.getItem('_t_currentPagePath') || '',
    )
    // 计算停留时长
    const stayDuration = Date.now() - currentPagePath.time
    return {
      stayDuration,
      router: currentPagePath.router,
    }
  } catch (e) {
    console.log('session开启')
  }
}

/**
 * chrome浏览器2021年3月份修改了 target="_black" 规则,会造成页面 sessionStorage丢失
 * 新开页面需要添加属性 rel="opener" 或者 window.open()。
 */

function pageAnalytics(this: Tracker) {
  const { router } = this
  router.afterEach(to => {
    // 因为新开tab页from会变成根路径,from信息不可靠
    // 信息全部从sessionStorage中获取,获取不到的情况必然是用户第一次开启会话
    const data = beforeLeavePage()
    if (data) {
      const params = {
        kind: 'pageAnalytics',
        path: data.router.path,
        fullPath: data.router.fullPath,
        nextPath: to.path,
        nextFullPath: to.fullPath,
        stayDuration: data.stayDuration / 1000,
        ...this.commonInfo,
      }
      this.slsTracker.sendImmediate(params)
    }
    // 先执行上个页面上报,再持久化当前页面数据,以供下次使用
    afterEnterPage(to)
  })
}

export default pageAnalytics