日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
揭秘!如何用Flutter設(shè)計一個100%準確的埋點框架?

用戶行為埋點是用來記錄用戶在操作時的一系列行為,也是業(yè)務(wù)做判斷的核心數(shù)據(jù)依據(jù),如果缺失或者不準確將會給業(yè)務(wù)帶來不可恢復(fù)的損失。閑魚將業(yè)務(wù)代碼從Native遷移到Flutter上過程中,發(fā)現(xiàn)原先Native體系上的埋點方案無法應(yīng)用在Flutter體系之上。而如果只把業(yè)務(wù)功能遷移過來就上線,是極其不負責(zé)任的。因此,經(jīng)過不斷探索,閑魚技術(shù)團隊沉淀了一套Flutter上的高準確率的用戶行為埋點方案,今天由工程師蘭昊來和大家分享一下。

成都創(chuàng)新互聯(lián)服務(wù)項目包括延吉網(wǎng)站建設(shè)、延吉網(wǎng)站制作、延吉網(wǎng)頁制作以及延吉網(wǎng)絡(luò)營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢、行業(yè)經(jīng)驗、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,延吉網(wǎng)站推廣取得了明顯的社會效益與經(jīng)濟效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到延吉省份的部分城市,未來相信會繼續(xù)擴大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!

用戶行為埋點定位

先來講講在我們這里是如何定義用戶行為埋點的。在如下用戶時間軸上,用戶進入A頁面后,看到了按鈕X,然后點擊了這個按鈕,隨即打開了新的頁面B。

這個時間軸上有如下5個埋點事件發(fā)生:

  • 進入A頁面。A頁面首幀渲染完畢,并獲得了焦點。
  • 曝光坑位X。按鈕X處于手機屏幕內(nèi),且停留一段時間,讓用戶可見可觸摸。
  • 點擊坑位X。用戶對按鈕X的內(nèi)容很感興趣,于是點擊了它。按鈕X響應(yīng)點擊,然后需要打開一個新頁面。
  • 離開A頁面。A頁面失去焦點。
  • 進入B頁面。B頁面首幀渲染完畢,并獲得焦點。

在這里,打埋點最重要的是時機,即在什么時機下的事件中觸發(fā)什么埋點,下面來看看閑魚在Flutter上的實現(xiàn)方案。

實現(xiàn)方案

進入/離開頁面

在Native原生開發(fā)中,Android端是監(jiān)聽Activity的onResume和onPause事件來做為頁面的進入和離開事件,同理iOS端是監(jiān)聽UIViewController的viewWillAppear和viewDidDisappear事件來做為頁面的進入和離開事件。同時整個頁面棧是由Android和iOS操作系統(tǒng)來維護。

在Flutter中,Android和iOS端分別是用FlutterActivity和FlutterViewController來做為容器承載Flutter的頁面,通過這個容器可以在一個Native的頁面內(nèi)來進行Flutter頁面的切換,即Flutter自己維護了一個Flutter頁面的頁面棧。這樣,原來我們最熟悉的那套在Native原生上的方案在Flutter上無法直接運作起來。

針對這個問題,可能很多人會想到去注冊監(jiān)聽Flutter的NavigatorObserver,這樣就知道Flutter頁面的進棧(push)和出棧(pop)事件。但是這會有兩個問題:

  • 假設(shè)A、B兩個頁面先后進棧(A enter -> A leave -> B enter)。然后B頁面返回退出(B leave),此時A頁面重新可見,但是此時是收不到A頁面push(A enter)的事件。
  • 假設(shè)在A頁面彈出一個Dialog或者BottomSheet,而這兩類也會走push操作,但實際上A頁面并未離開。

好在Flutter的頁面棧不像Android Native的頁面棧那么復(fù)雜,所以針對第一個問題,我們可以維護一個和頁面棧匹配的索引列表。當(dāng)收到A頁面的push事件時,往隊列里塞入A的索引。當(dāng)收到B頁面的push事件時,檢測列表內(nèi)是否有頁面,如有,則對列表最后一個頁面執(zhí)行離開頁面事件,再對B頁面執(zhí)行進入頁面事件,接著往隊列里塞B的索引。當(dāng)收到B頁面的pop事件時,先對B頁面執(zhí)行離開頁面事件記錄,再對隊列里存在的最后一個索引對應(yīng)的頁面(假設(shè)為A)進行判斷是否在棧頂(ModalRoute.of(context).isCurrent),如果是,則對A頁面執(zhí)行進入頁面事件。

針對第二個問題,Route類內(nèi)有個成員變量overlayEntries,可以獲取當(dāng)前Route對應(yīng)的所有圖層OverlayEntry,在OverlayEntry對象中有個成員變量opaque可以判斷當(dāng)前這個圖層是否全屏覆蓋,從而可以排除Dialog和BottomSheet這種類型。再結(jié)合問題1,還需要在上述方案中加上對push進來的新頁面來做判斷是否為一個有效頁面。如果是有效頁面,才對索引列表中前一個頁面做離開頁面事件,且將有效頁面加到索引列表中。如果不是有效頁面,則不操作索引列表。

以上并不是閑魚的方案,只是筆者給出的一個建議。因為閑魚APP在一開始落地Flutter框架時,就沒有使用Flutter原生的頁面棧管理方案,而是采用了Native+Flutter混合開發(fā)的方案,因此接下來也是基于此來闡述閑魚的方案。

閑魚的方案如下(以Android為例,iOS同理):

注:首次打開指的是基于混合棧新打開一個頁面,非首次打開指的是通過回退頁面的方式,在后臺的頁面再次到前臺可見。

看到這個方案可能會有人問,為什么這么繞,為什么不全部交給Native側(cè)去直接管理呢?交給Native側(cè)去直接管理這樣做針對非首次打開這個場景是合適的,但是對首次打開這個場景卻是不合適的。但是在首次打開這個場景下,onResume時Flutter頁面尚未初始化,此時還不知道頁面信息,因此也就不知道進入了什么頁面,所以需要在Flutter頁面初始化(init)時再回過來調(diào)Native側(cè)的進入頁面埋點接口。而為了避免開發(fā)人員去關(guān)注是否為首次打開Flutter頁面,因此我們統(tǒng)一在Flutter側(cè)來直接觸發(fā)進入/離開頁面事件。

曝光坑位

先講下曝光坑位在我們這里的定義,我們認為圖片和文本是有曝光意義的,其他用戶看不見的是沒有曝光意義的,在此之上,當(dāng)一個坑位同時滿足以下兩點時才會被認為是一次有效曝光:

  • 坑位在屏幕可見區(qū)域中的面積大于等于坑位整體面積的一半。
  • 坑位在屏幕可見區(qū)域中停留超過500ms。

基于此定義,我們可以很快得出如下圖所示的場景,在一個可以滾動的頁面上有A、B、C、D共4個坑位。其中:

  • 坑位A已經(jīng)滑出了屏幕可見區(qū)域,即invisible;
  • 坑位B即將向上從屏幕中可見區(qū)域滑出,即visible->invisible;
  • 坑位C還在屏幕中央可視區(qū)域內(nèi),即visible;
  • 坑位D即將滑入屏幕中可見區(qū)域,invisible->visible;

那么我們的問題就是如何算出坑位在屏幕內(nèi)曝光面積的比例。要算出這個值,需要知道以下幾個數(shù)值:

  • 容器相對屏幕的偏移量
  • 坑位相對容器的偏移量
  • 坑位的位置和寬高
  • 容器的位置和寬高

其中坑位和容器的寬和高很容易獲取和計算,這里就不再累述。

獲得容器相對屏幕的偏移量

 
 
 
 
  1. //監(jiān)聽容器滾動,得到容器的偏移量 
  2. double 
  3.  _scrollContainerOffset = scrollNotification.metrics.pixels; 

獲得坑位相對屏幕的偏移量

 
 
 
 
  1. //曝光坑位Widget的context 
  2. final 
  3.   
  4. RenderObject 
  5.  childRenderObject = context.findRenderObject(); 
  6. final 
  7.   
  8. RenderAbstractViewport 
  9.  viewport =  
  10. RenderAbstractViewport 
  11. .of(childRenderObject); 
  12. if 
  13.  (viewport ==  
  14. null 
  15. ) { 
  16.    
  17. return 
  18. if 
  19.  (!childRenderObject.attached) { 
  20.    
  21. return 
  22. //曝光坑位在容器內(nèi)的偏移量 
  23. final 
  24.   
  25. RevealedOffset 
  26.  offsetToRevealTop = viewport.getOffsetToReveal(childRenderObject,  
  27. 0.0 

邏輯判斷

 
 
 
 
  1. if 
  2.  (當(dāng)前坑位是invisible && 曝光比例 >= { 0.5) 
  3.  
  4. 記錄當(dāng)前坑位是visible狀態(tài) 
  5.  
  6. 記錄出現(xiàn)時間 
  7.  
  8. }  else if (當(dāng)前坑位是visible && 曝光比例 <  0.5 ) { 
  9.  
  10. 記錄當(dāng)前坑位是invisible狀態(tài) 
  11.  
  12. if (當(dāng)前時間-出現(xiàn)時間 >  { 500ms )
  13.  
  14.  
  15. 調(diào)用曝光埋點接口 
  16.  
  17.  

點擊坑位

點擊坑位埋點沒什么難點,很容易就可以想到下面的方案:

效果

經(jīng)過多輪迭代和優(yōu)化,目前線上Flutter頁面的埋點準確率已經(jīng)達到100%,有力地支持了業(yè)務(wù)的分析和判斷。同時這套方案讓業(yè)務(wù)同學(xué)在做開發(fā)時,對于頁面進入/離開、曝光坑位可以做到無感知,即不用關(guān)心何時去觸發(fā),做到了簡單易用和無侵入性。

未來

此外,針對頁面進入/離開這個場景,由于閑魚是基于Flutter Boost混合棧的方案,因此我們的解決方案還不夠通用。不過未來隨著閑魚上的Flutter頁面越來越多,我們后續(xù)也會去實現(xiàn)基于Flutter原生的方案。


分享名稱:揭秘!如何用Flutter設(shè)計一個100%準確的埋點框架?
網(wǎng)頁URL:http://www.dlmjj.cn/article/cosphij.html