一宝踪、為什么需要前端埋點
前端數(shù)據(jù)埋點的目的是:
獲取用戶行為以及跟蹤產(chǎn)品在用戶端的使用情況侨糟,并以監(jiān)控數(shù)據(jù)為基礎(chǔ),指明產(chǎn)品優(yōu)化的方向瘩燥。
前端監(jiān)控可以分為三類:數(shù)據(jù)監(jiān)控秕重、性能監(jiān)控和異常監(jiān)控。
(1) 數(shù)據(jù)監(jiān)控
數(shù)據(jù)監(jiān)控厉膀,顧名思義就是監(jiān)聽用戶的行為溶耘。常見的數(shù)據(jù)監(jiān)控包括:
- PV/UV:PV(page view)二拐,即頁面瀏覽量或點擊量。UV:指訪問某個站點或點擊某條新聞的不同IP地址的人數(shù)
- 用戶在每一個頁面的停留時間
- 用戶通過什么入口來訪問該網(wǎng)頁
- 用戶在相應(yīng)的頁面中觸發(fā)的行為
統(tǒng)計這些數(shù)據(jù)是有意義的凳兵,比如我們知道了用戶來源的渠道百新,可以促進產(chǎn)品的推廣,知道用戶在每一個頁面停留的時間庐扫,可以針對停留較長的頁面饭望,增加廣告推送等等。
(2) 性能監(jiān)控
性能監(jiān)控指的是監(jiān)聽前端的性能形庭,主要包括監(jiān)聽網(wǎng)頁或者說產(chǎn)品在用戶端的體驗铅辞。常見的性能監(jiān)控數(shù)據(jù)包括:
- 不同用戶,不同機型和不同系統(tǒng)下的首屏加載時間
- 白屏?xí)r間
- http等請求的響應(yīng)時間
- 靜態(tài)資源整體下載時間
- 頁面渲染時間
- 頁面交互動畫完成時間
這些性能監(jiān)控的結(jié)果碘勉,可以展示前端性能的好壞巷挥,根據(jù)性能監(jiān)測的結(jié)果可以進一步的去優(yōu)化前端性能桩卵,比如兼容低版本瀏覽器的動畫效果验靡,加快首屏加載等等。
(3) 異常監(jiān)控
此外雏节,產(chǎn)品的前端代碼在執(zhí)行過程中也會發(fā)生異常胜嗓,因此需要引入異常監(jiān)控。及時的上報異常情況钩乍,可以避免線上故障的發(fā)上辞州。雖然大部分異常可以通過try catch的方式捕獲寥粹,但是比如內(nèi)存泄漏以及其他偶現(xiàn)的異常難以捕獲变过。常見的需要監(jiān)控的異常包括:
- Javascript的異常監(jiān)控
- 樣式丟失的異常監(jiān)控
二、埋點方案
(1) 代碼埋點
代碼埋點涝涤,就是以嵌入代碼的形式進行埋點媚狰,比如需要監(jiān)控用戶的點擊事件,會選擇在用戶點擊時阔拳,插入一段代碼崭孤,保存這個監(jiān)聽行為或者直接將監(jiān)聽行為以某一種數(shù)據(jù)格式直接傳遞給server端。此外比如需要統(tǒng)計產(chǎn)品的PV和UV的時候糊肠,需要在網(wǎng)頁的初始化時辨宠,發(fā)送用戶的訪問信息等。
代碼埋點的優(yōu)點:
- 可以在任意時刻货裹,精確的發(fā)送或保存所需要的數(shù)據(jù)信息嗤形。
缺點:
- 工作量較大,每一個組件的埋點都需要添加相應(yīng)的代碼
(2) 可視化埋點
通過可視化交互的手段弧圆,代替代碼埋點赋兵。將業(yè)務(wù)代碼和埋點代碼分離还最,提供一個可視化交互的頁面,輸入為業(yè)務(wù)代碼毡惜,通過這個可視化系統(tǒng)拓轻,可以在業(yè)務(wù)代碼中自定義的增加埋點事件等等,最后輸出的代碼耦合了業(yè)務(wù)代碼和埋點代碼经伙。
可視化埋點聽起來比較高大上扶叉,實際上跟代碼埋點還是區(qū)別不大。也就是用一個系統(tǒng)來實現(xiàn)手動插入代碼埋點的過程帕膜。
缺點:
- 可視化埋點可以埋點的控件有限枣氧,不能手動定制。
(3) 無埋點
無埋點并不是說不需要埋點垮刹,而是全部埋點达吞,前端的任意一個事件都被綁定一個標(biāo)識,所有的事件都別記錄下來荒典。通過定期上傳記錄文件酪劫,配合文件解析,解析出來我們想要的數(shù)據(jù)寺董,并生成可視化報告供專業(yè)人員分析因此實現(xiàn)“無埋點”統(tǒng)計覆糟。
從語言層面實現(xiàn)無埋點也很簡單,比如從頁面的js代碼中遮咖,找出dom上被綁定的事件御吞,然后進行全埋點陶珠。
無埋點的優(yōu)點:
- 由于采集的是全量數(shù)據(jù)挟裂,所以產(chǎn)品迭代過程中是不需要關(guān)注埋點邏輯的,也不會出現(xiàn)漏埋背率、誤埋等現(xiàn)象
缺點:
- 無埋點采集全量數(shù)據(jù)话瞧,給數(shù)據(jù)傳輸和服務(wù)器增加壓力
- 無法靈活的定制各個事件所需要上傳的數(shù)據(jù)
三、前端可利用的事件
(1) 瀏覽器窗口事件
| 事件名 | 何時觸發(fā) |
| load | 頁面加載完成時觸發(fā) |
| beforeunload | 窗口關(guān)閉之前觸發(fā) |
| unload | 窗口關(guān)閉時觸發(fā) |
| focus | 窗口得到焦點時觸發(fā) |
| blur | 窗口失去焦點時觸發(fā) |
| error | 頁面上有腳本報錯時觸發(fā) |
| resize | 窗口大小改變時觸發(fā) |
(2) 鼠標(biāo)事件
| 事件名 | 何時觸發(fā) |
| mousedown | 當(dāng)在元素上按下鼠標(biāo)按鈕時觸發(fā) |
| mouseover | 當(dāng)在元素上按下鼠標(biāo)按鈕時觸發(fā) |
| mouseout | 當(dāng)鼠標(biāo)指針移出元素時觸發(fā) |
| mouseup | 當(dāng)在元素上釋放鼠標(biāo)按鈕時觸發(fā) |
| mousewheel | 當(dāng)在元素上滾動鼠標(biāo)滾輪時觸發(fā) |
(3) 鍵盤事件
| 事件名 | 何時觸發(fā) |
| keydown | 用戶按下按鍵觸發(fā) |
| keypress | 用戶按下按鍵觸發(fā) 晚于keydown |
| keyup | 用戶釋放按鍵時觸發(fā) |
(4) 表單事件
| 事件名 | 何時觸發(fā) |
| focus/focusin | 表單元素獲取焦點時觸發(fā) |
| blur/focusout | 表單元素失去焦點時觸發(fā) |
| change | 表單元素值被改變時觸發(fā) |
| input | 表單元素獲得用戶輸入時觸發(fā) |
| select | 表單元素內(nèi)容被選中時觸發(fā) |
| submit | 提交表單時觸發(fā) |
(5) 拖放事件
| 事件名 | 何時觸發(fā) |
| drag | 元素被拖動時觸發(fā) |
| dragstart | 拖動操作開始時觸發(fā) |
| dragover | 當(dāng)元素在有效拖放目標(biāo)上正在被拖動時觸發(fā) |
| dragenter | 當(dāng)元素已被拖動到目標(biāo)區(qū)域時觸發(fā) |
| dragleave | 當(dāng)元素離開有效目標(biāo)時觸發(fā) |
| drop | 當(dāng)被拖動元素放置在目標(biāo)區(qū)域時觸發(fā)Web瀏覽器常用事件 |
注:前端可以利用其中某些事件埋點分析用戶行為并生成前端關(guān)于用戶行為鏈路拓?fù)鋱D,標(biāo)紅的error事件可以捕捉前端錯誤饵筑,可以讓前端精準(zhǔn)找到線上bug埃篓,可以提高bug定位率同窘。
四、前端埋點方案選型和前端上報方案設(shè)計
(1) 監(jiān)控數(shù)據(jù)
首先我們需要明確一個產(chǎn)品或者網(wǎng)頁部脚,普遍需要監(jiān)控和上報的數(shù)據(jù)想邦。監(jiān)控的分為三個階段:用戶進入網(wǎng)頁首頁、用戶在網(wǎng)頁內(nèi)部交互和交互中報錯委刘。每一個階段需要監(jiān)控和上報的數(shù)據(jù)如下圖所示:
(2) 埋點方案
在實際項目初始階段考慮到會有一部分系統(tǒng)改動比較大丧没,為了盡量較少用戶配置以及少修改代碼的原則,所以選取無埋點方式锡移。
(3) 上報周期和上報數(shù)據(jù)類型
如果埋點的事件不是很多呕童,上報可以時時進行,比如監(jiān)控用戶的交互事件淆珊,可以在用戶觸發(fā)事件后夺饲,立刻上報用戶所觸發(fā)的事件類型。如果埋點的事件較多施符,或者說網(wǎng)頁內(nèi)部交互頻繁往声,可以通過本地存儲的方式先緩存上報信息,然后定期上報操刀。
上報的數(shù)據(jù)類型:
{
"elementID": "elm_xxxxx",//觸發(fā)元素的唯一ID
"useragent": "",//用戶的系統(tǒng)
"networkstate": "",//網(wǎng)絡(luò)等信息
"currenturl": "",//當(dāng)前url
"fromurl":"",//從哪一個頁面跳轉(zhuǎn)到當(dāng)前頁面
"ip": "",//ip
"traceid": "",//鏈路標(biāo)識
"fingerprint": "",// 指紋標(biāo)識
"eventtype": "",//事件類型
"userid": "",//用戶
"useriype": "",//用戶類型
"parentid": "",// 記錄前一個鏈路
"spanid": "",//可以使用 elementId替代
"timeStamp": "", // 時間戳
"widgettype": '',// 當(dāng)前元素
}
(4) 埋點和上報舉例
/**
* @author: visupervi
* @Date: 2021/3/5 1:21 下午
* @param:
* @return:
* @Description: 通過用戶點擊行為記錄數(shù)據(jù)
*/
const postPointObj = (data) => $fetch(`http://localhost:8088/apis/setPointData`, data, "post");
document.querySelector("body").addEventListener("click", async (evt) => {
const selector = OptimalSelect.select(evt.target,{
ignore:{
id: true
}
})
const element = document.activeElement.tagName;
const eltType = document.activeElement.type;
const spanId = `spanId_${uuid()}`;
if (element === "BUTTON" || element === "A" || eltType === "button") {
delDomHTML();
let obj = {
userAgent: window.navigator.userAgent,
networkState: window.navigator.connection.effectiveType,
url: window.location.href,
ip: "",
fingerprint: fingerprint,
eventType: "click",
userId: "",
userType: "",
timeStamp: Date.now(),
widgetType: document.activeElement.tagName,
traceId: traceId,
"parentID": "",
spanId: spanId,
};
postPointObj(obj);
console.log("click event", obj);
}
});
(5) 前端埋點系統(tǒng)的前后端通信加密
在上報數(shù)據(jù)的前后端通信中烁挟,需要和server端協(xié)商加密機制婴洼,利用 OpenSSL庫來實現(xiàn)的加密骨坑,OpenSSL已經(jīng)是一個廣泛被采用的加密算法。前端可以采用node的crypto模塊柬采。
首先來看hash算法欢唾,crypto.createHash() 來創(chuàng)建一個Hash實例,可利用的hash算法如下:
- md5
- sha1
- sha256
- sha512
- ripemd160
五粉捻、前端監(jiān)控結(jié)果可視化展示系統(tǒng)的設(shè)計
當(dāng)后端得到前端上報的信息之后礁遣,經(jīng)過數(shù)據(jù)分析和處理,需要前端可視化的展示數(shù)據(jù)分析后的結(jié)果肩刃。
暫時先展示拓?fù)鋱D祟霍。