原文地址:https://mp.weixin.qq.com/s?__biz=MTEwNTM0ODI0MQ==&mid=2653452704&idx=1&sn=96edccafae25d1ef6938035aae04a4d3
1、為什麼要做?先看下之前的埋點流程,如圖所示。產品提出埋點需求,開發人員在mp平臺配置埋點事件,然後進行程式碼埋點,再測試埋點,沒問題之後再提審。
小程式從 提審到稽核 透過大概需要 半天到兩天 的時間。透過之後還需要半天的線網驗證,線網有問題之後又得重新走一遍發版流程。整個埋點流程比較長。
有一次在比賽前一天晚上彩排的時候,產品臨時需要加個埋點需求,因為當時已經晚上10點多了,小程式沒人稽核,所以只能等到第二天早上找領導走內部緊急稽核通道,比較尷尬。
這個時候如果有一個 實時的埋點系統 就可以完美解決了。
細心的同學還會發現,整個埋點流程開發還是需要費神費力的,這種重複性的工作也是比較繁瑣的,而且對於技術能力的提升也沒有多少幫助。
所以埋點系統的另外一個要求就是
不需要開發介入 ,產品或者運營人員就可以單獨完成埋點。
2、怎麼做2.1、避免重複造輪子
在做之前,先了解下公司內外已有的埋點方案,避免重複造輪子。如圖所示,目前公司外有growingio和神策兩款產品,小程式官方也提供了埋點方案。
growingio是全埋點,資料全,但是由於是全埋點,後期還需要開發介入清理資料,不滿足埋點系統的要求;神策和MP需要程式碼埋點,不能實時生效。因此,現有的埋點方案都不能夠完全滿足我們的要求,需要獨立開發一個系統。2.2、埋點方案設計
框架圖如下,小程式的sdk分成兩種模式,埋點模式和採集模式,
埋點模式是產品操作的,供產品新增埋點事件。採集模式就是採集使用者的點選操作,在小程式啟動的時候,從後臺拉取產品需要的埋點事件,使用者點選動作命中埋點事件之後自動進行上報。在web端,產品可以檢視埋點資料
![](http://timg.juduo.cc/2020/12/5e6e77bf0a92415d877bc0b6fb16cb20.jpg)
這一篇闡述的是小程式SDK的實現,下面做具體介紹
3、埋點系統具體實現3.1 埋點整體流程
具體流程如圖所示,透過配置 確定是埋點模式還是採集模式
,假如是採集模式,需要獲取埋點事件,判斷是否有要統計的埋點事件。
尋找響應者唯一標識攔截互動事件其中比較難的一個點是尋找響應者,因為小程式是雙執行緒,檢視層和邏輯層是分開的,跟H5不太一樣,H5是可以獲取完整的dom節點資訊。但是在小程式中可以獲取到的資訊很少下面重點介紹下這幾個流程3.2 尋找響應者
1)業界方案介紹 業界方案主要有兩種,分別是工程化注入和冒泡採集。
工程化注入就是給所有標籤注入點選事件,這種相當於全埋點,資料比較全。但是缺點也很明顯,給所有標籤加上點選事件會讓專案顯得比較重,而且假如原來的標籤有點選事件,就更不好處理了。冒泡採集就是在wxml程式碼的最外層新增一個view,然後繫結catchtap事件。這種就比較輕量級,無需注入大量程式碼。但是依賴於冒泡事件,假如原來的業務程式碼阻止了冒泡,那就獲取不了,可靠性比較差。這兩種方案都是從檢視層出發,或多或少需要入侵業務程式碼,各有缺陷,不滿足我們的需求。
2)思路轉換 上面的方案是從檢視層出發,因為小程式的雙執行緒模型,這裡我從另外一個角度出發,從邏輯層下手。
3)具體實現目標分析:獲取使用者的 點選行為 ,從 wxml=>js ,也就是從渲染層轉向邏輯層。小程式的邏輯層涉及到兩個系統物件頁面物件自定義元件因此,只要重構這兩個系統物件即可,具體做法如下:在小程式啟動的時候, 重構Page()和Component()這兩個系統物件 ,遍歷物件裡面的所有屬性,如果屬性型別是函式,則進一步判斷是否在忽略名單,像監聽頁面滾動的函式這種是不需要新增hook的,最後才是給函式新增hook不過在小程式啟動的時候去給頁面的函式新增hook還不完整,因為有些函式是在執行時新增的,像這種該 怎麼新增hook呢 ?
給執行時的func新增hook這塊我想到了幾種方案給Page物件設定proxy,監控set方法在所有hook中監控Page屬性的數量Page新增生命週期函式,onLoad執行完之後給新生成的func新增hook第一種和第二種都存在多次觸發的情況,影響效能。只有第三種是一勞永逸的,只需要執行一次就可以了。
3.3 唯一標識
Target,觸發事件的源元件,currentTarget,事件繫結的當前元件。這種方案,唯一標識就是透過這 兩個id進行組合 得到
使用這種方案 可靠性比較差 ,因為在寫業務程式碼的時候,可能沒有給標籤新增id,這樣取到的id就是空字串,使得標識並不唯一
2)變數名+新特徵值
,防止其他頁面有相同的函式名。
這種方案的優勢很明顯,就是不依賴於id, 可靠性有保證 。
![](http://timg.juduo.cc/2020/12/90491a8e40ef4938bf8470f3b5632403.jpg)
不過細想一下,還是有一些情況需要考慮:
custom components如何獲取pagePath因為元件的層級比頁面層級低,從元件物件是沒法獲取頁面資訊的。但是由於是 視覺化埋點 ,所以元件所在的頁面肯定在頁面棧的最上面,因此,可以透過 頁面棧 獲取當前的 頁面物件 ,然後再獲取頁面路徑對於list點選事件,如何區分?如圖,每個tab的點選情況是需要區分統計的,而對於下面列表中的獎勵領取,一般是不需要區分的。不需要區分的按照原方案即可。對於需要區分統計的,因為tab不同時,所觸發的函式引數肯定也不同,所以 唯一標識需要帶上函式的引數。
如何統計一個事件在所有頁面的情況對於全域性範圍的統計,因為要統計所有頁面的情況,所以需要將頁面路徑和函式名稱分開存放,其中函式名作為埋點事件的唯一標識,頁面路徑作為子標識。
3.4 攔截互動事件
1)事件模型分析小程式的事件模型如下,使用者點選某個view時,會從外到內進行捕獲,事件冒泡的響應順序相反,是從內到外進行冒泡。可以看到,使用者點選一次可能會觸發多個事件,所以重點是要 防止多次上報統計事件
。
Hook的執行流程如下,首先會根據事件物件的事件戳和識別符號來判斷這個事件是否已經上報處理過,如果是就直接結束。
否則就記錄下這個事件已經處理過,防止後面重複處理。
3)採集模式流程採集模式是根據埋點事件進行資料上報。可以跟埋點模式一樣,
給所有func新增hook,在hook判斷是否要上報。這種方案有個弊端,因為埋點事件的數量遠比函式的數量要少,大多數函式是沒必要進行hook的,給全部函式加上hook會影響頁面的效能。根據埋點事件找到需要上報的func,只給這些func新增hook。很明顯,這種方案更佳,下面看看具體實現流程。小程式啟動的時候,同時進行兩件事。
給頁面新增一個生命週期函式initFuncHook從後臺拉取埋點事件當頁面開啟的時候,去執行initFuncHook生命週期函式,initFuncHook的流程如下:遍歷頁面的屬性,判斷屬性是否為fun型別,並且是需要埋點的,如果需要則新增hook,如果不需要就重新遍歷物件屬性,直到所有屬性都遍歷為止。至此,小程式視覺化實時埋點的整體思路就介紹完了。
原文地址:https://mp.weixin.qq.com/s?__biz=MTEwNTM0ODI0MQ==&mid=2653452704&idx=1&sn=96edccafae25d1ef6938035aae04a4d3