网站首页 > 知识剖析 正文
迎关注我的头条号:Wooola,10年Java软件开发及架构设计经验,专注于Java、Go语言、微服务架构,致力于每天分享原创文章、快乐编码和开源技术。
埋点即监控用户在应用表现层的行为,于产品迭代而言至关重要。埋点数据分析是产品需求的 来源,检验功能是否达预期的 佐证。前端较服务端更接近用户,本小白将在此对前端埋点统计方案述说一二。
采集埋点数据可做如下分析(以百度统计为例):
将 用户属性、用户行为 转化各类可视化图表:
不同产品对数据的关注角度不同,可按需采集。如信息流产品对停留时长的关注度更高(统计页面访问 & 跳出时间),商城类较注重“复购率”(统计新老用户),广告类更追求最大限度。
埋点统计通常分两类:
- 页面访问量统计
- 功能点击量统计
页面访问量统计
页面访问量统计通常分两类:
- PV:页面访问人次
- UV:页面访问人数
页面访问量,并非仅仅取决于其内容吸引力,影响因素包含入口 外观、位置、深度 等等(在此不考虑刚需)。入口外观属 UI 设计范畴,入口位置可通过分析用户点击热力图调整,入口深度可通过分析用户访问路径调整。
用户点击 热力图 形如:
将核心页面入口置于热力图红色区域?
采集页面加载 from、to 以获知用户访问路径:
分析可知用户普遍 访问深度、每一深度 & 每一页面的 流失率 等,依照结果调整核心页面入口源、入口深度?
页面访问量,也并非仅仅取决于产品设计。假若 PV 稳定的页面访问量 爆跌,便需考虑其加载成功率了(或许是枚技术 bug)。
前端如何实现全局 PV 统计,以 Vue 应用为例。
方案一
通过在入口文件 index.js 全局定义 Router.beforeEach:
import App from './app' import Router from './router' Router.beforeEach((to, from, next) => { App.logEvent({ type: 'visit', name: to.name, time: new Date().valueOf(), params: { from: { name: from.name, path: from.path, query: from.query }, to: { name: to.name, path: to.path, query: to.query } } }) next() }) 复制代码
停留时长可通过 (跳转页 time - 当前页 time) 获知,但关闭应用时如何统计?监听应用关闭 onbeforeunload + onunload?
其中 App.logEvent 为自定义 Vue 插件 App 中的 method,用于向服务器发起 埋点上报请求:
import Request from './utils/request' const App = { // ... logEvent (opts) { Request({ url: '/log/event', method: 'POST', data: { type: opts.type, name: opts.name, time: opts.time, params: opts.params || {} } }) } } App.install = (Vue, options) => { Vue.prototype.$app = { // ... logEvent: App.logEvent } } export default App 复制代码
方案二
通过在入口文件 index.js 全局注册混入 beforeRouteEnter、beforeRouteLeave 对象:
import Vue from 'vue' Vue.mixin({ beforeRouteEnter (to, from, next) { next(vm => { vm.$app.logEvent({ type: 'visit', name: to.name, time: new Date().valueOf(), params: { from: { name: from.name, path: from.path, query: from.query }, to: { name: to.name, path: to.path, query: to.query } } }) }) }, beforeRouteLeave (to, from, next) { this.$app.logEvent({ type: 'visit', name: to.name, time: new Date().valueOf(), params: { from: { name: from.name, path: from.path, query: from.query }, to: { name: to.name, path: to.path, query: to.query } } }) next() } }) 复制代码
关闭应用时 beforeRouteLeave 是否触发?
上述方案存在明显缺陷:
- 官方曰慎用全局混入对象!!!
- 对于页面同名钩子函数 beforeRouteEnter、beforeRouteLeave,如何 merge?如何 next?
- 含子路由的页面将调用 2 次 beforeRouteEnter、beforeRouteLeave,PV 无形翻倍...
我猜此刻有打全局混入 created、destroyed 并通过 this.$route 获知访问对象主意的人了,试试看?
令人不知所措的输出,打印次数与 路由表 长度一致嗷~
其中 this.$app.logEvent(vm.$app.logEvent) 等同方案一中 App.logEvent,不再赘述。
如何恰当选取全局 PV 统计方案?
- SPA 应用:仅单入口,在入口文件全局定义 Router.beforeEach 方便可行。
- MPA 应用:多入口,在每个入口文件定义 Router.beforeEach?可封装公用逻辑(伪装单入口),免去重复构造 entry 的成本。
- SPA + MPA 混合应用:emmmmmm...采用 MPA 应用的统计方案。
- SSR 应用:为追求更好的 SEO 而采用服务端渲染(SSR)。以 Jinja(Python 模板)为例,调用 TemplateView 则为渲染页面(不同于前后端分离项目,服务端无法获知接口调用与页面渲染的对应关系),统计其调用次数及 TemplateName 可知页面 PV。
至于 UV,统计 PV 时采集 userId 去重即可。若应用无用户管理体系,采集 IP、deviceId 也可粗略得知 UV(不精准)。
功能点击量统计
不同功能的点击量不同,同一功能不同区域的点击量也不同:
按钮点击量,影响因素包含按钮 外观、位置、入口 等等(在此不考虑刚需)。按钮外观属 UI 设计范畴,按钮位置可通过分析用户点击热力图调整,按钮入口可通过分析触发源分布调整。
举一实例:
运营同学会将一张图片裁切成 n 个区域,点击每一区域所推荐商品不同。统计区域点击坐标,据热力图调整商品排序以求 利益最大化。
前端如何实现功能点击量统计?
本人将功能点击分两类:
- 带业务接口请求
- 无业务接口请求
方案一
将埋点上报混入业务接口请求,无接口请求的点击采用自定义上报:
其中 param keys 指代需上报的业务请求参数 key list(并非全部参数均需随埋点上报)。
上述方案大大节约请求数,但存在明显缺陷:
- 将埋点上报混入业务接口,上报 crash 不仅丢失统计数据,还将影响主功能。
- 统计与业务 高耦合,两者尽量不混于同一服务。
方案二
将所有点击事件视为同一类,走统一上报接口:
logEvent (opts) { Request({ url: '/log/event', method: 'POST', data: { type: opts.type, name: opts.name, time: opts.time, params: opts.params || {} } }) } 复制代码
上述方案也存在明显缺陷:
- 请求量翻倍:但统计与业务服务拆分后,请求并非同一组服务器承担。
- 待上报的点击事件函数均需调用 logEvent:封装一枚附带埋点上报的 组件,以 Vue 为例。
<template> <div class="vc-trace" @click="triggerClick"> <slot></slot> </div> </template> <script> import Request from './utils/request' export default { name: 'Trace', props: { type: { type: String, default: '' }, name: { type: String, default: '' }, from: { type: String, default: '' }, params: { type: Object, default: () => ({}) } }, methods: { triggerClick () { Request({ url: 'XXX/log/event', method: 'POST', data: { type: this.type, name: this.name, from: this.from, time: new Date().valueOf(), params: this.params } }) } } } </script> 复制代码
方案本无优劣,适合才更重要,需综合考虑 产品设计、产品使用度、服务利用率 等等。例使用度较低应用可将统计与业务混于同一服务以节约成本,使用度较高应用可采取 本地缓存、批量上报 以降低服务压力,但批量上报是否加大统计 误差?
来源: 掘金 | 呆恋小喵_sunmy
如有侵权请联系删除
猜你喜欢
- 2024-11-17 Android对so体积优化的探索与实践
- 2024-11-17 JavaScript对象(javascript对象主要包括)
- 2024-11-17 第27节 函数、作用域及垃圾回收-Javascript-零点程序员-王唯
- 2024-11-17 微信小程序学习笔记:Page()(小程序 page)
- 2024-11-17 广州蓝景分享—搞懂js事件、事件流(捕获冒泡)、事件委托
- 2024-11-17 程序员都必掌握的前端教程之JavaScript基础教程(下)
- 2024-11-17 DOM核心内容(dom的核心部分包括)
- 2024-11-17 小程序生命周期解析(从概念、启动、运行、销毁场景的全面解析)
- 2024-11-17 微信小程序学习笔记(二)——开发之框架
- 2024-11-17 《微信小程序开发从入门到实战》学习六十一
- 04-29php开发者composer使用看这一篇就够了
- 04-29引用和变量声明在不同语言中的实作
- 04-29PHP 没你想的那么差
- 04-29Ubuntu linux 上的 Nginx 和 Php 安装
- 04-29CentOS下通过yum搭建lnmp(单版本PHP)
- 04-29为什么 PHP8 是个高性能版本
- 04-29PHP8函数包含文件-PHP8知识详解
- 04-29使用无参数函数进行命令执行
- 最近发表
- 标签列表
-
- xml (46)
- css animation (57)
- array_slice (60)
- htmlspecialchars (54)
- position: absolute (54)
- datediff函数 (47)
- array_pop (49)
- jsmap (52)
- toggleclass (43)
- console.time (63)
- .sql (41)
- ahref (40)
- js json.parse (59)
- html复选框 (60)
- css 透明 (44)
- css 颜色 (47)
- php replace (41)
- css nth-child (48)
- min-height (40)
- xml schema (44)
- css 最后一个元素 (46)
- location.origin (44)
- table border (49)
- html tr (40)
- video controls (49)