1. 程式人生 > >日誌採集與使用者行為鏈路跟蹤

日誌採集與使用者行為鏈路跟蹤

日誌採集這部分內容,其實在上一篇文章 阿里巴巴大資料實踐-讀書筆記 裡面多多少少已經提到了一些。不過正如前文提到的,這部分內容,從技術的角度來說,未必有多麼高深,但是從業務角度來說,要做到完善卻也很難,特別是在分析使用者行為鏈路的場景下,所以這篇專門來討論一下這一塊的內容。

所謂使用者行為,就是使用者在你的網站或者APP上所做的動作,比如:搜尋內容,瀏覽頁面,觀看視訊,購買商品,收藏,評論等等。

那為什麼要採集和記錄使用者的行為呢?吃飽了沒事幹,窺探使用者的隱私麼?


當然不是,說好聽點,是為了提高產品服務質量,提供個性化服務,說直接點呢,本質上還是為了更好的賺錢唄。在流量換金錢的網際網路商業模式下,尤其是下半場階段,流量的價值,無庸置疑,來之不易的流量,當然需要珍惜了。所以搞清楚你的使用者在自己的網站/APP上到底都做了什麼,想要做什麼,可以被"拐騙"去做些什麼,也就至關重要了:)

要搞清楚這些,當然要有資料,所以,你需要採集和分析使用者的行為,而行為日誌,無疑是最主要的資料來源。

記個日誌有什麼難的?

要想把使用者行為分析得徹底,那就需要全方位的採集資料,“全方位”這幾個字,實際上就是在類似我司這種業務鏈路複雜的電商環境下的系統中,日誌採集最大的難點所在了。

全方位,意味著不能遺漏。這實際上又包括了幾層涵義:

首先,頁面全覆蓋。類似我司這類業務場景的系統,使用者互動介面繁多,使用者互動的行為也是多種多樣。商品搜尋,圖牆瀏覽,資訊分享,收藏,加購,下單,支付,評論。。。而這些行為的載體也是多種多樣,PC端,移動端;H5,native;IOS,安卓;應用內開啟,微信小程式內開啟等等。

每個業務,每種載體,每個渠道,可能都是由不同的開發同學負責的,那麼如何做到全覆蓋呢?完全靠每個開發同學自己埋點,顯然不太現實。時間和工作量不是最大的問題,要保證資料的統一和不遺漏才是最大的麻煩所在。

其次,是流程上的全覆蓋。使用者的行為是有前後關聯關係的,獨立的使用者行為的採集統計固然重要,比如PV/UV這種用來騙取投資的使用者流量類資料。與此同時,完整的使用者行為鏈路的分析也是必不可少的,比如購買決策鏈路,會場活動效果分析,廣告流量來源去向統計等等。

這時候,往往就需要在行為日誌的採集過程中,附加必要的關聯資訊來實現行為的串聯。

你可能會想,那就讓所有的業務用統一的框架介面來採集日誌,需要什麼用於關聯業務的資訊,自己記錄不就好了唄,聽起來也沒多難。

確實如此,事實上,各種各樣的流量入口平臺,第三方網站/應用統計服務提供商等也都提供了類似js指令碼,日誌服務介面,日誌採集SDK等手段來標準化這件事。比如Goggle analytic,百度統計,Talking Data,Growing IO等等。從這個角度來看,這種方案本身,還是比較標準的,你自己開發起來,模式也不會偏離太多。

但是,大方向沒問題,不代表實現起來也很容易。要做到前面所說的全覆蓋的能力,JS也好,SDK也好,就得做到儘可能的降低對業務程式碼的侵入,特別是基礎的頁面瀏覽類日誌,最好能做到無需業務方主動呼叫相關程式碼邏輯。因為但凡需要業務方主動配合,開發程式碼才能完成的日誌採集方案,就有可能因為各種原因,遺漏(忽視)開發這部分程式碼,造成統計的遺漏。

而業務流程的串聯,也不僅僅是附加關聯資訊那麼簡單。舉個例子,比如想要做頁面來源跟蹤,有很多種方案,比如植入Cookie,然後在具體頁面採集cookie資訊判斷初始來源,比如在入口或落地頁面生成一個唯一標識ID,然後將這個ID作為引數向後傳遞等等。這些方案,在某些場景下也的確是可行的,但是一旦遇到多條業務鏈路可能有交叉,或者鏈路邏輯變化頻繁的情況,這些方案的邏輯就有可能隨時被打破了。

因此,通用,可靠,維護代價低,這三者在日誌採集的方案設計中,通常是最重要的考量因素。當然,實際情況下,在一些業務場景中,這三者可能很難同時做到,也就不排除某些鏈路需要定製化處理的可能性。

此外,還有很多問題,這裡先不單獨提出來討論了,在下面介紹我司的一些實踐和方案的過程中一併闡述。

我司的使用者行為日誌採集方案

整體流程

我司日誌採集的整體流程也很標準:頁面瀏覽類日誌,在Web端使用js採集頁面資訊,然後向日志伺服器特定URL發起一次http請求,將採集到的資料作為引數傳遞過去。日誌伺服器響應請求,記錄資訊,落盤。服務端日誌採集Agent收集日誌,再彙總傳送給下游鏈路,比如Kafka訊息佇列之類。

為了減少對業務程式碼的侵入和保障頁面的全覆蓋,js指令碼是在伺服器後端通過模版嵌入到每一個頁面的。

而使用者點選互動類日誌,還是需要業務方自行處理業務邏輯,然後呼叫標準介面傳送給日誌伺服器。

APP端則通過SDK提供介面給業務方,封裝底層元件的差異和日誌Log方式的具體實現,降低開發難度

日誌埋點的管理

不論是瀏覽類日誌還是點選互動類日誌,都會打上特定的事件ID進行標識,便於後續統計,細節後面再說。

這些ID標識,瀏覽類的,大多都是按規則自動生成的,也有重點頁面是通過註冊預先指定的(比如商品詳情頁什麼的)。而點選互動類日誌的事件ID,則都是通過後臺,統一註冊登記管理,生成唯一ID後,再由業務開發方通過SDK記錄下來的。

在Web端,埋點的實施是即時生效的,伺服器端程式碼修改以後,在客戶端瀏覽器裡下一次載入頁面時就能生效(當然,如果你有CDN靜態資源快取的機制,還要考慮如何淘汰舊的快取資源)。

而在APP端,往往需要通過版本釋出的流程才能更新程式碼,所以埋點的實施,需要提前規劃,也無法動態更新。這時候就有人提出動態埋點的技術了,多數情況下,絕大多數所謂的動態埋點技術,也就是先全部無差別的把所有可能的埋點位置先埋上程式碼,先不啟用,需要的時候再帶開開關。

我司在APP端目前也還沒有做到動態無痕埋點,所以互動類日誌埋點的全覆蓋,還是依靠業務上線前預先規劃統計需求,制定埋點方案,註冊管理,測試驗證這樣的流程來保證的。在業務快速變化的過程中,這麼瑣碎的事務,光靠人工來保證也是比較困難的。為此,我司也針對性的開發了專門的管理後臺來串聯相關工作流程。

PV UV和獨立互動類事件統計

PV UV 類的獨立頁面統計分析,理論上來說,通過頁面訪問記錄,獲取URL進行正則匹配來做也是可以的。但是這樣做也會存在很多問題,比如正則匹配的計算效率比較低,大量頁面的情況下URL正則匹配的規則難以管理,規則之間互相之間會不會重疊?一些動態生成的頁面,URL甚至可能無法通過正則匹配進行合理的歸類,新業務的頁面URL如何保證不和原有業務的匹配規則不衝突等等。總之,通過URL進行正則匹配,雖然可行,但是維護代價極高。

所以,更好的方式是給各個頁面賦予一個唯一的ID,當然考慮到統計的需要通常是按一類頁面進行統計,所以這個唯一ID一般也是賦予同一類頁面,而不是每一個具體的頁面例項的。(比如搜尋圖牆,每次使用者搜尋生成的資料都是不一樣的,當然沒辦法也沒有必要給每個搜尋結果頁面一個唯一的ID標識)

而使用者點選互動類的日誌,也是如此了,互動事件當然可以有可描述的文字,但是從統計的角度來說,還是賦予每個事件一個唯一ID比較靠譜一點。

有了ID,在後續統計中,對各個ID,進行分組聚合就好了。

使用者瀏覽行為鏈路跟蹤方案


相比通過獨立的單條日誌就能完成的簡單彙總類統計來說,使用者瀏覽行為的鏈路跟蹤,就麻煩很多了。比如想要知道使用者是如何到達一個特定的商品頁面的,是通過首頁的廣告位,還是通過會場活動,抑或是首頁/圖牆/商鋪/詳情這樣的瀏覽鏈路過來的,這就需要串聯多條日誌才能完成相關的分析工作。

舉一個實際的場景例子,作為電商類平臺,往往需要跟蹤一個訂單的下單鏈路,也就是所謂的訂單來源分析,做什麼用呢?用途也很多,和錢掛鉤的,比如要統計CPS廣告推廣的費用啊。

這種業務場景,透過URL匹配或者單純的頁面ID來做就會比較棘手,因為使用者的瀏覽行為可能是反覆隨機跳轉的,可能存在重複的瀏覽行為路徑。如何鑑別他是通過哪條路徑過來的呢? 對日誌做一下時間排序可能是一種解決方案,但是日誌如果存在亂序到達,或者丟失的情況,如何能夠發現呢。總之,做也是可以,但是代價和可靠性都會是比較大的問題。

當然,也並不是所有的鏈路分析場景都需要進行多跳分析,傳統的頁面轉換率分析這種群體行為的聚合統計類分析,只涉及到一次頁面跳轉的來源去向兩個頁面,與具體跳轉鏈路無關,還是容易處理的。

對於類似訂單來源這種多次跳轉類行為的精確分析,很容易想到的一種方式就是在作為可能來源的入口頁面,埋下一個唯一標識,然後一路透傳到最後的訂單頁面為止,這樣事後統計分析時,省去頁面跟蹤的過程,直接獲取這個標識就好了。

理論上,這也是可行的,關鍵是怎麼透傳這個引數?比如通過cookie記錄,或者生成一個唯一的TraceID,然後一路通過URL傳參往下游傳送。對於cookie來說,一方面種cookie的代價比較高,另一方面個數也是有限的。而對於URL傳遞TraceID引數這種方式來說,意味著業務鏈路上的所有頁面都要特殊處理這個引數,繼續往下游傳遞,一來代價更高,二來使用者的瀏覽行為很隨意,三來業務的流程也隨時可能變更,因此這種方案的維護代價和可靠性也是堪憂的,而且如果需要跟蹤的業務流程型別越來越多,這種ID和Cookie的方式也是無法擴充套件的。

所以,個別業務鏈路這麼處理可能可以,作為通用的解決方案還是不行的。

那麼怎麼做呢? 我司當前的方案是仿照阿里的SPM編碼方案。 這個方案,阿里對外的文章都是語焉不詳的,我估計稍微有點敏感,畢竟需要考慮刷流量作弊等問題,不宜過多宣傳,原理介紹得太多,不是要被人鑽空子麼 ;)不過其實有心人真想分析一下也是不難的。所以大概說一下我覺得也沒有什麼大不了的。當然,還是不要以我司為例了,以阿里的SPM方案為例吧:

SPM編碼是用來跟蹤頁面模組位置的編碼,早期的spm編碼由4段組成,採用a.b.c.d的格式,後來添加了e欄位,所以總共5個欄位組成,你可以在阿里系幾乎所有的業務頁面中看到spm引數,具體怎麼用這幾個欄位其實還是根據不同的業務場景來劃分的,並不完全一樣。不過,對於多數的業務場景來說,大致相同,比如,以下面這個在淘寶首頁點選中間Banner廣告的行為為例


在點選廣告開啟的頁面的URL上,你會看到 spm=a21bo.50862.201862-1.d1.5dcec6f7XFdlFJ 這樣的內容,其中:

  • a欄位代表的是站點或者你可以認為是一個大的業務,這裡a21bo應該就是淘寶了(相對天貓這種業務而言,具體a欄位的值,有時候也會變,這個看淘寶的心情了吧)

  • b欄位代表了這個業務下的頁面ID,比如這裡的50862就是淘寶首頁了

  • c欄位代表了具體的一個連結在頁面中的模組,你就理解為是為了再拆分頁面的層次結構就好了,這裡的201862-1,201862指的是首頁正中的Banner廣告位模組,-1是為了進一步定位這是這種輪播位置的第一個坑位。

  • d欄位代表的是點選的連結在模組內部的索引位置,這裡d1就是第一個位置了(Banner位特殊,只有一個位置)

  • e欄位是一個按特定規則生成的UniqueID,比如這裡的5dcec6f7XFdlFJ,用來區分不同的Session或者點選的,具體實現也和業務有關,你可以理解為為了區分同一個連結在不同的瀏覽鏈路例項中的點選之用。區分這個有什麼用呢?理論上可以有太多用途了,比如反作弊等等,有些敏感,不便細談 ;)

到這裡,可以看到SPM就是一個分層級的定位體系,這麼做的好處很多,比如根據不同的統計粒度需求,可以摘取特定欄位進行彙總,彙總的規則也非常標準,與具體業務幾乎無關。

比如需要按頁面型別統計PV,那麼取a.b兩個欄位分組聚合就可以了。如果要統計具體頁面模組的流量,那麼統計到a.b.c欄位就好了。要精確定位某一個推薦欄位的效果,就需要用到a.b.c.d四個欄位。這裡只是舉例,實際一些業務如何規劃這幾個欄位的層級,也不完全是絕對對映這種關係的,重要的是理解這種分層的目的和收益。

所以,分級定位的方式簡化了普通聚合彙總類分析的難度,但是SPM和使用者的瀏覽行為鏈路又有什麼關係呢?

前面看到,SPM引數唯一標識了特定站點頁面模組內部的一個連結,這個引數實際上是在使用者點選該連結的時候,自動生成並附加在目標連結的URL地址上的,所以在一個頁面的URL上的SPM引數,實際上表示的不是這個頁面的SPM引數,而是這個頁面的點選來源的SPM引數,也就是上一個頁面中開啟當前頁面所用到的連結的位置引數。所以URL中SPM的abcde五個欄位都是上個頁面的資訊。

至於當前頁面的SPM資訊,你還沒有點選連結呢,cd這兩個和具體點選位置相關的欄位自然是沒有的,但是ab這兩個和頁面繫結的欄位是存在的,e這個session判斷標識也是可以提前確定的。

所以,在頁面開啟以後Log的日誌裡面,我們可以記下URL中連結來源SPM的5個欄位,以及當前頁面SPM的abe三個欄位。這樣通過abe三個欄位在頁面之間就可以形成一個連結串列關係,通過追蹤這個連結串列我們就可以還原使用者的瀏覽行為鏈路了。 如果要具體統計模組位置的流量,再把來源頁面的cd欄位補上就好了。

這個邏輯是不是有點繞? 的確如此,所以此前在開發過程中,每次和我司的各種客戶端開發同學討論這個方案的時候,都要費不少的口舌。

不過這大概也算是鏈路跟蹤裡相對靠譜的方案了,這個方案,阿里系的網站已經沿用和發展了十幾年了,模仿這個方案的還有比如美團的MTT引數。當然也有更多的大公司沒有采用這種方案,不知道是沒有在意過這種方案呢,還是有其它解決手段,抑或只是依靠URL來解決問題。

我猜可能兼而有之,畢竟這套方案實施起來要全站貫穿,全端實現,如果有歷史包袱的話,代價確實也是很高的。而URL匹配的方案,雖然計算效率差一些,存在這樣那樣的維護問題,但是如果不是特別注重個體鏈路的精確分析的話,輔助以其它手段,絕大多數的業務場景,也還是能找到一些解決辦法的,不是完全無解。

SPM的原理很簡單,就是用格式化的欄位分層定位唄,那麼SPM方案的難點在哪裡呢?

難點還是在於這幾個欄位具體值的規範化,如何儘可能減少對業務方程式碼邏輯的侵入。引數已經細化到每一個連結,自然不可能手動維護每個欄位的值,這就需要儘可能自動化的生成這些引數,而對於特定的頁面或者模組還要保留自定義的能力,以備特殊用途之用。

如何自動化生成各欄位的ID資訊,這就不是一件簡單的事了,不同的欄位,不同的客戶端環境:Web/IOS/安卓,不同的控制元件物件,如何生成唯一的ID標識,又不需要業務方太多的干預或者配合,這就要各顯神通了。。。

隨便舉一些例子:

A欄位好說,畢竟站點/業務 級別的種類不會太多,直接預定義好,寫入頁面的後臺公共模版就好了。

B欄位呢?比如在Web端,可以採用後臺具體頁面模版的URL的Hash值,找一個不容易衝突的Hash函式基本就可以了。

那麼C欄位呢?C欄位的ID,通常只需要頁面內部唯一,所以ID值本身自動生成一個問題不大,倒是如何確定一個模組的範圍是比較大的問題?可行的方案,比如在Web頁面模版中,可以通過對頁面標籤新增特定屬性的方式來標識模組範圍,然後在點選時再自動為這個標籤生成一個固定的ID,然後再根據這個標籤的範圍計算模組內部連結的D欄位索引值。

但是,也不是所有的模組ID都只需要頁面內唯一就沒問題了,有些模組是跨頁面共享的,這種場景是預定義一個特殊ID加以標識,做到全域性唯一,還是依然只考慮頁面內唯一,那就看業務統計的需要了。

簡單來說,就是既要保留自定義的能力,又要在不打算自定義的場景下,找到一個自動生成唯一且固定的標識的途徑(UUID這種純粹隨機,每次生成結果都不一樣的值當然是不行的),以免業務方需要自己生成和維護ID列表。

而植入和串聯這些ID的過程,也有各種各樣的問題要解決,特殊定製化處理都不難,難就難在要以通用的方式,標準化的處理,總之,一切都是要圍繞著降低維護代價來考慮。

其它問題

上一篇的讀書筆記在討論阿里的日誌採集鏈路的過程中,其實也已經提到了一些問題。

比如使用者在客戶端進行的頁面回退行為的識別,需要對這種行為加以識別和篩選。PC端問題少一點,因為可以同時開啟多個頁面,使用者回退的行為會少一些。而在APP端,通常只能同時開啟一個頁面,所以比如從詳情頁回退到商品列表頁面,再次開啟另一個詳情頁,這種情況就會很普遍。很顯然,要分析頁面轉化率,你不能認為商品列表頁面的來源是上一個詳情頁吧,所以肯定要對這種行為進行修正處理。至於怎麼識別和修正這種行為,細節就不討論了。

Hybrid混合模式的處理:H5和Native頁面混合使用的場景越來越普及,雖然使用者未必能夠感知,但是從原理上來說,這兩種頁面的日誌採集方案通常是兩套架構,互相之間的日誌流程也往往是隔離的,但是在鏈路跟蹤的場景下,他們的日誌必須要統一處理才能正確的復現使用者的行為路徑。

所以通常是要自動識別H5頁面的執行環境,並且打通H5跳轉到Native和Native跳轉到H5兩個方向的頁面資料傳遞,否則在Hybrid場景下,行為鏈路的日誌就會被打斷了。


再有,比如當存在頁面301/302 重定向的行為時,鏈路引數怎麼處理?當要跟蹤訂單成交鏈路時,使用者是先加了購物車,過後,再從購物車裡下的訂單,又怎麼追蹤原始成交鏈路?還有更多的類似問題,都是使用者行為日誌採集過程中需要解決的。雖然每一個點,單從技術的角度來說,都未必很難,但要做到通用,完善,可靠,卻不是一兩天可以搞定的事情了。因此使用者鏈路行為跟蹤和分析的日誌採集,會是一個隨著業務的發展,需要持續改進的工作。

小節

我司在使用者行為鏈路跟蹤分析方面,日誌的採集方案主要參考了阿里的SPM的思想。前前後後實踐了也有快三年的時間了,原理和思想本身並不複雜,但是在方案完善的過程,包括歷史方案的相容遷移過程中,還是花費了不小的力氣,填補了各式大坑小坑。

總體來說,該方案,在各種精確鏈路追蹤,來源分析,活動統計等業務場景中都有不錯的表現,不過,在應用模式上,我司的實踐還不夠充分。不光是從標準化自動化的角度來看,也包括業務的應用場景和相關鏈路資料價值的進一步挖掘方面,都還有很大的發揮和改進空間。

-----------

常按掃描下面的二維碼,關注“大資料務虛雜談”,務虛,我是認真的 ;)