前端埋点和后端埋点的区别(前端埋点需求(vue.js))
提示:基于运营活动的需求 ,需要对用户行为进行埋点监控 ,因此以下文章是代码埋点的实现 。
前言
前端埋点有两种:全局埋点 、代码埋点 。
全局埋点:收集的用户所有行为 ,但是收集的数据驳杂 ,要进行处理 。
代码埋点:收集的用户所有行为更加精准 ,能够进行更细节的处理 。基于上述优缺点以及团队现状 ,因此采用代码埋点的方式来实现 。
以下仅介绍关于前端的部分 ,至于登录次数 、登录人数等均可完全靠后端进行实现
一 、埋点思考
运营需求:用户浏览各页面情况(时长等) ,用户对各个规定元素的点击操作 。
根据运营的需求我们需要做如下事:
1.对页面的访问 ,离开进行监控(包括关闭浏览器等操作) 。
document.addEventListener(‘visibilitychange’)2.对点击事件进行监控
采用vue自定义命令:v-log3.避免耗费请求资源,需要批量的给后端发送前端操作日志
在离开页面的时候或每隔三分钟发送一次日志4.避免日志内容丢失和错误
存储在本地localStorage中 ,一定要通过navigator.sendBeacon发送请求 ,若是不支持,则采用同步请求 ,避免发送不成功 ,成功后定时清除二 、埋点实现
以下代码是埋点封装类的实现,具体详解看注释
1.埋点工具类实现(operationLog.js)
/* 用户操作相关的所有方法 */ import store from @/store/store import router from @/router/router import { VueLocalStorage } from @/utils/storage class OperationLog { // 操作类型 operationType = { visit: PAGE_ACCESS,//访问行为 click: BUTTON_CLICK//点击行为 } // 页面路由与标识符对应关系 visitPage = new Map([ [[/dashboard], INSTRUMENT_PANEL_PAGE], [[/incidents/list], EVENT_ANALYZE_PAGE], [[/incidentsVul/detail], EVENT_ANALYZE_DETAIL_PAGE], [[/application/main/monitor], APPLICATION_MANAGE_MONITOR_PAGE], [[/application/main/nomonitor], APPLICATION_MANAGE_NOT_MONITOR_PAGE], [[/application/detail/risk], APPLICATION_DETAIL_RISK_LIST_PAGE], [[/applicationVul/history], APPLICATION_DETAIL_RISK_DETAIL_ATTACK_HISTORY_PAGE], [[/applicationVul/info], APPLICATION_DETAIL_RISK_DETAIL_VUL_INFO_PAGE], [[/baseline/list], BASELINE_INSPECT_PAGE], [[/instance/list], NODE_MANAGE_PAGE], [[/instance/details/cpufusing, /instance/details/baseline], NODE_MANAGE_DETAIL_PAGE], [[/blackWhite/main/black], BLACK_LIST_MANAGE_PAGE], [[/blackWhite/main/white], WHITE_LIST_MANAGE_PAGE], [[/strategy], DEFEND_POLICY_MANAGE_PAGE], [[/patch/main/list], VIRTUAL_PATCH_PAGE], [[/user/account, /user/security, /user/message], PERSONAL_CENTER_PAGE], [[/message/list], MESSAGE_NOTIFICATION_PAGE] ]) constructor () { this.timeOut = null// 记录定时器id this.timeNum = 60000 // 定时毫秒数 this.localKeyName = raspLog// 存储本地数据key } start () { this.visibilitywindow() this.timer() } // 发送操作日志信息给后端 async reportData () { const data = VueLocalStorage.getJSON(this.localKeyName) || [] // 没有操作日志的时候不进行日志发送 if (!data.length) { return } const url = `/rasp/api-v1/data/event/track/push?Authorization=Bearer ${store.state.login.accessToken}` if (navigator.sendBeacon) { const blob = new Blob([JSON.stringify(data)], { type: application/json; charset=UTF-8 }) navigator.sendBeacon(url, blob) this.clearLog() } else { // 同步请求 const xhr = new XMLHttpRequest() xhr.open(POST, url, false) xhr.setRequestHeader(Content-Type, application/json; charset=UTF-8) xhr.send(JSON.stringify(data)) this.clearLog() } } // 监控窗口变化(锁屏 ,关闭等) visibilitywindow () { document.addEventListener(visibilitychange, () => { if (document.visibilityState !== visible) { // 离开页面 this.reportData() } else { // 进入页面 this.writeLog(visit, router.currentRoute.path) } }) } // 定时器 timer () { if (this.timeOut) { clearTimeout(this.timeOut) this.timeOut = null } this.timeOut = setTimeout(() => { this.reportData() this.timer() }, this.timeNum) } /* 记录操作信息 type(操作类型):visit/click operation:type为visit的时候是path路径 ,为click的时候是直接传给后端的字符 */ writeLog (type, operation) { const params = { // 要记录的单挑数据 eventType: this.operationType[type], functionType: , createDate: Number.parseInt((new Date().getTime()) / 1000) } // 获取本地存储的数据 const localData = (VueLocalStorage.getJSON(this.localKeyName) || []) if (type === visit) { // 访问页面 // 根据路由找到对应页面的标识符 const functionType = Array.from(this.visitPage.entries()).find(item => { return item[0].some(path => path === operation) })?.[1] // 若是未找到对应的标识符则代表此页面路由不进行记录 if (functionType) { params.functionType = functionType } else { return } } else if (type === click) { // 点击元素 params.functionType = operation } // 记录前检查是否为重复数据 const repeat = (VueLocalStorage.getJSON(this.localKeyName) || []).some(item => { return item.eventType === params.eventType && item.functionType === params.functionType && item.createDate === params.createDate }) if (!repeat) { // 没有重复则进行记录 localData.push(params) VueLocalStorage.setJSON(this.localKeyName, localData) } } // 清空操作信息 clearLog () { localStorage.removeItem(this.localKeyName) } } const operation = new OperationLog() export function start () { operation.start() } export function writeLog (type, content) { operation.writeLog(type, content) }2.埋点监控的开启
在App.vue中
import { start } from @/utils/operationLog.js mounted () { start()// 开启日志监控 },3.页面访问日志的写入
路由拦截中进行写入日志
import { writeLog } from @/utils/operationLog.js router.beforeEach((to, from, next) => { writeLog(visit, to.path) })4.点击事件的日志写入
通过定义全局的vue命令进行写入
定义命令,在mai.js对指令进行全局引入
import { writeLog } from @/utils/operationLog.js // 记录点击日志 Vue.directive(log, { bind: (el, binding, vnode) => { el.addEventListener(click, () => { writeLog(click, binding.value) }, false) } })使用命令
<el-button v-log="EVENT_ANALYZE_ADVANCED_SEARCH_BUTTON">确认</el-button>总结
以上方法经过测试 ,可以对用户操作行为做到精准检测 ,除ie浏览器外 ,针对用户关闭 、最小化 、切出浏览器等操作行为进行监听且有效的上报 。用户只需要在针对特殊操作如点击等使用v-log就能做到全面的监控 。
创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!