背景說明
埋點需求是每個APP都需要做的一個功能,主要是為了統計分析數據。當然,也可以排查一些BUG,比如查看用戶的操作行為軌跡,復現BUG。當一個項目比較龐大時,埋點功能也會跟着變得非常龐大,需要開發人員熟悉具體頁面的業務邏輯,然后進行針對性的對組件的曝光進行計時,處理起來比較麻煩。本方案試圖使用一種自動的方式,讓埋點框架統一記錄所有被關注的組件的曝光數據,以減輕開發人員的工作。
為什么要做曝光?
在電商里,曝光的統計與分析是非常有必要的。比如:需要統計商品的曝光率,一件商品展示出來的(曝光)出來了,但用戶並沒有去點擊,這就可以統計出用戶的曝光點擊率,對后面的商品排序和展示優化分析是非常重要的。如果一個提醒按鈕展示爆光出來了,用戶沒有去點擊,可以分析到該功能的必要性。
方案說明
面對的主要問題
1. 曝光統計的代碼和業務緊密耦合在一起,每個新的業務場景都需要重新開發
2. 業務數據不規范,提取數據比較麻煩
如何解決
1. 采用通用的方式監測組件可見性,不依賴具體業務
2. 復用組件的點擊埋點數據,避免重復數據收集代碼
調研發現系統API無法提供view可見狀態的轉換通知,但可以檢查某個view是否在屏幕或者某個特定范圍內,從而可以判斷view的可見狀態。
我們只需要維護一個關注曝光的view集合,定期刷新隊列中每個view的曝光時長,就可以在離開頁面時獲取到曝光埋點所需要的數據。
整體流程
曝光監控驅動
1. 使用一個全局timer驅動,兼容性較好,可以支持所有的系統。
2. 如系統有幀刷新通知 ,注冊系統的幀刷新通知,如iOS的CADispayLink,省去全局timer。
曝光監控驅動對監控隊列中所有view的可見性檢查,當view的可見性發生變化時,更新view對應的上下文數據。
3. 考慮到性能問題,利用scroll事件進行驅動
曝光監控隊列的維護
1. view創建時,標記是否關注曝光。
2. 當標記關注的view所在頁面被展示時,自動加入監控隊列。
3. 當標記關注的view所在頁面被隱藏時,自動移出監控隊列。
4. 對於非資源類的曝光組件,因為不需要統計曝光時長,一旦確定曝光狀態就移出監控隊列。
曝光埋點發送
曝光事件觸發時,進行埋點發送,發送方式使用批量發送。每個曝光組件,攜帶的業務數據集是點擊數據集的子集,如果沒有定義點擊數據集的組件,使用common_set數據集。
方案存在的問題
1. iOS目前實現的可見性檢查,沒有判斷同一頁面上的view遮擋狀態,主要考慮實現代價比較大,另外不是曝光埋點的主要應用場景。
2. 持續的曝光監控,可能造成性能問題,需要實測影響。
性能測試結果
因為公用一個Timer作為引擎驅動整個曝光監控模塊,擔心對整體APP性能造成沖擊,主要是頻繁的Timer回調中進行可見性檢查對CPU的占用,因此分別在iOS和Android平台進行了針對性的性能測試。
測試設計如下:
以200ms為周期啟動一個Timer用於驅動曝光監控,創建100個view,加入監控隊列進行監控,統計曝光次數和曝光時長。
測試結果:
1. 假設view是資源組件,加入監控后一直不移除。在界面無其它交互狀態下,CPU占用率<0.5。
2. 假設view是公共組件,一旦判斷為曝光后可以移除監控。 在界面無其它交互狀態下,CPU占用率幾乎為0。
關鍵代碼
1、將系統的didMoveToWindow方法和vsas_didMoveToWindow進行交換
2、當view加載到window時,加入VSVisibleChecker隊列監聽
3、埋點發送,構成一個VSStatisticsRecord對象-->將該對象異步存入數據庫–>異步上傳埋點數據–>上傳成功,回調時,從數據庫移除該VSStatisticsRecord對象