0


前端埋点需求(vue.js)

提示:基于运营活动的需求,需要对用户行为进行埋点监控,因此以下文章是代码埋点的实现。

文章目录


前言

前端埋点有两种:全局埋点、代码埋点。
全局埋点:收集的用户所有行为,但是收集的数据驳杂,要进行处理。
代码埋点:收集的用户所有行为更加精准,能够进行更细节的处理。

基于上述优缺点以及团队现状,因此采用代码埋点的方式来实现。


以下仅介绍关于前端的部分,至于登录次数、登录人数等均可完全靠后端进行实现

一、埋点思考

运营需求:用户浏览各页面情况(时长等),用户对各个规定元素的点击操作。

根据运营的需求我们需要做如下事:

1.对页面的访问,离开进行监控(包括关闭浏览器等操作)。
document.addEventListener(‘visibilitychange’)

2.对点击事件进行监控
采用vue自定义命令:v-log

3.避免耗费请求资源,需要批量的给后端发送前端操作日志
在离开页面的时候或每隔三分钟发送一次日志

4.避免日志内容丢失和错误
存储在本地localStorage中,一定要通过navigator.sendBeacon发送请求,若是不支持,则采用同步请求,避免发送不成功,成功后定时清除

二、埋点实现

以下代码是埋点封装类的实现,具体详解看注释

1.埋点工具类实现(operationLog.js)

/*
  用户操作相关的所有方法
*/import store from'@/store/store'import router from'@/router/router'import{ VueLocalStorage }from'@/utils/storage'classOperationLog{// 操作类型
 operationType ={visit:'PAGE_ACCESS',//访问行为click:'BUTTON_CLICK'//点击行为}// 页面路由与标识符对应关系
 visitPage =newMap([[['/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// 记录定时器idthis.timeNum =60000// 定时毫秒数this.localKeyName ='raspLog'// 存储本地数据key}start(){this.visibilitywindow()this.timer()}// 发送操作日志信息给后端asyncreportData(){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 =newBlob([JSON.stringify(data)],{type:'application/json; charset=UTF-8'})
     navigator.sendBeacon(url, blob)this.clearLog()}else{// 同步请求const xhr =newXMLHttpRequest()
     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((newDate().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}}elseif(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 =newOperationLog()exportfunctionstart(){
  operation.start()}exportfunctionwriteLog(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-buttonv-log="'EVENT_ANALYZE_ADVANCED_SEARCH_BUTTON'">确认</el-button>

总结

以上方法经过测试,可以对用户操作行为做到精准检测,除ie浏览器外,针对用户关闭、最小化、切出浏览器等操作行为进行监听且有效的上报。用户只需要在针对特殊操作如点击等使用v-log就能做到全面的监控。


本文转载自: https://blog.csdn.net/weixin_43695002/article/details/128728729
版权归原作者 佛系内卷 所有, 如有侵权,请联系我们删除。

“前端埋点需求(vue.js)”的评论:

还没有评论