<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          三分鐘,教你3種前端埋點方式!

          共 4324字,需瀏覽 9分鐘

           ·

          2023-06-20 10:13


          作者:彩虹修狗

          https://juejin.cn/post/7224132741997281338

          前言

          只有了解用戶,我們才能服務(wù)好用戶,而最接近用戶的我們,自然要承擔(dān)起更多的責(zé)任。

          那么在一個企業(yè)中,我們要如何去了解用戶呢?
          最直接有效的方式就是了解用戶的行為,了解用戶在網(wǎng)站中做了什么,呆了多久。
          而如何去實現(xiàn)這一操作,這就涉及到我們前端的埋點了。

          埋點方式

          在聊如何進(jìn)行埋點前,我們先介紹下什么是埋點?

          所謂'埋點'是數(shù)據(jù)采集領(lǐng)域(尤其是用戶行為數(shù)據(jù)采集領(lǐng)域)的術(shù)語,指的是針對特定用戶行為或事件進(jìn)行捕獲、處理和發(fā)送的相關(guān)技術(shù)及其實施過程。. 比如用戶某個icon點擊次數(shù)、觀看某個視頻的時長等等。

          我們可以知道埋點是實際上是對特定事件或者行為的數(shù)據(jù)監(jiān)控和上報,常見的埋點上報方式有ajax,img,navigator.sendBeacon下面介紹下這三種埋點上報方式


          基于ajax的埋點上報

          介紹

          因為埋點實際上是對關(guān)鍵節(jié)點的數(shù)據(jù)進(jìn)行上報是和服務(wù)端交互的一個過程,所以我們可以和后端約定一個接口通過ajax去進(jìn)行數(shù)據(jù)上報。

          代碼實現(xiàn)

          我們可以封裝一個方法,代碼如下:

          function?buryingPointAjax(data)?{
          ??return?new?Promise((resolve,?reject)?=>?{
          ????//?創(chuàng)建ajax請求
          ????const?xhr?=?new?XMLHttpRequest();
          ????//?定義請求接口
          ????xhr.open("post",?'/buryingPoint',?true);
          ????//?發(fā)送數(shù)據(jù)
          ????xhr.send(data);
          ??});
          }

          使用時,直接調(diào)用即可

          let?info?=?{}
          buryingPointAjax(info)?//?這樣就成功上報了info的對象

          缺點

          一般而言,埋點域名并不是當(dāng)前域名,因此請求會存在跨域風(fēng)險,且如果ajax配置不正確可能會瀏覽器攔截。因此使用ajax這類請求并不是萬全之策。

          基于img的埋點上報

          上面可以看到如果使用ajax的話,會存在跨域的問題。而且數(shù)據(jù)上報前端主要是負(fù)責(zé)將數(shù)據(jù)傳遞到后端,并不過分強調(diào)前后端交互。

          因此我們可以通過一些支持跨域的標(biāo)簽去實現(xiàn)數(shù)據(jù)上報功能。

          script,link,img就是我們上報的數(shù)據(jù)的最好對象

          先說結(jié)論,這里推薦使用img標(biāo)簽去實現(xiàn)。

          script及l(fā)ink的缺陷

          因為埋點涉及到請求,因此我們需要保證script和link標(biāo)簽的src可以正常請求
          如果需要請求script和link,我們需要將標(biāo)簽掛載到頁面上。

          驗證缺陷

          不妨驗證下,我們在管理臺中加入以下代碼:

          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'

          創(chuàng)建一個script標(biāo)簽,未掛載中頁面上,并不會發(fā)起請求

          書接上文,當(dāng)我們將這個標(biāo)簽掛載中頁面上時:

          document.body.appendChild(a)

          這時發(fā)起了請求

          結(jié)論

          當(dāng)我們使用script和link進(jìn)行埋點上報時,需要掛載到頁面上,而反復(fù)操作dom會造成頁面性能受影響,而且載入js/css資源還會阻塞頁面渲染,影響用戶體驗,因此對于需要頻繁上報的埋點而言,script和link并不合適。

          基于img做埋點上報

          通常使用img標(biāo)簽去做埋點上報,img標(biāo)簽加載并不需要掛載到頁面上,基于js去new image(),設(shè)置其src之后就可以直接請求圖片。

          驗證img優(yōu)勢

          控制臺去創(chuàng)建一個image標(biāo)簽,如下:

          var?img=new?Image();
          img.src="https://lf3-cdn-tos.bytescm.com/obj/static/xitu_juejin_web/img/MaskGroup.13dfc4f1.png";

          可以看到即便未被掛載到頁面上依舊發(fā)起了請求。

          結(jié)論

          因此當(dāng)我們做埋點上報時,使用img是一個不錯的選擇。

          1. img兼容性好
          2. 無需掛載到頁面上,反復(fù)操作dom
          3. img的加載不會阻塞html的解析,但img加載后并不渲染,它需要等待Render Tree生成完后才和Render Tree一起渲染出來

          注:通常埋點上報會使用gif圖,合法的 GIF 只需要 43 個字節(jié)

          基于Navigator.sendBeacon的埋點上報

          Navigator.sendBeacon是目前通用的埋點上報方案,Navigator.sendBeacon方法接受兩個參數(shù),第一個參數(shù)是目標(biāo)服務(wù)器的 URL,第二個參數(shù)是所要發(fā)送的數(shù)據(jù)(可選),可以是任意類型(字符串、表單對象、二進(jìn)制對象等等)。

          介紹

          navigator.sendBeacon() 方法可用于通過 HTTP POST[1] 將少量數(shù)據(jù) 異步[2] 傳輸?shù)?Web 服務(wù)器。

          作用

          它主要用于將統(tǒng)計數(shù)據(jù)發(fā)送到 Web 服務(wù)器,同時避免了用傳統(tǒng)技術(shù)(如:XMLHttpRequest[3])發(fā)送分析數(shù)據(jù)的一些問題。

          補充

          sendBeacon 如果成功進(jìn)入瀏覽器的發(fā)送隊列后,會返回true;如果受到隊列總數(shù)、數(shù)據(jù)大小的限制后,會返回false。返回ture后,只是表示進(jìn)入了發(fā)送隊列,瀏覽器會盡力保證發(fā)送成功,但是否成功了,不會再有任何返回值。

          例子

          以掘金為例:

          這里發(fā)了一個post請求,將小量的數(shù)據(jù)發(fā)到服務(wù)端,用于統(tǒng)計數(shù)據(jù)

          優(yōu)勢

          相較于img標(biāo)簽,使用navigator.sendBeacon會更規(guī)范,數(shù)據(jù)傳輸上可傳輸資源類型會更多。

          對于ajax在頁面卸載時上報,ajax有可能沒上報完,頁面就卸載了導(dǎo)致請求中斷,因此ajax處理這種情況時必須作為同步操作.

          sendBeacon是異步的,不會影響當(dāng)前頁到下一個頁面的跳轉(zhuǎn)速度,且不受同域限制。這個方法還是異步發(fā)出請求,但是請求與當(dāng)前頁面脫離關(guān)聯(lián),作為瀏覽器的任務(wù),因此可以保證會把數(shù)據(jù)發(fā)出去,不拖延卸載流程。

          總結(jié)

          前端埋點上報常使用ajax,img,navigator.sendBeacon。

          不推薦使用ajax。

          如果考慮兼容性的話,img是不二之選。

          目前最合適的方案是navigator.sendBeacon,不僅是異步的,而且不受同域限制,而且作為瀏覽器的任務(wù),因此可以保證會把數(shù)據(jù)發(fā)出去,不影響頁面卸載。

          常見埋點行為

          點擊觸發(fā)埋點

          綁定點擊事件,當(dāng)點擊目標(biāo)元素時,觸發(fā)埋點上報。

          function?clickButton(url,?data)?{
          ????navigator.sendBeacon(url,?data)
          }

          頁面停留時間上報埋點

          路由文件中,初始化一個startTime,當(dāng)頁面離開時通過路由守衛(wèi)計算停留時間。

          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()
          ?????}
          ?})

          錯誤監(jiān)聽埋點

          通過監(jiān)聽函數(shù)去接收錯誤信息。

          vue錯誤捕獲

          app.config.errorHandler?=?(err)?=>?{?
          ????navigator.sendBeacon(url,?{error:?error.message,?text:?'vue運行異常'?})
          }

          JS異常與靜態(tài)資源加載異常

          window.addEventListener('error',?(error)?=>?{?
          ????if?(error.message)?{?
          ????????navigator.sendBeacon(url,?{error:?error.message,?text:?'js執(zhí)行異常'?})
          ????}?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:?'請求錯誤異常'?})
          ??}
          );

          內(nèi)容可見埋點

          通過交叉觀察器去監(jiān)聽當(dāng)前元素是否出現(xiàn)在頁面

          //?可見性發(fā)生變化后的回調(diào)?
          function?callback(data)?{?
          ????navigator.sendBeacon(url,?{?target:?data[0].target,?text:?'內(nèi)容可見'?})?
          }?
          //?交叉觀察器配置項?
          let?options?=?{};?
          //?生成交叉觀察器?
          const?observer?=?new?IntersectionObserver(callback);?
          //?獲取目標(biāo)節(jié)點?
          let?target?=?document.getElementById("target");?
          //?監(jiān)聽目標(biāo)元素?
          observer.observe(target);


          參考資料

          [1]

          HTTP POST: https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Methods/POST

          [2]

          異步: https://developer.mozilla.org/zh-CN/docs/Glossary/Asynchronous

          [3]

          XMLHttpRequest: https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest


          瀏覽 41
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  91久久成人| 亚洲A级黄片 | 青青在线视频 | 久草青娱乐小说在线视频 | 日本高清视频一区二区三区 |