埋點(diǎn)方案主要流程
1、 在 main.js 文件中生成 capol-log-uuid 埋點(diǎn)會(huì)話(huà)唯一id,并存入sessionStorage中
router.afterEach((to, from, next) => {
//優(yōu)先取url上面攜帶的埋點(diǎn)id
const uuid = to.query.logId ? to.query.logId : Utils.uuid()
console.log('進(jìn)入頁(yè)面,生成回話(huà)id')
sessionStorage.setItem('capol-log-uuid',uuid)
})
2、在 utils 文件夾下添加 commonLog.js 公共埋點(diǎn)方法類(lèi),提供3個(gè)方法:
- 添加埋點(diǎn)函數(shù):CapolLog.pointAdd(dynamicInfo, el)
- 更新埋點(diǎn)函數(shù):CapolLog.pointUpdate(id, type,updateData)
- 更新埋點(diǎn)輔助函數(shù):CapolLog.pointUpdateHelper(event,operateResultBool)
3、封裝v-capol-log指令,監(jiān)聽(tīng)元素點(diǎn)擊事件,觸發(fā)埋點(diǎn)
//通用按鈕埋點(diǎn)指令
Vue.directive('capol-log', {
inserted(el, binding) {
//按鈕點(diǎn)擊執(zhí)行事件
const handleClick = (el, binding) => {
//修飾符
const idFlag = binding.modifiers.idFlag ? 1 : 0;
//綁定值
const data = binding.value
//埋點(diǎn)外部傳參對(duì)象
const dynamicInfo = { idFlag, ...data }
CapolLog.pointAdd(dynamicInfo,el)
}
const wrappedClickEvent = function (event) {
handleClick(el, binding, event)
}
el.addEventListener('click', Utils.debounce(wrappedClickEvent, 300))
el.handleClick = handleClick
},
unbind(el, binding) {
const handleClick = el.handleClick
el.removeEventListener('click', handleClick)
delete el.handleClick
},
})
4、將埋點(diǎn)公共方法添加到Vue.prototype原型對(duì)象中,手動(dòng)調(diào)用,觸發(fā)埋點(diǎn)
startTask(event) {
//模擬接口響應(yīng)時(shí)間2s
setTimeout(() => {
this.$CapolLog
.pointUpdateHelper(event, true)
.then((res) => {
console.log(res)
})
.catch((error) => {
console.error(error)
})
}, 2000)
this.getMajorData()
this.showStartTaskDialog = true
},
埋點(diǎn)接口傳參說(shuō)明
添加埋點(diǎn)參數(shù)
字段 | 是否必填 | 備注說(shuō)明 |
---|---|---|
source | 是 | 來(lái)源端 |
functionType | 是 | 功能類(lèi)型 |
logType | 是 | 日志類(lèi)型 |
info | 是 | 埋點(diǎn)基本信息 |
uuid | 是 | 回話(huà)唯一值 |
menuCode | 否 | 菜單編碼 |
buttonName | 否(點(diǎn)擊按鈕為必填) | 按鈕名稱(chēng)(應(yīng)該帶上下文) |
privateData | 是 | 私有參數(shù)json字符串 |
idFlag | 是 | id值是否需要返回,后續(xù)用于更新 |
更新埋點(diǎn)參數(shù)
字段 | 是否必填 | 備注說(shuō)明 |
---|---|---|
functionType | 是 | 功能類(lèi)型(和添加埋點(diǎn)時(shí)傳參保持一致) |
updateData | 是 | 更新埋點(diǎn)參數(shù)json字符串(必須包含id字段,其他為更新參數(shù)) |
部分參數(shù)枚舉說(shuō)明
functionType(功能類(lèi)型)
功能類(lèi)型key | 功能類(lèi)型val |
---|---|
0 | 按鈕點(diǎn)擊 |
1 | 頁(yè)面初始 |
2 | 文件下載 |
3 | 文件瀏覽 |
4 | 文件分享 |
5 | 文件上傳 |
6 | 選擇模板 |
7 | 進(jìn)度瀏覽 |
8 | 管控事件 |
9 | 圖模關(guān)聯(lián) |
10 | 問(wèn)題導(dǎo)出 |
logType(日志類(lèi)型)
功能類(lèi)型key | 功能類(lèi)型val |
---|---|
0 | 工具埋點(diǎn)點(diǎn)擊 |
1 | 框架埋點(diǎn)初始 |
2 | 文件項(xiàng)目文件下載 |
3 | 文件分享文件下載 |
4 | 管控文件下載 |
5 | 項(xiàng)目文件瀏覽 |
6 | 分享文件瀏覽 |
7 | 管控文件瀏覽 |
8 | 圖紙文件瀏覽 |
9 | 項(xiàng)目文件分享 |
10 | 項(xiàng)目文件上傳 |
11 | 管控文件上傳 |
12 | 選擇模板埋點(diǎn) |
13 | 進(jìn)度瀏覽埋點(diǎn) |
14 | 進(jìn)度管控埋點(diǎn) |
15 | 圖模關(guān)聯(lián)埋點(diǎn) |
16 | 問(wèn)題導(dǎo)出埋點(diǎn) |
source(來(lái)源端)
來(lái)源key | 來(lái)源Val |
---|---|
0 | pc |
1 | android |
2 | ios |
3 | wx |
4 | Capol3D |
5 | Capol2D |
指令埋點(diǎn)詳細(xì)說(shuō)明
實(shí)現(xiàn)方案
1、在需要埋點(diǎn)的元素上綁定 v-capol-log 指令,監(jiān)聽(tīng)元素點(diǎn)擊事件,當(dāng)元素點(diǎn)擊時(shí),自動(dòng)觸發(fā)添加埋點(diǎn)方法,如果 v-capol-log 修飾符idFlag為true,在添加埋點(diǎn)成功后,在該點(diǎn)擊元素上添加capol-log-element 類(lèi)名、data-id(記錄此次埋點(diǎn)id)、data-type(記錄此次埋點(diǎn)類(lèi)型)
<button type="button" class="el-button el-button--default el-button--small is-plain capol-log-element" data-id="1929582931271722" data-type="按鈕點(diǎn)擊">發(fā)起審批任務(wù)</span></button>
2、在點(diǎn)擊事件相關(guān)業(yè)務(wù)執(zhí)行完畢后,通過(guò)點(diǎn)擊事件的event對(duì)象拿到元素上記錄的埋點(diǎn)id、埋點(diǎn)類(lèi)型type,將操作結(jié)果(‘“操作成功” || “操作失敗”)作為更新參數(shù)作為updateData參數(shù),調(diào)用CapolLog.pointUpdate(id, type,updateData)更新埋點(diǎn)方法實(shí)現(xiàn)埋點(diǎn)更新。后臺(tái)將根據(jù)初次埋點(diǎn)時(shí)間、更新埋點(diǎn)時(shí)間,計(jì)算出****此次點(diǎn)擊事件的響應(yīng)時(shí)間responseTime。
使用方案
1、綁定指令
<el-button
v-capol-log.idFlag="{
functionType: 0,
logType: 0,
buttonName: '發(fā)起審批任務(wù)-成功審查',
privateData: { functionName: '發(fā)起審批任務(wù)', menuName: '成果審查',projectId:123,enterpriseId:456 },
}"
plain
@click="startTask"
>發(fā)起審批任務(wù)
</el-button>
指令傳參說(shuō)明:
字段 | 是否必填 | 備注說(shuō)明 |
---|---|---|
idFlag | 否 | 指令修飾符,后續(xù)需要更新埋點(diǎn)必傳 |
functionType | 是 | 功能類(lèi)型,根據(jù)枚舉說(shuō)明表傳對(duì)應(yīng)下標(biāo)即可(eg:按鈕點(diǎn)擊傳0) |
logType | 是 | 日志類(lèi)型,根據(jù)枚舉說(shuō)明表傳對(duì)應(yīng)下標(biāo)即可(eg:工具埋點(diǎn)點(diǎn)擊傳0) |
buttonName | 是 | 按鈕名稱(chēng),需要帶上下文(eg:發(fā)起審批任務(wù)-成功審查) |
privateData | 是 | 私有參數(shù)對(duì)象,functionName(按鈕名稱(chēng))、menuName(菜單名稱(chēng))這兩個(gè)字段必傳,其他字段按需傳遞即可 |
menuCode | 否 | 菜單編碼,不傳優(yōu)先取左側(cè)導(dǎo)航欄高亮菜單code,取不到取當(dāng)前路由code |
2、點(diǎn)擊事件業(yè)務(wù)執(zhí)行完畢后,調(diào)用**this.$CapolLog.pointUpdateHelper(event,operateResultBool)**更新埋點(diǎn)(如果需要)文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-831312.html
startTask(event) {
//模擬接口響應(yīng)時(shí)間2s
setTimeout(() => {
this.$CapolLog
.pointUpdateHelper(event, true)
.then((res) => {
console.log(res)
})
.catch((error) => {
console.error(error)
})
}, 2000)
this.getMajorData()
this.showStartTaskDialog = true
},
頁(yè)面初始埋點(diǎn)詳細(xì)說(shuō)明
待后續(xù)更新…文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-831312.html
主要實(shí)現(xiàn)代碼
commonLog.js(通用埋點(diǎn)方法)
import API from '../api'
import router from '../router'
import Utils from './utils'
import store from '../store'
import { getDeviceInfo } from './getDeviceInfo'
// 獲取功能類(lèi)型
function getFunctionType(val) {
const List = {
0: '按鈕點(diǎn)擊',
1: '頁(yè)面初始',
2: '文件下載',
3: '文件瀏覽',
4: '文件分享',
5: '文件上傳',
6: '選擇模板',
7: '進(jìn)度瀏覽',
8: '管控事件',
9: '圖模關(guān)聯(lián)',
10: '問(wèn)題導(dǎo)出',
}
return List[val] || ''
}
// 獲取日志類(lèi)型
function getLogType(val) {
const List = {
0: '工具埋點(diǎn)點(diǎn)擊',
1: '框架埋點(diǎn)初始',
2: '項(xiàng)目文件下載',
3: '分享文件下載',
4: '管控文件下載',
5: '項(xiàng)目文件瀏覽',
6: '分享文件瀏覽',
7: '管控文件瀏覽',
8: '圖紙文件瀏覽',
9: '項(xiàng)目文件分享',
10: '項(xiàng)目文件上傳',
11: '管控文件上傳',
12: '選擇模板埋點(diǎn)',
13: '進(jìn)度瀏覽埋點(diǎn)',
14: '進(jìn)度管控埋點(diǎn)',
15: '圖模關(guān)聯(lián)埋點(diǎn)',
16: '問(wèn)題導(dǎo)出埋點(diǎn)',
}
return List[val] || ''
}
// 獲取來(lái)源端
// function getScource(val) {
// const List = {
// 0: 'pc', //WEB端
// 1: 'android', //安卓端
// 2: 'ios', //蘋(píng)果端
// 3: 'wx', //小程序端
// 4: 'Capol3D', //速建端
// 5: 'Capol2D', //速繪端
// }
// return List[val] || ''
// }
// 獲取基本埋點(diǎn)信息
function getBasicInfo() {
const basicInfo = getDeviceInfo(null, router.history.current)
console.log(basicInfo, 'basicInfo')
return basicInfo
}
//獲取回話(huà)唯一id
function getUUID() {
let uuid = sessionStorage.getItem('capol-log-uuid')
if (!uuid) {
uuid = Utils.uuid()
sessionStorage.setItem('capol-log-uuid', uuid)
}
return uuid
}
//按照后臺(tái)要求 將對(duì)象轉(zhuǎn)成json字符串
function getJSONObj(obj) {
if (typeof obj === 'object' && obj !== null) {
return JSON.stringify(obj).replace(/"/g, "'")
} else {
return ''
}
}
// 扁平化系統(tǒng)菜單數(shù)組
function flatterArray(arr, finalArr = []) {
if (arr.length === 0) return finalArr
for (let i = 0; i < arr.length; i++) {
const item = arr[i]
if (item.children && item.children.length) {
flatterArray(item.children, finalArr)
} else {
finalArr.push(item)
}
}
return finalArr
}
//獲取菜單code
function getMenuCode() {
//默認(rèn)取路由名稱(chēng)
let code = router.currentRoute.name || ''
let menuList = store.getters.menuList || []
if (menuList.length === 0) {
const queryObj = Utils.getURLParameters(decodeURIComponent(window.location.href))
const { proId, enterpriseId } = queryObj
menuList = JSON.parse(localStorage.getItem('pro_menu_list_' + proId + '_' + enterpriseId))
}
//從系統(tǒng)菜單列表中取code
if (menuList.length) {
const flatterMenuList = flatterArray(menuList)
const activeMenuText = document.querySelector(
'.sidebar-el-menu .el-menu-item.is-active .item span'
)?.innerHTML
const activeMenu = flatterMenuList.find((el) => el.title === activeMenuText)
if (activeMenu) {
code = activeMenu.code
}
}
return code
}
//埋點(diǎn)方法類(lèi)
export default class CapolLog {
/**
* 通用添加埋點(diǎn)函數(shù)
* @param dynamicInfo 添加埋點(diǎn)的參數(shù) (必填)
* @param dynamicInfo 必填項(xiàng)說(shuō)明:functionType(功能類(lèi)型);logType(日志類(lèi)型);privateData(埋點(diǎn)私有參數(shù));idFlag(是否需要后臺(tái)返回此次埋點(diǎn)id,用于后續(xù)更新)
* @param el dom元素,如果有傳,將往dom元素上添加埋點(diǎn)信息 (非必填)
* @returns {Promise} 添加埋點(diǎn)的狀態(tài)
*/
static pointAdd = (dynamicInfo, el) => {
let { functionType, source, logType, menuCode, buttonName, privateData, idFlag } =
dynamicInfo
const params = {
source: source || 'pc', //來(lái)源端
functionType: getFunctionType(functionType), //功能類(lèi)型
logType: getLogType(logType), //日志類(lèi)型
info: getJSONObj(getBasicInfo()), //埋點(diǎn)基本信息
uuid: getUUID(), //回話(huà)唯一值
menuCode: menuCode || getMenuCode(), //菜單編碼 (非必填)
buttonName, //按鈕名稱(chēng)
//私有參數(shù)json字符串
privateData: getJSONObj(privateData),
idFlag: idFlag || 0, //id值是否需要返回
}
return new Promise((resolve, reject) => {
API.log
.capolAddLog(params)
.then((res) => {
if (res.status === 200) {
if (res.data && el) {
el.classList.add('capol-log-element')
el.setAttribute('data-id', res.data)
el.setAttribute('data-type', getFunctionType(functionType))
}
resolve(res)
} else {
reject(res)
}
})
.catch((error) => {
reject(error)
})
})
}
/**
* 更新埋點(diǎn)通用函數(shù)
* @param id 此次需要更新的埋點(diǎn)id (必填)
* @param type 功能類(lèi)型 eg('按鈕點(diǎn)擊') (必填)
* @param updateData 更新的私有參數(shù) (必填)
* @returns {Promise} 返回更新埋點(diǎn)的狀態(tài)
*/
static pointUpdate = (id, type, updateData) => {
const params = {
functionType: type,
updateData: getJSONObj({
id,
...updateData,
}),
}
return new Promise((resolve, reject) => {
API.log
.capolUpdateLog(params)
.then((res) => {
if (res.status === 200) {
resolve(res)
} else {
reject(res)
}
})
.catch((error) => {
reject(error)
})
})
}
/**
* 按鈕點(diǎn)擊更新埋點(diǎn)輔助函數(shù)
* @param event 點(diǎn)擊事件的 event 對(duì)象 (必填)
* @param operateResultBool 點(diǎn)擊事件的操作結(jié)果 true || false (必填)
* @returns {updatePromise} 返回更新埋點(diǎn)的狀態(tài)
*/
static pointUpdateHelper = async (event, operateResultBool) => {
if (!event || operateResultBool === undefined) {
return Promise.reject(new Error('更新埋點(diǎn)參數(shù)缺失'))
}
const updateData = {
operateResult: operateResultBool ? '操作成功' : '操作失敗',
}
console.log(event?.target.closest('.capol-log-element'))
const targetBtn = event?.target.closest('.capol-log-element')
//返回更新埋點(diǎn)的狀態(tài)
let updatePromise
if (targetBtn) {
const id = targetBtn.dataset.id
const type = targetBtn.dataset.type
updatePromise = await this.pointUpdate(id, type, updateData)
} else {
updatePromise = Promise.reject(new Error('獲取不到更新埋點(diǎn)id'))
}
return updatePromise
}
}
到了這里,關(guān)于vue項(xiàng)目前端通用埋點(diǎn)方案的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!