為什么大廠前端監(jiān)控都在用GIF做埋點(diǎn)?
?什么是前端監(jiān)控?
它指的是通過(guò)一定的手段來(lái)獲取用戶行為以及跟蹤產(chǎn)品在用戶端的使用情況,并以監(jiān)控?cái)?shù)據(jù)為基礎(chǔ),為產(chǎn)品優(yōu)化指明方向,為用戶提供更加精確、完善的服務(wù)。
?
前端監(jiān)控
一般來(lái)講一個(gè)成熟的產(chǎn)品,運(yùn)營(yíng)與產(chǎn)品團(tuán)隊(duì)需要關(guān)注用戶在產(chǎn)品內(nèi)的行為記錄,通過(guò)用戶的行為記錄來(lái)優(yōu)化產(chǎn)品,研發(fā)與測(cè)試團(tuán)隊(duì)則需要關(guān)注產(chǎn)品的性能以及異常,確保產(chǎn)品的性能體驗(yàn)以及安全迭代。
「所以前端監(jiān)控一般也分為三大類:」
數(shù)據(jù)監(jiān)控(監(jiān)控用戶行為)
PV/UV: PV(page view):即頁(yè)面瀏覽量或點(diǎn)擊量;UV(unique visitor):指訪問(wèn)某個(gè)站點(diǎn)或點(diǎn)擊某條新聞的不同 IP 地址的人數(shù) 用戶在每一個(gè)頁(yè)面的停留時(shí)間 用戶通過(guò)什么入口來(lái)訪問(wèn)該網(wǎng)頁(yè) 用戶在相應(yīng)的頁(yè)面中觸發(fā)的行為,等...
統(tǒng)計(jì)這些數(shù)據(jù)是有意義的,比如我們知道了用戶來(lái)源的渠道,可以促進(jìn)產(chǎn)品的推廣,知道用戶在每一個(gè)頁(yè)面停留的時(shí)間,可以針對(duì)停留較長(zhǎng)的頁(yè)面,增加廣告推送等等。
性能監(jiān)控(監(jiān)控頁(yè)面性能)
不同用戶,不同機(jī)型和不同系統(tǒng)下的首屏加載時(shí)間 白屏?xí)r間 http 等請(qǐng)求的響應(yīng)時(shí)間 靜態(tài)資源整體下載時(shí)間 頁(yè)面渲染時(shí)間 頁(yè)面交互動(dòng)畫(huà)完成時(shí)間,等...
這些性能監(jiān)控的結(jié)果,可以展示前端性能的好壞,根據(jù)性能監(jiān)測(cè)的結(jié)果可以進(jìn)一步的去優(yōu)化前端性能,盡可能的提高用戶體驗(yàn)。
異常監(jiān)控(監(jiān)控產(chǎn)品、系統(tǒng)異常)
及時(shí)的上報(bào)異常情況,可以避免線上故障的發(fā)上。雖然大部分異??梢酝ㄟ^(guò) try catch 的方式捕獲,但是比如內(nèi)存泄漏以及其他偶現(xiàn)的異常難以捕獲。常見(jiàn)的需要監(jiān)控的異常包括:
Javascript 的異常監(jiān)控 樣式丟失的異常監(jiān)控
埋點(diǎn)上報(bào)
OK,上面我們說(shuō)到了前端監(jiān)控的三個(gè)分類,了解了一個(gè)產(chǎn)品需要監(jiān)控哪些內(nèi)容以及為什么需要監(jiān)控這些內(nèi)容,那么我們應(yīng)該怎么實(shí)現(xiàn)前端監(jiān)控呢?
實(shí)現(xiàn)前端監(jiān)控,第一步肯定是將我們要監(jiān)控的事項(xiàng)(數(shù)據(jù))給收集起來(lái),再提交給后臺(tái)進(jìn)行入庫(kù),最后再給數(shù)據(jù)分析組進(jìn)行數(shù)據(jù)分析,最后處理好的數(shù)據(jù)再同步給運(yùn)營(yíng)或者是產(chǎn)品。數(shù)據(jù)收集的豐富性和準(zhǔn)確性會(huì)直接影響到我們做前端監(jiān)控的質(zhì)量,因?yàn)槲覀儠?huì)以此為基礎(chǔ),為產(chǎn)品的未來(lái)發(fā)展指引方向。
現(xiàn)在常見(jiàn)的埋點(diǎn)上報(bào)方法有三種:手動(dòng)埋點(diǎn)、可視化埋點(diǎn)、無(wú)埋點(diǎn)
手動(dòng)埋點(diǎn)
手動(dòng)埋點(diǎn),也叫代碼埋點(diǎn),即純手動(dòng)寫(xiě)代碼,調(diào)用埋點(diǎn) SDK 的函數(shù),在需要埋點(diǎn)的業(yè)務(wù)邏輯功能位置調(diào)用接口,上報(bào)埋點(diǎn)數(shù)據(jù),像[友盟]、[百度統(tǒng)計(jì)]等第三方數(shù)據(jù)統(tǒng)計(jì)服務(wù)商大都采用這種方案。手動(dòng)埋點(diǎn)讓使用者可以方便地設(shè)置自定義屬性、自定義事件;所以當(dāng)你需要深入下鉆,并精細(xì)化自定義分析時(shí),比較適合使用手動(dòng)埋點(diǎn)。
手動(dòng)埋點(diǎn)的缺陷就是,項(xiàng)目工程量大,需要埋點(diǎn)的位置太多,而且需要產(chǎn)品開(kāi)發(fā)運(yùn)營(yíng)之間相互反復(fù)溝通,容易出現(xiàn)手動(dòng)差錯(cuò),如果錯(cuò)誤,重新埋點(diǎn)的成本也很高。
可視化埋點(diǎn)
通過(guò)可視化交互的手段,代替上述的代碼埋點(diǎn)。將業(yè)務(wù)代碼和埋點(diǎn)代碼分離,提供一個(gè)可視化交互的頁(yè)面,輸入為業(yè)務(wù)代碼,通過(guò)這個(gè)可視化系統(tǒng),可以在業(yè)務(wù)代碼中自定義的增加埋點(diǎn)事件等等,最后輸出的代碼耦合了業(yè)務(wù)代碼和埋點(diǎn)代碼。
可視化埋點(diǎn)的缺陷就是可以埋點(diǎn)的控件有限,不能手動(dòng)定制。
無(wú)埋點(diǎn)
無(wú)埋點(diǎn)則是前端自動(dòng)采集全部事件,上報(bào)埋點(diǎn)數(shù)據(jù),由后端來(lái)過(guò)濾和計(jì)算出有用的數(shù)據(jù)。優(yōu)點(diǎn)是前端只要一次加載埋點(diǎn)腳本,缺點(diǎn)是流量和采集的數(shù)據(jù)過(guò)于龐大,服務(wù)器性能壓力山大。
為什么都用GIF來(lái)做埋點(diǎn)?
發(fā)現(xiàn)過(guò)程
首先說(shuō)一下我是怎么發(fā)現(xiàn)的,前一段時(shí)間,產(chǎn)品提了個(gè)需求,說(shuō)我們現(xiàn)在的書(shū)籍曝光上報(bào)規(guī)范并不是他們想要的數(shù)據(jù),并且以后所有頁(yè)面的書(shū)籍上報(bào)都統(tǒng)一成最新規(guī)范。
曝光規(guī)范:
書(shū)籍出現(xiàn)在可視區(qū)并停留1秒,算作有效曝光 書(shū)籍不能重復(fù)曝光,假如它一直在可視區(qū)滾動(dòng)時(shí)只能上報(bào)一次 當(dāng)它移出可視區(qū)后再回到可視區(qū),再按第一點(diǎn)進(jìn)行曝光
OK,既然要所有頁(yè)面統(tǒng)一,那就只能封裝成通用庫(kù)來(lái)使用了,這里實(shí)現(xiàn)邏輯就不貼了,想看的私聊我發(fā)你,主要的難點(diǎn)就是停留時(shí)長(zhǎng)計(jì)算,以及曝光標(biāo)記。
const?exposeReportClass?=?new?exposeReport({
??????scrollDom:?"",??//?滾動(dòng)容器,建議指定一個(gè)滾動(dòng)容器,不傳默認(rèn)為window
??????watchDom:?".bookitem",?//?監(jiān)聽(tīng)的dom,建議使用class類,標(biāo)簽也支持
??????time:?1000?????????????//?停留有效時(shí)長(zhǎng)ms
});
//?提供兩個(gè)上報(bào)方法
exposeReportClass.didReport(()=>{
??//?手動(dòng)上報(bào)
??//callback
})
exposeReportClass.scrollReport(()=>{
??//?滾動(dòng)上報(bào)
??//callback
})
//?
具體業(yè)務(wù)邏輯之需要放在對(duì)應(yīng)的callback里面,而上報(bào)邏輯開(kāi)發(fā)者無(wú)需考慮,因?yàn)槲业讓右呀?jīng)統(tǒng)一處理好了。
然后我再測(cè)試的時(shí)候就發(fā)現(xiàn),上報(bào)發(fā)的請(qǐng)求居然是通過(guò)圖片發(fā)起的,并不是我們認(rèn)為的接口上報(bào)。

然后我去查了下資料,發(fā)現(xiàn)很多大廠的上報(bào)都是這么干的!
使用GIF上報(bào)的原因
向服務(wù)器端上報(bào)數(shù)據(jù),可以通過(guò)請(qǐng)求接口,請(qǐng)求普通文件,或者請(qǐng)求圖片資源的方式進(jìn)行。只要能上報(bào)數(shù)據(jù),無(wú)論是請(qǐng)求GIF文件還是請(qǐng)求其他普通文件(JS)或者是請(qǐng)求接口,服務(wù)器端其實(shí)并不關(guān)心具體的上報(bào)方式。那為什么所有系統(tǒng)都統(tǒng)一使用了請(qǐng)求GIF圖片的方式上報(bào)數(shù)據(jù)呢?
「防止跨域」
一般而言,打點(diǎn)域名都不是當(dāng)前域名,所以所有的接口請(qǐng)求都會(huì)構(gòu)成跨域。而跨域請(qǐng)求很容易出現(xiàn)由于配置不當(dāng)被瀏覽器攔截并報(bào)錯(cuò),這是不能接受的。但圖片的src屬性并不會(huì)跨域,并且同樣可以發(fā)起請(qǐng)求。(排除接口上報(bào))
「防止阻塞頁(yè)面加載,影響用戶體驗(yàn)」
通常,創(chuàng)建資源節(jié)點(diǎn)后只有將對(duì)象注入到瀏覽器DOM樹(shù)后,瀏覽器才會(huì)實(shí)際發(fā)送資源請(qǐng)求。反復(fù)操作DOM不僅會(huì)引發(fā)性能問(wèn)題,而且載入js/css資源還會(huì)阻塞頁(yè)面渲染,影響用戶體驗(yàn)。
但是圖片請(qǐng)求例外。構(gòu)造圖片打點(diǎn)不僅不用插入DOM,只要在js中new出Image對(duì)象就能發(fā)起請(qǐng)求,而且還沒(méi)有阻塞問(wèn)題,在沒(méi)有js的瀏覽器環(huán)境中也能通過(guò)img標(biāo)簽正常打點(diǎn),這是其他類型的資源請(qǐng)求所做不到的。(排除文件方式)
「相比PNG/JPG,GIF的體積最小」
最小的BMP文件需要74個(gè)字節(jié),PNG需要67個(gè)字節(jié),而合法的GIF,只需要43個(gè)字節(jié)。
同樣的響應(yīng),GIF可以比BMP節(jié)約41%的流量,比PNG節(jié)約35%的流量。
「并且大多采用的是1*1像素的透明GIF來(lái)上報(bào)」
1x1像素是最小的合法圖片。而且,因?yàn)槭峭ㄟ^(guò)圖片打點(diǎn),所以圖片最好是透明的,這樣一來(lái)不會(huì)影響頁(yè)面本身展示效果,二者表示圖片透明只要使用一個(gè)二進(jìn)制位標(biāo)記圖片是透明色即可,不用存儲(chǔ)色彩空間數(shù)據(jù),可以節(jié)約體積。
最后
如果你覺(jué)得這篇內(nèi)容對(duì)你挺有啟發(fā),我想邀請(qǐng)你幫我三個(gè)小忙:
點(diǎn)個(gè)「在看」,讓更多的人也能看到這篇內(nèi)容(喜歡不點(diǎn)在看,都是耍流氓 -_-)
歡迎加我微信「qianyu443033099」拉你進(jìn)技術(shù)群,長(zhǎng)期交流學(xué)習(xí)...
關(guān)注公眾號(hào)「前端下午茶」,持續(xù)為你推送精選好文,也可以加我為好友,隨時(shí)聊騷。

