如何精確統計頁面停留時長
1、背景
頁面停留時間(Time on Page)簡稱 Tp,是網站分析中很常見的一個指標,用於反映使用者在某些頁面上停留時間的長短,傳統的Tp統計方法會存在一定的統計盲區,比如無法監控單頁應用,沒有考慮使用者切換Tab、最小化視窗等操作場景。基於上述背景,重新調研和實現了精確統計頁面停留時長的方案,需要 相容單頁應用和多頁應用,並且不耦合或入侵業務程式碼。
2、分析
我們可以把一個頁面生命週期抽象為三個動作:「進入」、「活躍狀態切換」、「離開」
如下圖,計算頁面停留時長及如何監控這三個動作,然後在對應觸發的事件中記錄時間戳,比如要統計活躍停留時長就把 active 區間相加即可,要統計總時長及 tn -t0 。
2.1 如何監聽頁面的進入和離開?
對於常規頁面的 首次載入、頁面關閉、重新整理 等操作都可以透過 window。onload 和 window。onbeforeunload 事件來監聽頁面進入和離開,瀏覽器前進後退可以透過 pageshow 和 pagehide 處理。
load / beforeunload
pageshow / pagehide
對於單頁應用內部的跳轉可以轉化為兩個問題:
監聽路由變化
判斷變化的URL是否為不同頁面 。
2.1.1 監聽路由變化
目前主流的單頁應用大部分都是基於 browserHistory (history api) 或者 hashHistory 來做路由處理,我們可以透過監聽路由變化來判斷頁面是否有可能切換。注意是有可能切換,因為URL發生變化不代表頁面一定切換,具體的路由配置是由業務決定的(即URL和頁面的匹配規則)。
browserHistory
路由的變化本質都會呼叫 History。pushState() 或 History。replaceState() ,能監聽到這兩個事件就能知道。透過 popstate 事件能解決一半問題,因為 popstate 只會在瀏覽器前進後退的時候觸發,當呼叫 history。pushState() or history。replaceState() 的時候並不會觸發。
The popstate event is fired when the active history entry changes。 If the history entry being activated was created by a call to history。pushState() or was affected by a call to history。replaceState(), the popstate event’s state property contains a copy of the history entry’s state object。
Note that just calling history。pushState() or history。replaceState() won’t trigger apopstateevent。 The popstate event will be triggered by doing a browser action such as a click on the back or forward button (or calling。history。back() or history。forward() in JavaScript)。
這裡需要透過猴子補丁(Monkeypatch)解決,執行時重寫 history。pushState 和 history。replaceState 方法:
let _wr = function (type) {
let orig = window。history[type]
return function () {
let rv = orig。apply(this, arguments)
let e = new Event(type。toLowerCase())
e。arguments = arguments
window。dispatchEvent(e)
return rv
}}
window。history。pushState = _wr(‘pushState’)
window。history。replaceState = _wr(‘replaceState’)
window。addEventListener(‘pushstate’, function (event) {})
window。addEventListener(‘replacestate’, function (event) {})
hashHistory
hashHistory 的實現是基於 hash 的變化,hash 的變化可以透過 hashchange 來監聽
2.1.2 判斷URL是否為不同頁面
方案1: 客戶端定義
透過業務方在初始化的時候配置頁面規則,然後JS透過URL匹配不同的規則來區分不同的頁面,這種方案在客戶端資料上報的時候就已經明確了不同的頁面,虛擬碼:
new Tracer({
rules: [
{ path: ‘/index’ },
{ path: ‘/detail/:id’ },
{ path: ‘/user’, query: {tab: ‘profile’} }
])
方案2: 資料分析平臺定義
假設我們最終上報後有一個數據分析平臺來展現,我們可以在類似資料平臺來配置頁面規則,這樣在客戶端實現的程式碼邏輯就不需要區分頁面,而是每次URL發生變化就將資料上報,最終透過資料平臺配置的頁面URL規則來求和、過濾資料等。
當資料展現平臺不支援配置URL規則來區分頁面的時候,可以採用方案1;當有資料平臺支援的時候採用方案2更合理;
2.1.3 對於頁面進入和離開相關事件整理
2.2 如何監聽頁面活躍狀態切換?
可以透過 Page Visibility API 以及在 window 上宣告 onblur/onfocus 事件來處理。
2.2.1 Page Visibility API
一個網頁的可見狀態可以透過 Page Visibility API 獲取,比如當用戶 切換瀏覽器Tab、最小化視窗、電腦睡眠 的時候,系統API會派發一個當前頁面可見狀態變化的 visibilitychange 事件,然後在事件繫結函式中透過 document。hidden 或者 document。visibilityState 讀取當前狀態。
document。addEventListener(‘visibilitychange’, function (event) {
console。log(document。hidden, document。visibilityState)})
2.2.2 onblur/onfocus
可以透過 Page Visibility API 以及在 window 上宣告 onblur/onfocus 事件來處理。對於PC端來說,除了監聽上述相關事件外,還可以考慮監聽滑鼠行為,比如當一定時間內滑鼠沒有操作則認為使用者處於非活躍狀態。
2.3 什麼時機上報資料?
2.3.1 頁面離開時上報
對於頁面重新整理或者關閉視窗觸發的操作可能會造成資料丟失
2.3.2 下次開啟頁面時上報
會丟失歷史訪問記錄中的最後一個頁面資料
目前採用的方案2,對於單頁內部跳轉是即時上報,對於單頁/多頁應用觸發 window。onbeforeunload 事件的時候會把當前頁面資料暫存在 localStorage 中,當用戶下次進入頁面的時候會把暫存資料上報。有個細節問題,如果使用者下次開啟頁面是在第二天,對於統計當天的活躍時長會有一定的誤差,所以在資料上報的同時會把該條資料的頁面進入時間/離開時間帶上。
3、設計
3.1 UML類關係圖
Tracer
核心類,用來例項化一個監控,對原生事件和自定義事件的封裝,監聽 enter activechange exit 事件來操作當前 Page 例項。
P。S。 取名來自暴雪旗下游戲守望先鋒英雄獵空(Tracer),直譯為:追蹤者。
Page
頁面的抽象類,用來例項化一個頁面,封裝了 enter exit active inactive 等操作,內部透過 state 屬性來維護當前頁面狀態。
3.2 事件派發關係圖
4、相容性
Desktop
Mobile
5、思考
對於頁面停留時長的定義可能在不同場景會有差異,比如內部業務系統或者OA系統,產品可能更關心使用者在頁面的活躍時長;而對於資訊型別的產品,頁面可見時長會更有價值。單一的資料對業務分析是有限的,所以在具體的程式碼實過程中我們會把停留時長分三個指標,這樣能更好的幫助產品/運營分析。
active 頁面活躍時長
visible 頁面可見時長 //僅支援Desktop
duration 頁面總停留時長
作者:今日頭條技術
連結:
https://
techblog。toutiao。com/20
18/06/05/ru-he-jing-que-tong-ji-ye-mian-ting-liu-shi-chang/
上一篇:如何讓自己學會享受孤獨?
下一篇:我只玩過一次“筆仙”