主頁 > 前端設計 > 揭開JS無埋點技術的神秘面紗

揭開JS無埋點技術的神秘面紗

2021-01-25 11:24:53 前端設計

一、背景

相信很多人都接觸過**“埋點”這個概念,無論是前端還是后端開發,我們都可以使用這門技術來生產出一些運營性質的原始資料(介面耗時、程式安裝/啟動、用戶互動行為等等),然后分析它們得到一些抽象指標(例如留存率、轉化率),進而決定產品運營或者代碼優化的方向,現在業界有許多比較知名資料平臺,比如Google Analytics、Facebook Pixel、Mixpanel、GrowingIO、諸葛IO、TalkingData、神策資料等數不勝數一大票,這些平臺有單純做資料分析的,也有服務于特定領域例如廣告監測轉化的,都提供了多端(Android、iOS、Web、小程式、ReactNative)的埋點SDK和比較全面的BI服務,這一兩年,不少平臺都開始宣傳一種叫“無埋點”**的技術,下面以Web端為例,揭開它的神秘面紗,

二、什么是無埋點?

**“無埋點”在國外一些平臺被叫做Codeless Tracking,顧名思義就是可以寫“更少”的埋點代碼,而“代碼埋點”**一般需要開發人員撰寫代碼,監聽某個html元素的產生的事件,然后呼叫上報資料的介面,發送資料,而無埋點則可以由非技術人員(例如運營、產品),在可視化的工具中作出配置,然后就可以將html元素中產生的行為上報到后臺,下面是Mixpanel平臺的可視化工具的截圖,

在這個工具里,需要首先輸入頁面的url,頁面加載完成后,會出現可視化配置的工具條,點擊創建事件,就可以進入元素選擇模式,用滑鼠點擊頁面上的某個元素(例如button、a這些element),就可以在彈出的對話框里面,設定這個事件的名稱(比如叫TEST),保存這個配置之后,如果頁面在瀏覽器中被瀏覽,剛才配置的那個按鈕發生點擊時,就會向后臺上報一個TEST事件,我們還可以設定上報TEST事件的時候,帶上一些屬性(properties),這些屬性同樣也是在頁面中用滑鼠去選擇,然后保存起來的,

看到這里,首先從產品層面上,我們比較具體的了解到“無埋點”到底是干什么的了,無埋點就是用可視化工具配置頁面中需要被監測的元素,并設定這個元素產生行為的時候需要上報的資料,但是還有非常關鍵的一點必須提到,要讓“無埋點”作業起來,頁面里面還是必須嵌入了一段JS SDK的基礎代碼,只是不需要再去呼叫SDK具體的資料上報介面罷了,

所以,“無埋點”技術的關鍵是:

  • 操作可視化配置工具,保存配置
  • SDK基礎代碼如何根據配置上報行為

下面介紹一下如何實作這兩個關鍵,

三、關鍵技術

1. 基礎代碼

和代碼埋點一樣,要讓“無埋點”作業起來,網頁里也必須有一段“基礎代碼”,

<!-- start Mixpanel --><script type="text/javascript">(function(e,a){if(!a.__SV){var b=window;try{var c,l,i,j=b.location,g=j.hash;c=function(a,b){return(l=a.match(RegExp(b+"=([^&]*)")))?l[1]:null};g&&c(g,"state")&&(i=JSON.parse(decodeURIComponent(c(g,"state"))),"mpeditor"===i.action&&(b.sessionStorage.setItem("_mpcehash",g),history.replaceState(i.desiredHash||"",e.title,j.pathname+j.search)))}catch(m){}var k,h;window.mixpanel=a;a._i=[];a.init=function(b,c,f){function e(b,a){var c=a.split(".");2==c.length&&(b=b[c[0]],a=c[1]);b[a]=function(){b.push([a].concat(Array.prototype.slice.call(arguments,
0)))}}var d=a;"undefined"!==typeof f?d=a[f]=[]:f="mixpanel";d.people=d.people||[];d.toString=function(b){var a="mixpanel";"mixpanel"!==f&&(a+="."+f);b||(a+=" (stub)");return a};d.people.toString=function(){return d.toString(1)+".people (stub)"};k="disable time_event track track_pageview track_links track_forms register register_once alias unregister identify name_tag set_config reset opt_in_tracking opt_out_tracking has_opted_in_tracking has_opted_out_tracking clear_opt_in_out_tracking people.set people.set_once people.unset people.increment people.append people.union people.track_charge people.clear_charges people.delete_user".split(" ");
for(h=0;h<k.length;h++)e(d,k[h]);a._i.push([b,c,f])};a.__SV=1.2;b=e.createElement("script");b.type="text/javascript";b.async=!0;b.src="undefined"!==typeof MIXPANEL_CUSTOM_LIB_URL?MIXPANEL_CUSTOM_LIB_URL:"file:"===e.location.protocol&&"//cdn4.mxpnl.com/libs/mixpanel-2-latest.min.js".match(/^\\/\\//)?"https://cdn4.mxpnl.com/libs/mixpanel-2-latest.min.js":"//cdn4.mxpnl.com/libs/mixpanel-2-latest.min.js";c=e.getElementsByTagName("script")[0];c.parentNode.insertBefore(b,c)}})(document,window.mixpanel||[]);
mixpanel.init("46042714e64a7536dde6f02af1aec923");</script><!-- end Mixpanel -->

上面是Mixpanel平臺的基礎代碼,不同平臺家的這段基礎代碼,大同小異,都是一段IIFE形式的、壓縮過的js代碼,執行完成之后,在head里面插入了一個新的script標簽,異步去下載真正的核心SDK代碼下來作業,所以并不是基礎代碼可以根據配置上報行為,而是基礎代碼會下載一段**“更大”**的SDK核心代碼,這段代碼才是SDK真正的功能實作,

這樣子做的好處是,基礎代碼很短,加載的時候不會影響到網頁的性能,而且核心SDK代碼的更新也不需要用戶去更新這段基礎代碼,

2. 頁面的唯一標識

在配置元素行為的時候,需要唯一標識一個頁面,這樣才能保證A頁面的配置,不會下發給在B頁面,不會導致B頁面產生出A頁面里配置的行為,在Web里面標識頁面靠的是url,url由protocol、domain、port、path和引陣列成,存盤配置的時候要將url的引數提出來再存,而url的引數位置是可以變化的,比如urlA(http://a.b.com/c.html?pa=1&pb=2)和urlB(http://a.b.com/c.html?pb=2&pa=1)雖然urlA !== urlB,但是其實它們是一個頁面,

3. 元素的唯一標識

唯一標識頁面后,接下來就要唯一標識頁面里面的元素,這樣才能保證A頁面中配置的元素A1可以被SDK找到,從而監聽它產生的事件,

在html里面,元素是以DOM Tree組織的,如果沿著元素A1出發,一直向上記錄它的parent和它在parent中的index,直到根節點body,那么就可以得到元素A1在DOM Tree中的唯一路徑,

html的元素還會擁有很多屬性,例如css class、id可以用來定位元素,通過Chrome開發者工具可以看到Mixpanel的可視化工具在配置元素的時候,使用的是https://github.com/Autarc/optimal-select這個庫來生成element的唯一標識的,而Github上還有https://github.com/rowthan/whats-element這樣的庫,也可以生成元素在DOM Tree中的唯一標識,

此外,還有平臺在標識元素的時候,采用了xpath,這也是一個思路,

4. 如何查找元素

上面說到元素可以有唯一標識,那么有了唯一標識,就可以利用它的原理,找到這個元素,有一個很好用的API是document.querySelector(),這個API可以根據CSS選擇器找到對應的元素,此外,根據元素的標識方法,還可以使用document.getElementById()document.getElementByName()來實作元素的查找,

這里需要重點強調的是,如果頁面在配置完成之后又發生了修改,導致DOM Tree發生變化,此時需要被監測的元素的唯一標識可能也會發生改變,很可能導致根據之前的配置無法找到該元素了,或者找到的并不是我們希望監測的元素,從而導致產生的事件數量發生比較明顯的變化,為了資料的穩定性和準確性,應該設有相應的監測告警處理這種case,并提示用戶去重新配置頁面,我個人認為這是無埋點最大的缺點,

5. 標記元素時的高亮效果和可視化互動實作

這是一個比較細節的點,其實熟悉js的大牛們都知道,有無數種方式去實作滑鼠移動到元素上時的類hover效果,點擊元素后彈出一個對話框,讓用戶輸入配置的資訊也so easy,但是我想說的是,一旦我們采用向頁面中動態添加元素的方式去實作可視化工具的互動界面,那么有可能會破壞掉頁面原來的DOM Tree結構,從而導致生成元素唯一標識的時候出現誤差,所以這里必須要好好處理,保證生成的元素標識不會受到影響,

我看到Mixpanel采用了CustomElementShadowDOM,把可視化工具所有的功能都用自定義的Web Component實作了,雖然目前只有Chrome支持Web Component,但是真的有點叼,,這樣自定義的元素和互動不會對用戶的網頁DOM產生影響,當然,如果你的可視化工具實作做的很輕,比如只是將用戶的網頁放在一個iframe里面,大部分互動都交給iframe的parent頁面去處理,那也可以在配置的時候,最小程度的破壞用戶的網頁了,

6. 配置工具中如何控制頁面的跳轉

當進入可視化配置狀態時,我們可以讓用戶點擊一個元素,然后彈一個對話框,讓用戶對這個元素進行配置,此時,如果這個元素本身的click行為是頁面跳轉呢?我們應該怎么處理?

這里本質上是一個互動設計的問題,在可視化配置工具中,應該有兩種基本互動操作,一種是讓用戶選中某一個元素,進行配置;另一種,是讓用戶可以觸發頁面原有的行為,

為什么要有第二種互動?因為我們的工具肯定要支持用戶進行二級頁面的可視化配置對不對?或者說,用戶的頁面中可能會彈出一個對話框,對話框里面有一個按鈕,用戶對監測這個按鈕,對它做配置,對不對?簡單來說,就是用戶頁面中原有的點擊行為,可能會導致頁面結構產生變化,例如跳轉,頁面內彈出對話框等等,

那問題就好解了,除了點擊,再設計一種互動來支持用戶網頁中原有的點擊行為不就好了,用“右鍵點擊”或者“按住shift+點擊”之類都可以,反正不要再和網頁默認的互動很容易產生沖突的方式就行,

最后再提一下,之前想很久沒有想明白,如何能夠能防止用戶點擊的時候頁面產生跳轉,后來才知道,DOM的事件流分三個階段:捕獲、目標、冒泡,所以為了避免用戶的點擊產身頁面跳轉,給document在捕獲階段加一個listener,攔截掉這個事件的繼續分發就行了,

簡單的示例代碼如下:

document.addEventListener('click', e => {
  // 如果是按住shift的點擊,那么保持原有的行為
  if (e.shiftKey) {
    return;
  }
  // 如果是單純的點擊,那么攔截分發
  e.preventDefault();
  e.stopImmediatePropagation();
  // 獲取元素的唯一標識,然后讓用戶進行配置等等
  this._selectElement(e.target);
}, true); // useCapture必須為true

四、總結

可以看到“無埋點”并不是零侵入,用戶的網頁中依然需要加載SDK的代碼(除非你是瀏覽器廠商,可以在加載網頁的時候,給網頁加inject基礎代碼),只是每一個行為事件的上報代碼不需要開發人員手動撰寫,而是由運營人員用可視化工具配置,所以叫它**“可視化埋點”**也許更加合適,我們知道資料采集是資料分析的基礎和先決條件,資料采集做不好,其他的東西都是空中樓閣,

這里可以小結一下“無埋點”技術的優劣,無埋點的好處是技術成本低,對用戶非常友好,不需要重新部署,配置完成就可以生效,但是其缺點也非常明顯,不具有代碼埋點的靈活性和深度,只能采集到用戶肉眼可見的資料,無法獲取記憶體里的資料,同時也無法適應頁面結構的變化,所以在實際生產中,要選擇性地在合適的地方使用無埋點技術,

多扯一點產品設計和技術方案的選擇,產品上是否可以支持采集記憶體資料呢?當然可以,比如微信小程式的“自定義分析”,就可以支持上報頁面data下面的屬性,這時雖然同樣是可視化配置,運營人員肯定不會知道代碼里面的變數名字,必須得有開發人員參與配置才行,關于頁面結構發生變化之后的資料丟失,也是有方案可以破的,比如Mixpanel平臺的Codeless Tracking,實際上采集了頁面中所有頁面的點擊事件上報,然后在后臺再去根據用戶的配置計算轉化數量,這樣做的好處就是如果頁面變化后,用戶接到告警,修改了配置,那么用于資料上報方案是全量的,所以平臺是由能力將過去的資料回溯出來的,而上面我們說的根據配置下發,查找監測指定元素,再上報資料的方案屬于按需上報,資料出現誤差是無法回溯的,不過全量上報資料大家也知道,太不友好了,這個資料量太大,不僅前端消耗資源多,如果為了做資料回溯,后臺的存盤壓力也會加大,而存盤的資料大部分還是無效的,這個成本有點高了,

五、參考資料

  • JS埋點技術分析
  • https://github.com/Autarc/optimal-select
  • https://github.com/rowthan/whats-element
  • https://www.zhihu.com/question/38000812
  • **本文作者:**unclechen
  • 本文鏈接: 2018/06/24/揭開JS無埋點技術的神秘面紗/
  • 著作權宣告: 本文采用知識共享 署名-非商業性使用-相同方式共享 4.0 國際 許可協議進行許可,轉載請注明出處!

轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/252145.html

標籤:其他

上一篇:一篇博文教會你學習CSS盒子模型(五)

下一篇:騰訊位置 - 關鍵詞輸入提示(結尾附視頻)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • vue移動端上拉加載

    可能做得過于簡單或者比較low,請各位大佬留情,一起探討技術 ......

    uj5u.com 2020-09-10 04:38:07 more
  • 優美網站首頁,頂部多層導航

    一個個人用的瀏覽器首頁,可以把一下常用的網站放在這里,平常打開會比較方便。 第一步,HTML代碼 <script src=https://www.cnblogs.com/szharf/p/"js/jquery-3.4.1.min.js"></script> <div id="navigate"> <ul> <li class="labels labels_1"> ......

    uj5u.com 2020-09-10 04:38:47 more
  • 頁面為要加<!DOCTYPE html>

    最近因為寫一個js函式,需要用到$(window).height(); 由于手寫demo的時候,過于自信,其實對前端方面的認識也不夠體系,用文本檔案直接敲出來的html代碼,第一行沒有加上<!DOCTYPE html> 導致了$(window).height();的結果直接是整個document的高 ......

    uj5u.com 2020-09-10 04:38:52 more
  • WordPress網站程式手動升級要做好資料備份

    WordPress博客網站程式在進行升級前,必須要做好網站資料的備份,這個問題良家佐言是遇見過的;在剛開始接觸WordPress博客程式的時候,因為升級問題和博客網站的修改的一些嘗試,良家佐言是吃盡了苦頭。因為購買的是西部數碼的空間和域名,每當佐言把自己的WordPress博客網站搞到一塌糊涂的時候 ......

    uj5u.com 2020-09-10 04:39:30 more
  • WordPress程式不能升級為5.4.2版本的原因

    WordPress是一款個人博客系統,受到英文博客愛好者和中文博客愛好者的追捧,并逐步演化成一款內容管理系統軟體;它是使用PHP語言和MySQL資料庫開發的,用戶可以在支持PHP和MySQL資料庫的服務器上使用自己的博客。每一次WordPress程式的更新,就會牽動無數WordPress愛好者的心, ......

    uj5u.com 2020-09-10 04:39:49 more
  • 使用CSS3的偽元素進行首字母下沉和首行改變樣式

    網頁中常見的一種效果,首字改變樣式或者首行改變樣式,效果如下圖。 代碼: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, ......

    uj5u.com 2020-09-10 04:40:09 more
  • 關于a標簽的講解

    什么是a標簽? <a> 標簽定義超鏈接,用于從一個頁面鏈接到另一個頁面。 <a> 元素最重要的屬性是 href 屬性,它指定鏈接的目標。 a標簽的語法格式:<a href=https://www.cnblogs.com/summerxbc/p/"指定要跳轉的目標界面的鏈接">需要展示給用戶看見的內容</a> a標簽 在所有瀏覽器中,鏈接的默認外觀如下: 未被訪問的鏈接帶 ......

    uj5u.com 2020-09-10 04:40:11 more
  • 前端輪播圖

    在需要輪播的頁面是引入swiper.min.js和swiper.min.css swiper.min.js地址: 鏈接:https://pan.baidu.com/s/15Uh516YHa4CV3X-RyjEIWw 提取碼:4aks swiper.min.css地址 鏈接:https://pan.b ......

    uj5u.com 2020-09-10 04:40:13 more
  • 如何設定html中的背景圖片(全屏顯示,且不拉伸)

    1 <style>2 body{background-image:url(https://uploadbeta.com/api/pictures/random/?key=BingEverydayWallpaperPicture); 3 background-size:cover;background ......

    uj5u.com 2020-09-10 04:40:16 more
  • Java學習——HTML詳解(上)

    HTML詳解 初識HTML Hyper Text Markup Language(超文本標記語言) 1 <!--DOCTYPE:告訴瀏覽器我們要使用什么規范--> 2 <!DOCTYPE html> 3 <html lang="en"> 4 <head> 5 <!--meta 描述性的標簽,描述一些 ......

    uj5u.com 2020-09-10 04:40:33 more
最新发布
  • 我的第一個NPM包:panghu-planebattle-esm(胖虎飛機大戰)使用說明

    好家伙,我的包終于開發完啦 歡迎使用胖虎的飛機大戰包!! 為你的主頁添加色彩 這是一個有趣的網頁小游戲包,使用canvas和js開發 使用ES6模塊化開發 效果圖如下: (覺得圖片太sb的可以自己改) 代碼已開源!! Git: https://gitee.com/tang-and-han-dynas ......

    uj5u.com 2023-04-20 07:59:23 more
  • 生產事故-走近科學之消失的JWT

    入職多年,面對生產環境,盡管都是小心翼翼,慎之又慎,還是難免捅出簍子。輕則滿頭大汗,面紅耳赤。重則系統停擺,損失資金。每一個生產事故的背后,都是寶貴的經驗和教訓,都是專案成員的血淚史。為了更好地防范和遏制今后的各類事故,特開此專題,長期更新和記錄大大小小的各類事故。有些是親身經歷,有些是經人耳傳口授 ......

    uj5u.com 2023-04-18 07:55:04 more
  • 記錄--Canvas實作打飛字游戲

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 打開游戲界面,看到一個畫面簡潔、卻又富有挑戰性的游戲。螢屏上,有一個白色的矩形框,里面不斷下落著各種單詞,而我需要迅速地輸入這些單詞。如果我輸入的單詞與螢屏上的單詞匹配,那么我就可以獲得得分;如果我輸入的單詞錯誤或者時間過長,那么我就會輸 ......

    uj5u.com 2023-04-04 08:35:30 more
  • 了解 HTTP 看這一篇就夠

    在學習網路之前,了解它的歷史能夠幫助我們明白為何它會發展為如今這個樣子,引發探究網路的興趣。下面的這張圖片就展示了“互聯網”誕生至今的發展歷程。 ......

    uj5u.com 2023-03-16 11:00:15 more
  • 藍牙-低功耗中心設備

    //11.開啟藍牙配接器 openBluetoothAdapter //21.開始搜索藍牙設備 startBluetoothDevicesDiscovery //31.開啟監聽搜索藍牙設備 onBluetoothDeviceFound //30.停止監聽搜索藍牙設備 offBluetoothDevi ......

    uj5u.com 2023-03-15 09:06:45 more
  • canvas畫板(滑鼠和觸摸)

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>canves</title> <style> #canvas { cursor:url(../images/pen.png),crosshair; } #canvasdiv{ bo ......

    uj5u.com 2023-02-15 08:56:31 more
  • 手機端H5 實作自定義拍照界面

    手機端 H5 實作自定義拍照界面也可以使用 MediaDevices API 和 <video> 標簽來實作,和在桌面端做法基本一致。 首先,使用 MediaDevices.getUserMedia() 方法獲取攝像頭媒體流,并將其傳遞給 <video> 標簽進行渲染。 接著,使用 HTML 的 < ......

    uj5u.com 2023-01-12 07:58:22 more
  • 記錄--短視頻滑動播放在 H5 下的實作

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 短視頻已經無數不在了,但是主體還是使用 app 來承載的。本文講述 H5 如何實作 app 的視頻滑動體驗。 無聲勝有聲,一圖頂百辯,且看下圖: 網址鏈接(需在微信或者手Q中瀏覽) 從上圖可以看到,我們主要實作的功能也是本文要講解的有: ......

    uj5u.com 2023-01-04 07:29:05 more
  • 一文讀懂 HTTP/1 HTTP/2 HTTP/3

    從 1989 年萬維網(www)誕生,HTTP(HyperText Transfer Protocol)經歷了眾多版本迭代,WebSocket 也在期間萌芽。1991 年 HTTP0.9 被發明。1996 年出現了 HTTP1.0。2015 年 HTTP2 正式發布。2020 年 HTTP3 或能正... ......

    uj5u.com 2022-12-24 06:56:02 more
  • 【HTML基礎篇002】HTML之form表單超詳解

    ??一、form表單是什么

    ??二、form表單的屬性

    ??三、input中的各種Type屬性值

    ??四、標簽 ......

    uj5u.com 2022-12-18 07:17:06 more