破局傳統埋點四大痛點!攜程機票前端可視化埋點實踐
作者簡介
zy.jiang,攜程前端開發專家,關注新技術與效能提升,熱衷效率工具研發。
可視化埋點(Visual Event Tracking)作為一種廣泛應用的用戶行為數據采集方案,通過可視化界面配置頁面元素與數據采集事件的關聯關系,為傳統代碼埋點的痛點提供了有效解決方案。傳統埋點模式存在開發周期長、溝通成本高、代碼耦合嚴重、驗證困難等問題,而可視化埋點通過可視化圈選、低代碼采集等技術,可顯著降低技術門檻和維護成本,提升迭代效率。
基于上述背景,我們研發了河圖可視化埋點系統(以下簡稱河圖),旨在提升埋點流程的效能,并簡化埋點管理。河圖現已融入公司內部的伏羲埋點管理系統(以下簡稱伏羲),作為其子系統,專注于可視化埋點領域,而伏羲則是一個集埋點開發、數據分析與管理于一體的綜合系統。
本文首先系統對比兩種埋點方案的實現差異,深入剖析可視化埋點在敏捷迭代與跨團隊協作中的核心價值;其次,從架構設計與運行機制層面闡述可視化埋點如何系統性解決傳統埋點的弊端;最后,圍繞"從實現到可用"的主題,探討通過規范化管理與技術優化構建高可用性埋點體系的最佳實踐。
一、系統背景
埋點是一種非常重要的數據收集方式,主要用于收集用戶行為和系統運行狀況等數據。傳統的手工埋點(代碼埋點)流程圖如下:
從上述流程圖可以看出,傳統代碼埋點采用硬編碼方式與業務邏輯緊密耦合,這種實現方式主要帶來四方面問題:
1)周期長,迭代慢
- 每次變更需經歷完整發版流程
- 無法實時調整,需求響應延遲
2)成本高,效率低
- 需手動編寫埋點代碼,開發維護耗時
- 埋點字段需多方確認,增加溝通成本
3)易出錯,質量難控
- 缺乏自動校驗,存在參數類型錯誤風險
- 人工編碼可能導致關鍵字段遺漏
4)管理難,維護差
- 埋點分散各業務代碼,難以統一管理
- 版本迭代后易被遺忘,形成了技術債
既然傳統代碼埋點存在以上諸多缺點,那么我們是否可以將流程中的手動開發埋點代碼和手動測試埋點兩個環節(圖中開發與測試階段)從開發周期中剝離出來,轉變為通過可視化系統配置的方式實現,最終簡化成如下圖所示的流程:
可視化埋點通過"所見即所得"的配置模式,將埋點流程從代碼中剝離至平臺界面,可縮短上線周期并提升數據規范性。其核心優勢在于:配置人員無需接觸業務代碼即可完成埋點管理,大幅降低開發成本,減少代碼侵入性,同時實現規則實時生效,避免了包體積膨脹問題。接下來,我們將深入探討可視化埋點的運作原理、操作過程和可靠性提升機制。
二、系統概覽
河圖可視化埋點系統在整個埋點生態中的定位及與其他系統的關系如下:
伏羲為河圖提供了強大數據支持和可視化埋點管理分析等功能。
公共框架為河圖提供了埋點基礎數據,一些底層的埋點觸發事件以及UBT(User Behavior Tracking,用戶行為跟蹤系統)上報基礎API。
自動化測試平臺和前端公共發布運維系統(以下簡稱mPaas)在數據驗證與可靠性保障部分發揮了重要作用。
河圖系統由以下三大核心部分組成:
1)河圖SDK: 提供多端適配的SDK,盡管各端實現細節有所差異,但核心功能保持一致。
2)配置平臺: 具備配置與管理可視化埋點規則的功能界面,并集成質量檢查報告等輔助工具。
3)后臺服務: 承擔兩大職責,一是建立SDK與配置平臺間的通信橋梁,二是提供數據服務,支持對自定義埋點的深入分析等操作。
河圖系統分層如下:
上圖展示了河圖系統的分層架構,其核心組件是河圖SDK。以下是該SDK的主要特點:
1)簡單接入:基于公司成熟的UBT SDK擴展構建,客戶端只需接入河圖SDK即可獲得完整的埋點能力,包括規則管理、數據上報和埋點分布分析。
2)多端統一:雖然各端(Web/小程序/APP)底層實現不同,但提供完全一致的接口規范。一套配置即可實現多端數據采集標準化,大幅減少適配工作量。
3)代碼無侵入:業務代碼完全無需修改,開發過程無感知。SDK在編譯階段通過AST分析自動管理組件導入,開發者無需手動調整任何布局代碼。
三、系統介紹
我們將對河圖可視化埋點的原理以及配置平臺的使用做詳細介紹,它的總體流程包含以下幾個步驟:
系統配置平臺概覽圖如下:
上圖展示了埋點配置的完整工作流:從元素圈選、規則編寫到審批上線。接下來我們將深入探討埋點配置的技術實現原理,以及如何通過配置平臺落地這套埋點方案。
3.1 SDK模式介紹
SDK是可視化埋點的核心,負責實現元素的圈選、消息通信、規則適配、數據組裝以及數據上報等功能。它支持四種運行模式,分別是:
1)配置模式:支持對埋點位置和觸發條件進行規則配置,配置人員可以通過可視化界面靈活定義埋點規則。
2)驗收模式:在規則配置完成后,可對待驗收的埋點規則進行測試和驗證,確保埋點的準確性和有效性。
3)上報模式:在滿足規則條件時,SDK會自動組裝并上報埋點數據,確保數據采集的實時性和準確性。
4)熱力圖模式:用于查看頁面上埋點的熱力分布情況,點擊熱力圖可以查看具體埋點的詳細信息,幫助分析用戶行為。
由于篇幅限制,本文將重點介紹SDK如何接入以及四種模式中的配置模式和上報模式,這也是埋點從配置到生效的主要流程。
3.2 SDK原理及接入
可視化埋點SDK通過"編譯時預處理+運行時攔截"的兩個關鍵階段工作:在編譯階段進行組件預處理,使其具備埋點能力;在運行時當滿足埋點觸發條件時,SDK會按配置規則處理數據并自動上報。它由兩個核心功能部分構成:編譯插件和核心包。
3.2.1 編譯插件
編譯插件在構建階段發揮作用,主要完成兩項關鍵工作:
首先,它通過包導入替換機制,將項目中引用的原始UI組件庫(如React、React Native等)替換為對應的增強組件。這是一種非侵入式的組件增強方法,無需修改項目實際代碼,只需在構建流程中引入該插件即可。例如:
js // 編譯前,開發人員編寫的代碼:
import { Text, Button, TouchableOpacity, TouchableHighlight } from 'react-native'
// 運行時代碼與以下寫法等效:
import { Text, Button, TouchableOpacity, TouchableHighlight } from 'path/to/sdk/core'
用戶可以通過配置文件指定需要增強的組件類型,同時插件也會基于默認配置處理常用交互組件。
其次,插件會優化項目的渲染時UI結構,特別是針對條件渲染場景。當業務邏輯判斷某組件不需要渲染時,插件會在相應位置插入空占位組件,確保頁面結構的穩定性。這種結構占位優化對于基于路徑匹配的元素定位至關重要,能有效防止因條件渲染導致的節點索引不一致問題。實際測試表明,這種優化方案對頁面性能幾乎沒有影響,同時有助于提高埋點的可靠性。
3.2.2 核心包
核心包是SDK的核心功能模塊,為所有運行模式提供基礎能力。其工作原理主要體現在兩個關鍵環節:
首先,在配置模式下,核心包通過增強的UI組件攔截用戶交互,提供元素圈選、屬性提取和消息通信等功能。當用戶與界面元素交互時,SDK會捕獲當前節點及其父節點的完整屬性數據,并通過消息通道實時發送給配置平臺,由平臺進行可視化規則編輯,最終生成結構化的埋點配置規則。下一章節會詳細介紹配置模式下的具體實現。
其次,在非配置模式下(包括上報模式、驗收模式和熱力圖模式),核心包主要負責:
1)規則管理:頁面初始化時自動拉取配置規則并建立索引
2)觸發攔截:通過增強組件精確識別各類用戶交互時機
3)數據處理:根據預配置規則組裝、過濾目標數據
4)上報隊列:管理異步上報隊列,支持批量發送和失敗重試
5)可視化支持:提供埋點分布熱力圖展示,便于分析用戶行為熱點
3.3 配置埋點
在配置階段,為了實現端側圈選與配置平臺的實時交互,需要在端側與配置平臺之間建立實時通信機制。針對不同端側,我們提供了多種通信方案:
Web端:
可以通過iframe內嵌或瀏覽器插件的形式,實現頁面與配置平臺之間的消息通信。web頁面本身可以內嵌在配置平臺中,也可以通過瀏覽器插件的形式,實現頁面與配置平臺之間的消息通信。
App端或小程序端:
對于App端或小程序端,我們采用云手機或掃碼通信方案來實現配置平臺與端側的實時連接。接下來,我們將重點介紹掃碼方式的實現過程,詳細說明如何通過掃碼建立端側與配置平臺的通信,并完成埋點配置的實時交互。
在掃碼通信過程中,配置平臺會生成一個包含唯一連接串的二維碼。當已接入SDK的App掃描該二維碼時,會使用這個唯一的連接串與配置平臺建立實時通信。如下圖所示,三種顏色分別代表三個不同的連接串。連接串作為消息路由的標識,服務器會將消息定向發送給具有相同連接串的客戶端和配置平臺,確保多個并發配置會話之間互不干擾。在消息推送實現上,系統支持WebSocket和SSE(Server-Sent Events)兩種方案,為了有效降低網絡開銷,河圖系統默認使用SSE方案。
用戶的配置過程時序如下圖所示:
以上這個圖詳細展示了用戶配置埋點規則的時序。埋點配置的核心技術實現主要包含兩個關鍵部分:定義埋點位置和配置上報規則。接下來我們將深入探討這兩部分的技術原理,以及如何結合配置平臺實現高效的埋點管理。
3.3.1 埋點位置
可視化埋點位置,顧名思義,是指界面上一目了然的元素。它可以是具體的按鈕、輸入框、復選框等獨立組件,也可以是一組井然有序的元素,例如列表項、Tab 欄、下拉框,甚至是某個節點的第幾個子元素。
在配置元素時,首先需要對目標元素進行圈選。不同端采用不同的圈選實現方式:Web端通常在元素上層創建蒙層來突出顯示選中區域,而在App端則傾向于直接為圈選元素添加高亮邊框,這種方式實現相對簡單。
當開啟配置模式時,圈選元素后,元素上的屬性數據通過消息服務推送到配置平臺上,如下圖左側的埋點位置信息以及右側的屬性信息。
對于節點位置的配置,我們可以簡單歸納為三種方案:
1)固定標識方案:如果埋點位置帶有唯一標識(如 testID),我們可以直接使用該標識。例如,在編寫 UI 自動化用例時,如果已經為元素預設了唯一的testID,那么直接使用它即可。這種方案穩定性較高,但需要在頁面上統一添加標識,靈活性稍差。
2)相對路徑方案:當埋點位置沒有唯一標識時,可以使用節點路徑來描述位置。不過,這種方案的穩定性較差,因為頁面布局的變動可能導致路徑失效,影響準確性。
3)混合路徑方案:結合當前元素所在模塊的 id 以及元素相對于模塊的位置來描述。這種方案適合模塊內部位置的描述,兼具靈活性與穩定性。
在實際生產環境中,混合路徑的一個典型示例如下:
/RCTView[S_FLT_N_List_Flight_Label_Infor_Actual_Total]/RCTView[1]/RCTView[0]/RCTView[0]/RCTView[0]/VetTouchableOpacity[0]
其中,
RCTView[S_FLT_N_List_Flight_Label_Infor_Actual_Total]
是具有固定testID標識的父組件,而后面的
/RCTView[1]/RCTView[0]/RCTView[0]/RCTView[0]/VetTouchableOpacity[0]
則是目標元素相對于該固定標識父組件的相對路徑。這種混合路徑方式通過固定標識父組件作為錨點,結合相對路徑定位具體元素,使埋點配置在頁面結構發生局部變化時仍能保持穩定。
補充說明:對于列表型元素,系統支持正則表達式匹配,只需配置一次即可覆蓋所有動態生成的列表項,無需逐項設置。
下面,我們以三層結構示意說明位置描述(實際客戶端可能涉及幾十層關系)。
如上圖所示,樹狀結構的最右側葉子節點中,固定標識的路徑最短,穩定性也最好。
注意:不同技術棧的節點元素名稱可能不同。例如,Web 端有 div、span 等,而 RN 端則只有 view、touchableopacity 等組件名。在實際使用時,只需將圖中的 node 或 leaf 替換為對應組件名即可。
在配置時,根據埋點位置的圈選方式,我們可以分為當前元素與同類元素:
當前元素:僅描述當前位置的元素路徑,例如某個提交按鈕或輸入框。
同類元素:用于描述符合一定規則的一類元素,例如列表項、TAB、復選框等。如下圖所示的航班列表頁,每一項都有收藏點擊位置(黃色五角星)。在任意一個收藏按鈕上點擊后,位置信息可填寫為【第(\d+)條航班收藏入口】。運行時,SDK 會根據具體索引值匹配位置。
相對路徑生成:
基于頁面布局的元素樹狀結構,我們可以自定義一套相對路徑生成規則。需要注意的是,不同客戶端(如 iOS 和 Android)在生成相對路徑時需保證一致性。
生成元素相對路徑的實現方案有多種,例如 Web 頁面的 DOM 樹、React 的 Fiber 樹,以及 Native 端的虛擬樹等。我們可以根據元素在樹中的位置生成相對路徑。
以下以 React Native 頁面為例,說明相對路徑的生成過程:
根據 React Fiber 架構的原理,從當前 fiberNode 節點向上查找,并將經過的節點組合起來,形成路徑。
如上圖所示,當用戶點擊節點 LA 觸發埋點時,系統會順著 fiberNode 節點的 return 屬性向上查找父節點,并記錄這條鏈路上的所有節點信息,最終組合成相對路徑。經過大量實踐驗證,路徑長度達到 8 層時,已能在大多數場景下穩定描述元素的相對位置。因此,SDK 的默認配置將最大路徑層級設置為 8。
8層路徑示例如下:
/RCTScrollView[flightDetail_scrollView]/RCTView[0]/RCTView[0]/RCTView[0]/RCTView[0]/VetTouchableOpacity[1]
3.3.2 上報規則
上報規則定義了埋點數據的上報來源以及數據處理方式,包括篩選、組合、字段名稱映射、取值路徑設置等操作。數據來源可分為以下三種:
1)當前位置: 所需上報的數據已掛載在當前觸發埋點的元素及其父級節點上,直接從中提取即可。
2)關聯位置: 當所需數據無法從當前觸發元素及其父級節點獲取時,可通過規則配置關聯其他節點。例如,在列表頁項(綠框)被點擊時,可關聯獲取出發城市和到達城市名稱(紅框)一并上報。
3)全局上下文數據:即SDK運行時的上下文數據,通常在App渲染后的某個生命周期中進行組裝,供埋點上報時使用。
通過合理配置上報規則,確保埋點數據的準確性和完整性。
組裝規則:
在上報過程中,原始數據需要經過一系列處理步驟,包括篩選、組合、字段名稱映射以及取值路徑設置,最終生成可上報的數據。用戶可以通過拖放操作建立取值路徑的映射關系。只有建立了映射關系的數據才會被上報,其他無關字段在運行時會被SDK自動過濾舍棄,從而確保上報數據的精準性和簡潔性。
3.4 上報埋點
在埋點上報模式下,當當前元素命中上一節配置的規則后,便會觸發埋點上報。下面以最常見的點擊和曝光埋點為例,介紹可視化上報的具體流程。
以"點擊"埋點為例:
1)拉取配置: 從服務端獲取埋點配置規則。
2)用戶點擊: 用戶觸發頁面元素的點擊事件。
3)配置規則: 根據預配置的規則,確定需要上報的數據內容。
4)獲取基礎數據: 從當前元素或其關聯位置提取所需的基礎數據。
5)組裝上報數據: 對基礎數據進行篩選、組合、轉換、字段映射等處理,生成最終上報數據。
6)加入上報隊列: 將組裝好的數據加入上報隊列,等待發送。
7)ubt SDK上報: 通過UBT SDK將數據上報至服務器。
通過以下最簡示例,說明SDK是如何從組件數據中篩選并組裝最終的上報數據:
// 字段映射規則說明:
// 參數名稱: 取值路徑
payWay: child.props.nqhGuideTipsData.payWay // 支付方式字段
title: child.props.nqhGuideTipsData.title // 立減方案字段
// 運行時觸發埋點的組件實際數據結構
{
props: {
testID: "第**航班",
nqhGuideTipsData: {
payWay: "分期",
title: "立減10元",
// ...其它字段(不會被埋點采集)
},
// ...其它字段(不會被埋點采集)
}
}
在這個示例中:
1)payWay
和title
是我們配置的埋點參數名稱
2)child.props.nqhGuideTipsData.payWay
和child.props.nqhGuideTipsData.title是對應的取值路徑
3)當埋點觸發時,SDK會根據配置的取值路徑從組件數據中提取對應的值
4)最終只有配置的這兩個字段會被采集上報,組件上的其他數據會被自動過濾
最終上報的數據格式如下:
{
payWay: "分期",
title: "立減10元"
}
以上示例展示了點擊事件觸發時的數據處理流程。事實上,可視化埋點支持多種類型的事件采集,這些埋點的主要區別在于觸發時機不同,例如頁面進入、離開、元素輸入、失焦、曝光等。盡管數據組裝的流程略有差異,但整體思路相似。比如曝光埋點,Web端可以使用IntersectionObserver和MutationObserver;在React Native端則可以使用measure和measureInWindow等接口來檢測元素位置。業界也有多種實現方案可供參考,例如通過Native底層監控所有變化的元素,生成一棵虛擬樹,并通過對比新舊樹的變化來識別曝光開始或結束的元素。網易曙光埋點系統就采用了類似的虛擬樹對比方案。
攜程內部Native框架團隊已在底層對點擊與曝光等埋點做了大量基礎建設,提供了觸發時機識別和基礎數據組裝等能力。河圖SDK基于這些Native框架能力,通過偵聽曝光時機,利用框架底層UBT接口上報可視化埋點相關數據。
四、從實現到可用
通過前文的闡述,相信讀者已對可視化埋點的核心流程建立了系統理解。在實際落地過程中,我們積累了許多最佳實踐,從數據獲取擴展、上報穩定性保障、版本迭代維護,到條件渲染優化等多個方面,不斷提升系統的可用性。下面我們將重點介紹其中幾個關鍵實踐:
4.1 數據獲取擴展
在系統設計初期,可視化埋點僅支持從當前觸發節點及其相關屬性中獲取數據。然而,在實際應用中我們發現這種單一的數據獲取方式存在局限性:某些需要上報的數據可能并未在UI上呈現,或者分散在其他節點上。為了解決這個問題,我們對系統進行了兩個方面的擴展:
1)多元素組合上報:支持從頁面上其他非父子關系的元素上獲取數據,將多個元素的數據組合形成一條完整的埋點記錄。
2)全局上下文數據:在頁面級別維護統一的埋點上下文數據,所有埋點配置都可以訪問這些上下文數據并按規則篩選組裝,特別適合處理那些UI上不可見但業務上需要的數據。
這兩項擴展使系統能夠更好地滿足復雜業務場景的需求。
4.2 上報穩定性保障
針對配置拉取與匹配的強依賴特性,我們通過以下機制確保數據上報的穩定性:
1)異步隊列與重試機制:當未成功拉取配置時,埋點行為會進入緩存隊列等待,待網絡恢復或配置拉取成功后按規則匹配上報。結合優化的接口重試機制(如指數退避策略),數據上報準確率可達代碼埋點級別。
2)分批上報策略:為防止Native事件通道阻塞導致應用卡頓,系統會監控埋點數據量。當單次需要上報的埋點數據量過高時(如大量列表元素同時曝光),會采用200毫秒間隔的分批上報策略,確保應用性能的同時不丟失埋點數據。這個時間閾值可根據不同場景動態調整,實現性能與數據完整性的平衡。
3)跨頁防丟失:針對頁面快速切換導致的PageID漂移問題,通過頁面生命周期監聽與元素曝光狀態雙向校驗,實現跨頁埋點數據的精確關聯。
4.3 版本迭代維護
為應對UI改版導致的布局變化,我們構建了覆蓋全流程的防控體系:
1)版本灰度管控:配置規則與客戶端版本強綁定,支持按版本號范圍生效,避免新舊版本布局差異引發的規則失效。
2)發布卡口攔截:與自動化測試平臺深度集成,在發版流程中,通過公司的mPaas平臺自動檢測埋點配置健康度(如元素匹配率、曝光覆蓋率),若命中率低于預設閾值則阻斷發布并告警。
3)數據健康監測:定期輸出埋點質檢報告,包含配置規則命中詳情、失效原因分析及修復建議,驅動數據治理閉環。
4.4 條件渲染優化
在實際開發中,某些組件的條件渲染邏輯(如三元運算符)可能會導致頁面元素結構隨數據變化而改變,進而影響元素的相對位置描述。例如,當條件渲染的分支不同時,頁面結構可能發生顯著變化,導致埋點配置失效或數據不準確。
為避免類似上述問題,我們在編譯階段通過抽象語法樹(AST)分析,對動態渲染的元素進行占位改造。具體來說,可以在條件渲染的分支中插入占位節點,確保頁面結構在不同數據場景下保持穩定。這種方式不僅能夠提升埋點配置的魯棒性,還能減少因頁面結構變化導致的埋點失效問題。
五、結語
綜上所述,可視化埋點通過無代碼侵入、實時動態生效和開發解耦等特性,顯著提升了埋點效率。借助伏羲埋點系統的標準化輸出和配置平臺約束,確保了數據格式統一和字段完整性,同時降低了技術門檻,使非技術人員也能參與埋點配置。
然而,可視化埋點也存在一定局限性:復雜交互場景難以完全覆蓋、非UI綁定數據獲取受限、動態渲染結構變化帶來穩定性挑戰。因此,它并非替代其他埋點方式的全能解決方案,而是一種重要補充。在實際應用中,應結合多種埋點策略,取長補短,以滿足復雜業務場景的數據需求,提升采集準確性和全面性。