埋点又称为事件追踪,目的是收集用户行为数据,例如用户点击了什么按钮,浏览了哪些页面,浏览了多长时间、从哪个页面进入的当前页(转化率)等。
刨除node等实现方式,对于前端来说, 保存这些操作或者说记录这些数据,最终一定是调用接口。
一、按钮点击
假设现在要实现记录用户点击了什么按钮,首先想到的是按钮点击事件,在vue项目中,就是@click,例如:
<el-button @click="confirm" size="mini">确定</el-button>
//...
confirm() {
//httpRequest...
},
//...
在confirm()中实现接口调用,埋点用户操作。
但是,如果每一个点击都要记录,那就每一个@click事件都要调用一次埋点的接口,而且用户点击是功能性的操作,它目的是为了执行操作,而不是为了让我们埋点的。
或许读者会说,那就继续调用接口。这种方案理论可行,但可行性极低,例如:
- ①项目是开发得很完善了,现在要埋点,肯定不能全局搜索,全局修改。
- ②即使项目非常小,可以全局修改,那就意味着要整个项目进行测试,成本非常大。
- ③即使上述都不是问题,当一个点击事件要做的功能非常复杂,原本就要调用很多接口,且掺杂这同步异步、条件判断、变量依据、条件判断和变量依据的if...else...分支语句,再有分支语句是弹出各种弹框,弹框中的各种操作,关闭弹窗后还需要触发@click等情况,代码复杂冗长,这时还要加入这么多重复代码,为人诟病。
由于埋点的事件是独立的功能,只受用户操作的影响,完全可以独立出来。因此,我们需要想个其他方法来统一对这类事件捕获——自定义指令。
在挂载时监听点击事件,在卸载时移除点击事件,触发点击后调用埋点接口(封装在track.js中),代码如下:
directive.js
import { track } from "track.js";
const appDirective = app => {
app.directive("tracking", {
mounted(el, binding, vnode) {
el.addEventListener("click", () => {
track(binding);
});
},
unmounted(el, binding) {
el && el.removeEventListener("click", () => {
track(binding);
});
}
});
};
export { appDirective };
main.js
//...
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
import ElementPlus from "element-plus";
import "element-plus/lib/theme-chalk/index.css";
import { appDirective } from "./directive"
let app = createApp(App);
appDirective(app)
app.config.errorHandler = (error, vm, info) => {
}
app
.use(store)
.use(router)
.use(ElementPlus)
.mount("#app");
完成上述自定义指令的实现和装载,下面就可以使用v-tracking指令实现点击事件的埋点:
<el-button size="mini" @click="confirm" type="info"
v-tracking="{
name: 'x页面-确定-点击',
type: 'click',
id: '',
from: ''
}"
>查询</el-button>
<span size="mini" @click="confirm" type="info"
v-tracking="{
name: 'x页面-下载-点击',
type: 'click',
id: '',
from: ''
}"
>下载</el-button>
二、页面浏览
利用路由拦截守卫,进入页面时记录必要入参和当前时间(beginTime),记录在vuex中,离开页面时,获取当前时间(endTime),算出差值即为用户在当前页码停留的时间。调用接口(track.js)传输埋点数据。
track({
name: 'x页浏览',
type: 'scan',
id: '',
from: '菜单',
time: '10s'
});