揭祕!一個高準確率的Flutter埋點框架如何設計
背景
使用者行為埋點是用來記錄使用者在操作時的一系列行為,也是業務做判斷的核心資料依據,如果缺失或者不準確將會給業務帶來不可恢復的損失。閒魚將業務程式碼從Native遷移到Flutter上過程中,發現原先Native體系上的埋點方案無法應用在Flutter體系之上。而如果我們只把業務功能遷移過來就上線,對業務是極其不負責任的。因此,經過不斷探索,我們沉澱了一套Flutter上的高準確率的使用者行為埋點方案。
使用者行為埋點定位
先來講講在我們這裡是如何定義使用者行為埋點的。在如下使用者時間軸上,使用者進入A頁面後,看到了按鈕X,然後點選了這個按鈕,隨即開啟了新的頁面B。
這個時間軸上有如下5個埋點事件發生:
進入A頁面。A頁面首幀渲染完畢,並獲得了焦點。
曝光坑位X。按鈕X處於手機螢幕內,且停留一段時間,讓使用者可見可觸控。
點選坑位X。使用者對按鈕X的內容很感興趣,於是點選了它。按鈕X響應點選,然後需要開啟一個新頁面。
離開A頁面。A頁面失去焦點。
進入B頁面。B頁面首幀渲染完畢,並獲得焦點。
在這裡,打埋點最重要的是時機,即在什麼時機下的事件中觸發什麼埋點,下面來看看閒魚在Flutter上的實現方案。
實現方案
進入/離開頁面
在Native原生開發中,Android端是監聽Activity的onResume和onPause事件來做為頁面的進入和離開事件,同理iOS端是監聽UIViewController的viewWillAppear和viewDidDisappear事件來做為頁面的進入和離開事件。同時整個頁面棧是由Android和iOS作業系統來維護。
在Flutter中,Android和iOS端分別是用FlutterActivity和FlutterViewController來做為容器承載Flutter的頁面,通過這個容器可以在一個Native的頁面內來進行Flutter頁面的切換,即Flutter自己維護了一個Flutter頁面的頁面棧。這樣,原來我們最熟悉的那套在Native原生上的方案在Flutter上無法直接運作起來。
針對這個問題,可能很多人會想到去註冊監聽Flutter的NavigatorObserver,這樣就知道Flutter頁面的進棧(push)和出棧(pop)事件。但是這會有兩個問題:
假設A、B兩個頁面先後進棧(A enter -> A leave -> B enter)。然後B頁面返回退出(B leave),此時A頁面重新可見,但是此時是收不到A頁面push(A enter)的事件。
假設在A頁面彈出一個Dialog或者BottomSheet,而這兩類也會走push操作,但實際上A頁面並未離開。
好在Flutter的頁面棧不像Android Native的頁面棧那麼複雜,所以針對第一個問題,我們可以維護一個和頁面棧匹配的索引列表。當收到A頁面的push事件時,往佇列裡塞入A的索引。當收到B頁面的push事件時,檢測列表內是否有頁面,如有,則對列表最後一個頁面執行離開頁面事件,再對B頁面執行進入頁面事件,接著往佇列裡塞B的索引。當收到B頁面的pop事件時,先對B頁面執行離開頁面事件記錄,再對佇列裡存在的最後一個索引對應的頁面(假設為A)進行判斷是否在棧頂(ModalRoute.of(context).isCurrent),如果是,則對A頁面執行進入頁面事件。
針對第二個問題,Route類內有個成員變數overlayEntries,可以獲取當前Route對應的所有圖層OverlayEntry,在OverlayEntry物件中有個成員變數opaque可以判斷當前這個圖層是否全屏覆蓋,從而可以排除Dialog和BottomSheet這種型別。再結合問題1,還需要在上述方案中加上對push進來的新頁面來做判斷是否為一個有效頁面。如果是有效頁面,才對索引列表中前一個頁面做離開頁面事件,且將有效頁面加到索引列表中。如果不是有效頁面,則不操作索引列表。
以上並不是閒魚的方案,只是筆者給出的一個建議。因為閒魚APP在一開始落地Flutter框架時,就沒有使用Flutter原生的頁面棧管理方案,而是採用了Native+Flutter混合開發的方案。具體可參考前面的一篇文章《已開源|碼上用它開始Flutter混合開發——FlutterBoost》。因此接下來也是基於此來闡述閒魚的方案。
閒魚的方案如下(以Android為例,iOS同理):
注:首次開啟指的是基於混合棧新開啟一個頁面,非首次開啟指的是通過回退頁面的方式,在後臺的頁面再次到前臺可見。
看到這個方案可能會有人問,為什麼這麼繞,為什麼不全部交給Native側去直接管理呢?交給Native側去直接管理這樣做針對非首次開啟這個場景是合適的,但是對首次開啟這個場景卻是不合適的。但是在首次開啟這個場景下,onResume時Flutter頁面尚未初始化,此時還不知道頁面資訊,因此也就不知道進入了什麼頁面,所以需要在Flutter頁面初始化(init)時再回過來調Native側的進入頁面埋點介面。而為了避免開發人員去關注是否為首次開啟Flutter頁面,因此我們統一在Flutter側來直接觸發進入/離開頁面事件。
曝光坑位
先講下曝光坑位在我們這裡的定義,我們認為圖片和文字是有曝光意義的,其他使用者看不見的是沒有曝光意義的,在此之上,當一個坑位同時滿足以下兩點時才會被認為是一次有效曝光:
坑位在螢幕可見區域中的面積大於等於坑位整體面積的一半。
坑位在螢幕可見區域中停留超過500ms。
基於此定義,我們可以很快得出如下圖所示的場景,在一個可以滾動的頁面上有A、B、C、D共4個坑位。其中:
坑位A已經滑出了螢幕可見區域,即invisible;
坑位B即將向上從螢幕中可見區域滑出,即visible->invisible;
坑位C還在螢幕中央可視區域內,即visible;
坑位D即將滑入螢幕中可見區域,invisible->visible;
那麼我們的問題就是如何算出坑位在螢幕內曝光面積的比例。要算出這個值,需要知道以下幾個數值:
容器相對螢幕的偏移量
坑位相對容器的偏移量
坑位的位置和寬高
容器的位置和寬高
其中坑位和容器的寬和高很容易獲取和計算,這裡就不再累述。
獲得容器相對螢幕的偏移量
//監聽容器滾動,得到容器的偏移量 double _scrollContainerOffset = scrollNotification.metrics.pixels;
獲得坑位相對螢幕的偏移量
//曝光坑位Widget的context final RenderObject childRenderObject = context.findRenderObject(); final RenderAbstractViewport viewport = RenderAbstractViewport.of(childRenderObject); if (viewport == null) { return; } if (!childRenderObject.attached) { return; } //曝光坑位在容器內的偏移量 final RevealedOffset offsetToRevealTop = viewport.getOffsetToReveal(childRenderObject, 0.0);
邏輯判斷
if (當前坑位是invisible && 曝光比例 >= 0.5) { 記錄當前坑位是visible狀態 記錄出現時間 } else if (當前坑位是visible && 曝光比例 < 0.5) { 記錄當前坑位是invisible狀態 if (當前時間-出現時間 > 500ms) { 呼叫曝光埋點介面 } }
點選坑位
點選坑位埋點沒什麼難點,很容易就可以想到下面的方案:
效果
經過多輪迭代和優化,目前線上Flutter頁面的埋點準確率已經達到100%,有力地支援了業務的分析和判斷。同時這套方案讓業務同學在做開發時,對於頁面進入/離開、曝光坑位可以做到無感知,即不用關心何時去觸發,做到了簡單易用和無侵入性。
未來
此外,針對頁面進入/離開這個場景,由於閒魚是基於Flutter Boost混合棧的方案,因此我們的解決方案還不夠通用。不過未來隨著閒魚上的Flutter頁面越來越多,我們後續也會去實現基於Flutter原生的方案。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69900359/viewspace-2647427/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 揭祕!如何用Flutter設計一個100%準確的埋點框架?Flutter框架
- 揭秘!如何用Flutter設計一個100%準確的埋點框架?Flutter框架
- 揭開JS無埋點技術的神祕面紗JS
- Flutter頁面曝光事件埋點框架Flutter事件框架
- 香港無創dna的準確率高嗎?
- 【LiteApp系列】埋點的設計APP
- 1. 揭祕Spring型別轉換 - 框架設計的基石Spring型別框架
- 揭祕如何辨別高仿包包
- 揭祕如何找高仿包包的貨源
- 揭祕如何搭建夢幻西遊社交框架框架
- 準確率(Accuracy) 精確率(Prescision) 召回率(Recall)
- 揭祕js框架中的常用套路JS框架
- 精確率、召回率、準確率與ROC曲線
- 自媒體人如何正確追熱點,三大祕訣,一個工具
- Dubbo框架的1個核心設計點框架
- 香港無創DNA95項準確率高嗎
- 如何設計一個流計算基準測試?
- 揭祕高階高仿包包批發
- 揭祕Flutter Hot Reload(基礎篇)Flutter
- 揭祕Flutter Hot Reload(原理篇)Flutter
- 揭祕淘寶高仿包包
- 揭祕高仿包包市場
- 如何設計一個高可用的運營系統
- 迄今最準確方法誕生!AI預測過早死亡風險,準確率高達76%AI
- 混淆矩陣、準確率、精確率/查準率、召回率/查全率、F1值、ROC曲線的AUC值矩陣
- 一個輕量級react埋點元件React元件
- 揭祕廣州賣高仿包的地址
- 埋點計算定位
- 揭祕高仿包包進貨渠道
- 揭祕女士高仿包包批發
- 揭祕精高仿包包批發
- 揭祕徐州高仿包包貨源
- 前端監控和前端埋點方案設計前端
- 準確率評價指標指標
- JJEvent 一個可靠的Android端資料埋點SDKAndroid
- 你的手機竊聽準確率可達 90%,這個安全漏洞如何堵?
- 如何設計一個高可用、高併發秒殺系統
- 如何從0到1設計一個類Dubbo的RPC框架RPC框架