三分鐘,教你三種前端埋點方式!再也不怕面試被問到埋點了!
前言
大家好,我是林三心,用最通俗易懂的話講最難的知識點是我的座右銘,基礎是進階的前提是我的初心。
只有瞭解用戶,我們才能服務好用戶,而最接近用戶的我們,自然要承擔起更多的責任。
那麼在一個企業中,我們要如何去了解用戶呢?
最直接有效的方式就是了解用戶的行爲,瞭解用戶在網站中做了什麼,呆了多久。
而如何去實現這一操作,這就涉及到我們前端的埋點了。
埋點方式
在聊如何進行埋點前,我們先介紹下什麼是埋點?
所謂'埋點'是數據採集領域(尤其是用戶行爲數據採集領域)的術語,指的是針對特定用戶行爲或事件進行捕獲、處理和發送的相關技術及其實施過程。. 比如用戶某個icon點擊次數、觀看某個視頻的時長等等。
從數據產品經理視角,聊聊埋點的意義 | 人人都是產品經理 (woshipm.com)[1]
基於此我們可以知道埋點是實際上是對特定事件或者行爲的數據監控和上報,常見的埋點上報方式有ajax,img,navigator.sendBeacon下面介紹下這三種埋點上報方式
基於 ajax 的埋點上報
介紹
因爲埋點實際上是對關鍵節點的數據進行上報是和服務端交互的一個過程,所以我們可以和後端約定一個接口通過 ajax 去進行數據上報。
代碼實現
我們可以封裝一個方法,代碼如下:
function buryingPointAjax(data) {
return new Promise((resolve, reject) => {
// 創建ajax請求
const xhr = new XMLHttpRequest();
// 定義請求接口
xhr.open("post", '/buryingPoint', true);
// 發送數據
xhr.send(data);
});
}
複製代碼
使用時,直接調用即可
let info = {}
buryingPointAjax(info) // 這樣就成功上報了info的對象
複製代碼
缺點
一般而言,埋點域名並不是當前域名,因此請求會存在跨域風險,且如果 ajax 配置不正確可能會瀏覽器攔截。因此使用 ajax 這類請求並不是萬全之策。
基於 img 的埋點上報
上面可以看到如果使用 ajax 的話,會存在跨域的問題。而且數據上報前端主要是負責將數據傳遞到後端,並不過分強調前後端交互。
因此我們可以通過一些支持跨域的標籤去實現數據上報功能。
script,link,img就是我們上報的數據的最好對象
先說結論,這裏推薦使用 img 標籤去實現。
script 及 link 的缺陷
因爲埋點涉及到請求,因此我們需要保證script和link標籤的src可以正常請求
。
如果需要請求 script 和 link,我們需要將標籤掛載到頁面上。
驗證缺陷
不妨驗證下,我們在管理臺中加入以下代碼:
let a = document.createElement('script')
a.src = 'https://lf-headquarters-speed.yhgfb-cn-static.com/obj/rc-client-security/web/stable/1.0.0.28/bdms.js'
複製代碼
創建一個 script 標籤,未掛載中頁面上,並不會發起請求
書接上文,當我們將這個標籤掛載中頁面上時:
document.body.appendChild(a)
複製代碼
這時發起了請求
結論
當我們使用script和link進行埋點上報時,需要掛載到頁面上,而反覆操作dom會造成頁面性能受影響,而且載入js/css資源還會阻塞頁面渲染,影響用戶體驗
,因此對於需要頻繁上報的埋點而言,script 和 link 並不合適。
基於 img 做埋點上報
通常使用 img 標籤去做埋點上報,img標籤加載並不需要掛載到頁面上,基於js去new image(),設置其src之後就可以直接請求圖片。
驗證 img 優勢
控制檯去創建一個 image 標籤,如下:
var img=new Image();
img.src="https://lf3-cdn-tos.bytescm.com/obj/static/xitu_juejin_web/img/MaskGroup.13dfc4f1.png";
複製代碼
可以看到即便未被掛載到頁面上依舊發起了請求。
結論
因此當我們做埋點上報時,使用 img 是一個不錯的選擇。
-
img 兼容性好
-
無需掛載到頁面上,反覆操作 dom
-
img 的加載不會阻塞 html 的解析,但 img 加載後並不渲染,它需要等待 Render Tree 生成完後才和 Render Tree 一起渲染出來
注:通常埋點上報會使用 gif 圖,合法的 GIF 只需要 43 個字節
基於 Navigator.sendBeacon 的埋點上報
Navigator.sendBeacon 是目前通用的埋點上報方案,Navigator.sendBeacon方法接受兩個參數,第一個參數是目標服務器的 URL,第二個參數是所要發送的數據(可選),可以是任意類型(字符串、表單對象、二進制對象等等)。
介紹
navigator.sendBeacon()
方法可用於通過 HTTP POST[2] 將少量數據 異步 [3] 傳輸到 Web 服務器。
作用
它主要用於將統計數據發送到 Web 服務器,同時避免了用傳統技術(如:XMLHttpRequest
[4])發送分析數據的一些問題。
補充
sendBeacon 如果成功進入瀏覽器的發送隊列後,會返回 true;如果受到隊列總數、數據大小的限制後,會返回 false。返回 ture 後,只是表示進入了發送隊列,瀏覽器會盡力保證發送成功,但是否成功了,不會再有任何返回值。
例子
以掘金爲例:
這裏發了一個 post 請求,將小量的數據發到服務端,用於統計數據
優勢
相較於 img 標籤,使用 navigator.sendBeacon 會更規範,數據傳輸上可傳輸資源類型會更多。
對於 ajax 在頁面卸載時上報,ajax 有可能沒上報完,頁面就卸載了導致請求中斷,因此 ajax 處理這種情況時必須作爲同步操作.
sendBeacon是異步的,不會影響當前頁到下一個頁面的跳轉速度,且不受同域限制。這個方法還是異步發出請求,但是請求與當前頁面脫離關聯,作爲瀏覽器的任務,因此可以保證會把數據發出去,不拖延卸載流程。
總結
前端埋點上報常使用 ajax,img,navigator.sendBeacon。
不推薦使用 ajax。
如果考慮兼容性的話,img 是不二之選。
目前最合適的方案是 navigator.sendBeacon,不僅是異步的,而且不受同域限制,而且作爲瀏覽器的任務,因此可以保證會把數據發出去,不影響頁面卸載。
常見埋點行爲
點擊觸發埋點
綁定點擊事件,當點擊目標元素時,觸發埋點上報。
function clickButton(url, data) {
navigator.sendBeacon(url, data)
}
複製代碼
頁面停留時間上報埋點
路由文件中,初始化一個 startTime,當頁面離開時通過路由守衛計算停留時間。
let url = ''// 上報地址
let startTime = Date.now()
let currentTime = ''
router.beforeEach((to, from, next) => {
if (to) {
currentTime = Date.now()
stayTime = parseInt(currentTime - startTime)
navigator.sendBeacon(url, {time: stayTime})
startTime = Date.now()
}
})
複製代碼
錯誤監聽埋點
通過監聽函數去接收錯誤信息。
vue 錯誤捕獲
app.config.errorHandler = (err) => {
navigator.sendBeacon(url, {error: error.message, text: 'vue運行異常' })
}
複製代碼
JS 異常與靜態資源加載異常
window.addEventListener('error', (error) => {
if (error.message) {
navigator.sendBeacon(url, {error: error.message, text: 'js執行異常' })
} else {
navigator.sendBeacon(url, {error: error.filename, text: '資源加載異常' })
}
}, true)
複製代碼
請求錯誤捕獲
axios.interceptors.response.use(
(response) => {
if (response.code == 200) {
return Promise.resolve(response);
} else {
return Promise.reject(response);
}
},
(error) => {
// 返回錯誤邏輯
navigator.sendBeacon(url, {error: error, text: '請求錯誤異常' })
}
);
複製代碼
內容可見埋點
通過交叉觀察器去監聽當前元素是否出現在頁面
// 可見性發生變化後的回調
function callback(data) {
navigator.sendBeacon(url, { target: data[0].target, text: '內容可見' })
}
// 交叉觀察器配置項
let options = {};
// 生成交叉觀察器
const observer = new IntersectionObserver(callback);
// 獲取目標節點
let target = document.getElementById("target");
// 監聽目標元素
observer.observe(target);
作者:彩虹修狗
鏈接:https://juejin.cn/post/7224132741997281338
來源:稀土掘金
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/EFymXMy80BYEQLE33aKHtA