<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>

          通過(guò)自定義 Vue 指令實(shí)現(xiàn)前端曝光埋點(diǎn)

          共 8410字,需瀏覽 17分鐘

           ·

          2021-06-26 07:30

          ??  這是第 94 篇不摻水的原創(chuàng),想要了解更多,請(qǐng)戳上方藍(lán)色字體:政采云前端團(tuán)隊(duì) 關(guān)注我們吧~

          本文首發(fā)于政采云前端團(tuán)隊(duì)博客:通過(guò)自定義 Vue 指令實(shí)現(xiàn)前端曝光埋點(diǎn)

          https://www.zoo.team/article/vue-command-buried-point

          前言

          互聯(lián)網(wǎng)發(fā)展至今,數(shù)據(jù)的重要性已經(jīng)不言而喻,尤其是在電商公司,數(shù)據(jù)的統(tǒng)計(jì)分析尤為重要,通過(guò)數(shù)據(jù)分析可以提升用戶的購(gòu)買體驗(yàn),方便運(yùn)營(yíng)和產(chǎn)品調(diào)整銷售策略等等。埋點(diǎn)就是網(wǎng)站分析的一種常用的數(shù)據(jù)采集方法。

          埋點(diǎn)按照獲取數(shù)據(jù)的方式一般可以分為以下 3 種:

          • 頁(yè)面埋點(diǎn):統(tǒng)計(jì)用戶進(jìn)入或離開頁(yè)面的各種維度信息,如頁(yè)面瀏覽次數(shù)(PV)、瀏覽頁(yè)面人數(shù)(UV)、頁(yè)面停留時(shí)間、瀏覽器信息等。
          • 點(diǎn)擊埋點(diǎn):統(tǒng)計(jì)用戶在應(yīng)用內(nèi)的每一次點(diǎn)擊事件,如新聞的瀏覽次數(shù)、文件下載的次數(shù)、推薦商品的命中次數(shù)等。
          • 曝光埋點(diǎn):統(tǒng)計(jì)具體區(qū)域是否被用戶瀏覽到,如活動(dòng)的引流入口的顯示、投放廣告的顯示等。

          政采云前端團(tuán)隊(duì)(ZooTeam)通過(guò)渾儀系統(tǒng)實(shí)現(xiàn)數(shù)據(jù)采集及數(shù)據(jù)可視化,分析量化的能力,想了解渾儀系統(tǒng)或者還不了解埋點(diǎn)的同學(xué)可以先閱讀 前端工程實(shí)踐之?dāng)?shù)據(jù)埋點(diǎn)分析系統(tǒng)

          渾儀系統(tǒng)的數(shù)據(jù)采集是基于代碼侵入式埋點(diǎn)方案實(shí)現(xiàn)的,提供了自動(dòng)發(fā)送和手動(dòng)調(diào)用埋點(diǎn)信息上報(bào)接口發(fā)送兩種方式實(shí)現(xiàn)埋點(diǎn)數(shù)據(jù)上報(bào)。其中頁(yè)面埋點(diǎn)點(diǎn)擊埋點(diǎn)是使用自動(dòng)上報(bào)的方式實(shí)現(xiàn),在 DOM 節(jié)點(diǎn)掛載特殊屬性,通過(guò)埋點(diǎn)采集 JSSDK 監(jiān)聽掛載了相應(yīng)屬性對(duì)應(yīng)的事件,在事件觸發(fā)時(shí)進(jìn)行埋點(diǎn)數(shù)據(jù)上報(bào)。曝光埋點(diǎn)由于涉及到有效曝光邏輯的判斷,自動(dòng)上報(bào)不能滿足相應(yīng)的需求,所以我們采用手動(dòng)調(diào)用接口方式進(jìn)行埋點(diǎn)數(shù)據(jù)上報(bào)。

          有效曝光

          先舉個(gè)例子:

          上圖是某電商首頁(yè)底部的推薦區(qū)域,為了衡量用戶對(duì)推薦結(jié)果的感興趣程度,需要計(jì)算推薦區(qū)域的點(diǎn)擊率(點(diǎn)擊次數(shù)/曝光次數(shù))。為了保證點(diǎn)擊率的準(zhǔn)確性,我們必須確保用戶真正的瀏覽到了這些商品,由于用戶瀏覽商品的不確定性會(huì)發(fā)生相同商品的頻繁曝光,我們還要避免重復(fù)的曝光行為。所以我們需要制定一套邏輯來(lái)規(guī)定何時(shí)進(jìn)行曝光埋點(diǎn)的數(shù)據(jù)上報(bào)。比如:

          1. 商品卡片必須完全的出現(xiàn)在瀏覽器可視化區(qū)域內(nèi)。
          2. 商品必須在可視化區(qū)域內(nèi)停留 5s 以上。
          3. 用戶進(jìn)入頁(yè)面到離開頁(yè)面相同的商品只進(jìn)行一次曝光。

          滿足以上規(guī)定的曝光就是一次有效曝光。了解了有效曝光后,我們來(lái)看看曝光埋點(diǎn)實(shí)現(xiàn)最重要的一環(huán),如何判斷元素出現(xiàn)在頁(yè)面的可視化區(qū)域內(nèi)。

          判斷元素出現(xiàn)在頁(yè)面的可視化區(qū)域內(nèi)

          我們首先想到商品曝光類似于圖片懶加載的形式,通過(guò)監(jiān)聽 scroll 事件,調(diào)用 Element.getBoundingClientRect() 方法以獲取相關(guān)元素的邊界信息,然后判斷元素是否出現(xiàn)在頁(yè)面的可視化區(qū)域內(nèi)。由于 scroll 事件頻發(fā)觸發(fā),計(jì)算量很大,所以很容易造成性能問(wèn)題,雖然我們可以采用防抖節(jié)流等方式去解決。

          目前有一個(gè)新的 IntersectionObserver API,提供了一種異步檢測(cè)目標(biāo)元素與祖先元素或 viewport(可視窗口)相交情況變化的方法。可以自動(dòng)"觀察"元素是否可見。

          IntersectionObserver基本用法

          let options = {
              rootdocument.querySelector('#scrollArea'),
              rootMargin'0px',
              threshold1.0
          }
          let callback =(entries, observer) => {
            entries.forEach(entry => {});
          };
          let observer = new IntersectionObserver(callback, options);

          IntersectionObserver 是瀏覽器原生提供的構(gòu)造函數(shù),接受兩個(gè)參數(shù):callback 是可見性變化時(shí)的回調(diào)函數(shù),option 是配置對(duì)象(該參數(shù)可選),返回一個(gè) observer 實(shí)例。我們可以看到,創(chuàng)建一個(gè) IntersectionObserver 對(duì)象,接受兩個(gè)參數(shù):callback 可見性變化時(shí)的回調(diào)函數(shù),該回調(diào)函數(shù)將會(huì)在目標(biāo)(target)元素和根(root)元素的交集大小超過(guò)閾值(threshold)規(guī)定的大小時(shí)候被執(zhí)行。

          options 是配置對(duì)象,它有以下字段:

          • root:指定根 (root) 元素,用于檢查目標(biāo)的可見性。必須是目標(biāo)元素的父級(jí)元素。如果未指定或者為 null,則默認(rèn)為瀏覽器視窗。
          • rootMargin:根 (root) 元素的外邊距。類似于 CSS 中的 margin 屬性。默認(rèn)值為 0。
          • threshold:target 元素和 root 元素相交程度達(dá)到該值的時(shí)候 callback 函數(shù)將會(huì)被執(zhí)行,可以是單一的Number 也可以是 Number 數(shù)組,當(dāng)為數(shù)組時(shí)每達(dá)到該值都會(huì)執(zhí)行 callback 函數(shù)。

          我們通過(guò)實(shí)例的方法可以指定觀察哪個(gè) DOM 節(jié)點(diǎn)。實(shí)例的方法有:

          • IntersectionObserver.observe():使 IntersectionObserver 開始監(jiān)聽一個(gè)目標(biāo)元素。
          • IntersectionObserver.disconnect():使 IntersectionObserver 對(duì)象停止監(jiān)聽工作。
          • IntersectionObserver.takeRecords():返回所有觀察目標(biāo)的 IntersectionObserverEntry 對(duì)象數(shù)組。
          • IntersectionObserver.unobserve():使 IntersectionObserver 停止監(jiān)聽特定目標(biāo)元素。

          IntersectionObserverEntry 對(duì)象提供目標(biāo)元素的信息,一共有七個(gè)屬性:

          • IntersectionObserverEntry.target :需要觀察的目標(biāo)元素,是一個(gè) DOM 節(jié)點(diǎn)對(duì)象 。
          • IntersectionObserverEntry.boundingClientRect:返回包含目標(biāo)元素的邊界信息。邊界的計(jì)算方式與 Element.getBoundingClientRect() 相同。
          • IntersectionObserverEntry.intersectionRect :用來(lái)描述根和目標(biāo)元素的相交區(qū)域的信息。
          • IntersectionObserverEntry.intersectionRatio:返回 intersectionRect 與 boundingClientRect 的比例值,0 為完全不可見,1 為完全可見。
          • IntersectionObserverEntry.isIntersecting:返回一個(gè)布爾值, 如果根與目標(biāo)元素相交(即從不可視狀態(tài)變?yōu)榭梢暊顟B(tài)),則返回 true。如果返回 false,變換是從可視狀態(tài)到不可視狀態(tài)。
          • IntersectionObserverEntry.rootBounds :根元素的區(qū)域的信息。
          • IntersectionObserverEntry.time:可見性狀態(tài)發(fā)生改變時(shí)間的時(shí)間戳,單位為毫秒。

          目標(biāo)元素的可見性變化時(shí),就會(huì)調(diào)用觀察器的回調(diào)函數(shù) callbackcallback函數(shù)的參數(shù) entries 是一個(gè)數(shù)組,每個(gè)成員都是一個(gè) IntersectionObserverEntry 對(duì)象,observer 是被調(diào)用的 IntersectionObserver 實(shí)例。callback 函數(shù)一般會(huì)被調(diào)用兩次,一次是目標(biāo)元素進(jìn)入可視化區(qū)域,另一次是離開可視化區(qū)域。配置 options.threshold 會(huì)影響 callback 函數(shù)的調(diào)用次數(shù)。

          我們?cè)賮?lái)看看 Intersection Observer API 的瀏覽器兼容情況

          我們看到是存在兼容性問(wèn)題的,好在已經(jīng)有了兼容的 polyfill (https://github.com/w3c/IntersectionObserver/tree/master/polyfill)。當(dāng)前瀏覽器不支持 Intersection Observer API 時(shí),使用 Element.getBoundingClientRect() 去實(shí)現(xiàn) Intersection Observer API。

          具體實(shí)現(xiàn)

          了解了 Intersection Observer 的基本用法了以后,下面我們來(lái)實(shí)現(xiàn)前端的曝光埋點(diǎn)。因?yàn)闃I(yè)務(wù)是基于 Vue 實(shí)現(xiàn)的,所以我們通過(guò)自定義 Vue 指令實(shí)現(xiàn)前端的曝光埋點(diǎn)。

          首先我們自定義一個(gè) visually 指令,當(dāng)指令第一次綁定在元素上時(shí)使用 IntersectionObserver 監(jiān)聽目標(biāo)元素,當(dāng)指令從元素上解綁時(shí)停止監(jiān)聽目標(biāo)元素。

          const options = {
              rootnull//默認(rèn)瀏覽器視窗
              threshold1 //元素完全出現(xiàn)在瀏覽器視窗內(nèi)才執(zhí)行callback函數(shù)。
          }
          const callback =(entries, observer) => {
            entries.forEach(entry => {});
          };
          const observer = new IntersectionObserver(callback, options);
          const addListenner = (ele, binding) => {
           observer.observe(ele);
          };
          const removeListener = (ele) => {
            observer.unobserve(ele);
          };
          //自定義曝光指令
          Vue.directive('visually', {
            bind: addListenner,
            unbind: removeListener,
          });

          我們需要一個(gè) List 將已經(jīng)上報(bào)過(guò)的埋點(diǎn)信息記錄下來(lái),防止重復(fù)曝光。

          let visuallyList = []; //記錄已經(jīng)上報(bào)過(guò)的埋點(diǎn)信息
          const addListenner = (ele, binding) => {
           if(visuallyList.indexOf(binding.value) !== -1return;
           
           observer.observe(ele);
          };

          我們將要上報(bào)的信息綁定在目標(biāo)元素的 'visually-data' 屬性中,當(dāng)目標(biāo)元素出現(xiàn)在視窗內(nèi)時(shí),并停留 5 秒以上時(shí),我們上報(bào)埋點(diǎn)信息。

          let timer = {}; //增加定時(shí)器對(duì)象
          const callback = entries => {
            entries.forEach(entry => {
              let visuallyData = null;
              try {
                visuallyData = JSON.parse(entry.target.getAttribute('visually-data'));
              } catch (e) {
                visuallyData = null;
                console.error('埋點(diǎn)數(shù)據(jù)格式異常', e);
              }
              //沒有埋點(diǎn)數(shù)據(jù)取消上報(bào)
              if (!visuallyData) {
                observer.unobserve(entry.target);
                return;
              }
              
              if (entry.isIntersecting) {
                timer[visuallyData.id] = setTimeout(function({
                  //上報(bào)埋點(diǎn)信息
                  sendUtm(visuallyData).then(res => {
                    if (res.success) {
                      //上報(bào)成功后取消監(jiān)聽
                      observer.unobserve(entry.target);
                      visuallyList.push(visuallyData.id);
                      timer[visuallyData.id] = null;
                    }
                  });
                }, 5000);
            } else {
              if (timer[visuallyData.id]) {
                clearTimeout(timer[visuallyData.id]);
                timer[visuallyData.id] = null;
              }
            }
            });
          };

          最后我們引入 polyfill 實(shí)現(xiàn) IE 的兼容,封裝一個(gè)全局指令。

          require('intersection-observer');
          export default Vue => {
           ...
            //自定義曝光指令
            Vue.directive('visually', {
              bind: addListenner,
              unbind: removeListener,
            });
          };

          我們通過(guò) Vue.use() 引入組件后,就可以在業(yè)務(wù)代碼中直接通過(guò)指令實(shí)現(xiàn)曝光埋點(diǎn)。曝光數(shù)據(jù) visuallyData 中必須要有一個(gè)唯一 ID。

          <div v-visually="visuallyData.id" :visually-data="JSON.stringify(visuallyData)" class="browse"></div>

          總結(jié)

          埋點(diǎn)是數(shù)據(jù)分析的基礎(chǔ),埋點(diǎn)數(shù)據(jù)統(tǒng)計(jì)的準(zhǔn)確性對(duì)后續(xù)的數(shù)據(jù)分析非常重要,所以我們?cè)诮y(tǒng)計(jì)曝光埋點(diǎn)的時(shí)候一定要基于適用場(chǎng)景優(yōu)先制定曝光埋點(diǎn)的規(guī)則。本文只是針對(duì)前端曝光埋點(diǎn)的實(shí)現(xiàn)方案,如有問(wèn)題處,請(qǐng)大佬們多多交流。

          看完兩件事

          如果你覺得這篇內(nèi)容對(duì)你挺有啟發(fā),我想邀請(qǐng)你幫我兩件小事

          1.點(diǎn)個(gè)「在看」,讓更多人也能看到這篇內(nèi)容(點(diǎn)了在看」,bug -1 ??

          2.關(guān)注公眾號(hào)「政采云前端團(tuán)隊(duì)」,持續(xù)為你推送精選好文

          招賢納士

          政采云前端團(tuán)隊(duì)(ZooTeam),一個(gè)年輕富有激情和創(chuàng)造力的前端團(tuán)隊(duì),隸屬于政采云產(chǎn)品研發(fā)部,Base 在風(fēng)景如畫的杭州。團(tuán)隊(duì)現(xiàn)有 40 余個(gè)前端小伙伴,平均年齡 27 歲,近 3 成是全棧工程師,妥妥的青年風(fēng)暴團(tuán)。成員構(gòu)成既有來(lái)自于阿里、網(wǎng)易的“老”兵,也有浙大、中科大、杭電等校的應(yīng)屆新人。團(tuán)隊(duì)在日常的業(yè)務(wù)對(duì)接之外,還在物料體系、工程平臺(tái)、搭建平臺(tái)、性能體驗(yàn)、云端應(yīng)用、數(shù)據(jù)分析及可視化等方向進(jìn)行技術(shù)探索和實(shí)戰(zhàn),推動(dòng)并落地了一系列的內(nèi)部技術(shù)產(chǎn)品,持續(xù)探索前端技術(shù)體系的新邊界。

          如果你想改變一直被事折騰,希望開始能折騰事;如果你想改變一直被告誡需要多些想法,卻無(wú)從破局;如果你想改變你有能力去做成那個(gè)結(jié)果,卻不需要你;如果你想改變你想做成的事需要一個(gè)團(tuán)隊(duì)去支撐,但沒你帶人的位置;如果你想改變既定的節(jié)奏,將會(huì)是“5 年工作時(shí)間 3 年工作經(jīng)驗(yàn)”;如果你想改變本來(lái)悟性不錯(cuò),但總是有那一層窗戶紙的模糊… 如果你相信相信的力量,相信平凡人能成就非凡事,相信能遇到更好的自己。如果你希望參與到隨著業(yè)務(wù)騰飛的過(guò)程,親手推動(dòng)一個(gè)有著深入的業(yè)務(wù)理解、完善的技術(shù)體系、技術(shù)創(chuàng)造價(jià)值、影響力外溢的前端團(tuán)隊(duì)的成長(zhǎng)歷程,我覺得我們?cè)摿牧摹H魏螘r(shí)間,等著你寫點(diǎn)什么,發(fā)給 [email protected]

          瀏覽 52
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  色婷婷在线小视频 | 操操操操操操操逼 | 在线看毛片网站 | 人人操人人插人人摸人人爽人人 | 欧美操逼免费视频 |