翻譯自 Google 工程師 Philip Walton 的文章递览。共 3754 字,讀完需 7 分鐘偶宫。合格的工程師要能認(rèn)識(shí)到數(shù)據(jù)和功能一樣重要非迹,因?yàn)闇?zhǔn)確的數(shù)據(jù)收集是產(chǎn)品迭代、市場(chǎng)營(yíng)銷的決策基礎(chǔ)纯趋。本文會(huì)幫你剖析為什么你常用的統(tǒng)計(jì)方式是錯(cuò)的憎兽?然后給出可行的解決方案。
直言不諱的說(shuō)吵冒,目前市面上的 Page View(常說(shuō)的PV纯命,即用戶瀏覽頁(yè)面的次數(shù))統(tǒng)計(jì)工具無(wú)法準(zhǔn)確統(tǒng)計(jì)越來(lái)越多的新站點(diǎn),且已經(jīng)和 WEB 技術(shù)的演進(jìn)方向完全脫節(jié)痹栖。
因?yàn)樵诖蠖鄶?shù)情況下亿汞,這些工具假設(shè)每次頁(yè)面瀏覽(Page View)對(duì)應(yīng)一次頁(yè)面加載(Page Load),且每次頁(yè)面加載完成后都會(huì)運(yùn)行一些統(tǒng)計(jì)代碼揪阿,將 Page View 事件發(fā)送到后端服務(wù)器疗我。任何不符合這種模式的網(wǎng)站都需要工程師做額外的工作才能統(tǒng)計(jì)到正確的結(jié)果咆畏,然而大多數(shù)前端工程師似乎不具備這方面的專業(yè)知識(shí),或者干脆沒(méi)有時(shí)間吴裤。
現(xiàn)實(shí)是旧找,WEB 技術(shù)在過(guò)去 10 年間發(fā)生了巨大的變化,越來(lái)越多的網(wǎng)站已經(jīng)不符合傳統(tǒng)的網(wǎng)站模式麦牺,而我們的分析工具演化并沒(méi)有跟上钮蛛。
問(wèn)題在哪兒?
舉個(gè)具體的例子剖膳,考慮 mail.google.com(Gmail)魏颓,使用 Gmail 的大多數(shù)人在首次打開后會(huì)保持它在后臺(tái)運(yùn)行,每隔一段時(shí)間去檢查是否有新消息吱晒,如果有新消息甸饱,會(huì)直接打開閱讀,整個(gè)過(guò)程無(wú)需刷新頁(yè)面枕荞。
由于絕大多數(shù) Gmail 用戶幾乎從來(lái)不刷新頁(yè)面柜候,從統(tǒng)計(jì)分析的角度就產(chǎn)生了一些非常有趣但重要的疑問(wèn):
- 如果用戶打開 Gmail 一次搞动,而在接下來(lái)的幾天之內(nèi)使用數(shù)百次躏精,但是并沒(méi)有刷新頁(yè)面,這種情況應(yīng)該只算一個(gè) Page View 么鹦肿?
- 如果用戶點(diǎn)擊 Gmail 左上角的 Logo 來(lái)刷新頁(yè)面內(nèi)容矗烛,或者移動(dòng)端的下拉刷新,是否應(yīng)該算一個(gè)新的 Page View箩溃?這種動(dòng)作與完全刷新頁(yè)面有何不同瞭吃?
- 如果用戶打開并閱讀一封新郵件,實(shí)際上無(wú)需刷新頁(yè)面涣旨,是否應(yīng)該計(jì)算為一個(gè)新的 Page View歪架?
- 如果兩個(gè)用戶每天訪問(wèn) Gmail 的次數(shù)完全相同,但是其中一個(gè)每次刷新霹陡,而另一個(gè)保持頁(yè)面在后臺(tái)運(yùn)行和蚪,這兩種使用模式的 Page View 統(tǒng)計(jì)結(jié)果應(yīng)該有很大的不同么?
列舉這些疑問(wèn)想說(shuō)明的問(wèn)題是烹棉,對(duì)于某些站點(diǎn)攒霹,繼續(xù)使用傳統(tǒng)的 Page View 統(tǒng)計(jì)方法會(huì)導(dǎo)致不準(zhǔn)確的統(tǒng)計(jì)結(jié)果,而在 WEB 應(yīng)用的技術(shù)實(shí)現(xiàn)方案隨時(shí)間推移不斷演進(jìn)的情況下浆洗,這種不準(zhǔn)確會(huì)變的非常離譜催束。
試想,你在傳統(tǒng)的 WEB 網(wǎng)站中添加了統(tǒng)計(jì)代碼伏社,幾個(gè)月后抠刺,你將該網(wǎng)站更新為單頁(yè)應(yīng)用(SPA塔淤,或 Single Page Application),而沒(méi)有修改統(tǒng)計(jì)代碼代碼速妖。再過(guò)幾個(gè)月凯沪,你又將網(wǎng)站更新為漸進(jìn)式 WEB 應(yīng)用(PWA,或 Progressive Web Application)买优,這種技術(shù)可以在后臺(tái)重新加載內(nèi)容并脫機(jī)工作)妨马,這時(shí)候你仍然沒(méi)有更新統(tǒng)計(jì)代碼。如果這段時(shí)間應(yīng)用的訪客數(shù)量及使用模式?jīng)]有變化杀赢,你肯定會(huì)期望統(tǒng)計(jì)結(jié)果不出現(xiàn)大幅度波動(dòng)烘跺。
不幸的是,在上述情況下脂崔,即使你改善了用戶體驗(yàn)滤淳,但 Page View 的統(tǒng)計(jì)結(jié)果可以肯定是下降的。這是一個(gè)非常糟糕的情況:你希望改善網(wǎng)站的交互體驗(yàn)砌左,但是無(wú)法用數(shù)據(jù)說(shuō)服任何人這樣做是值得的脖咐,因?yàn)榻y(tǒng)計(jì)數(shù)據(jù)給出的結(jié)果是完全相反的。
該怎么解決汇歹?
任何技術(shù)問(wèn)題總會(huì)有解決辦法屁擅,本文提出的解決方案則需要回歸 Page View 這個(gè)指標(biāo)的本原。我們需要追蹤的不是頁(yè)面被加載(loaded)的次數(shù)产弹,而是被瀏覽(viewed)的次數(shù)派歌。
我們可以利用 Page Visibility API 達(dá)成目的,實(shí)際上該 API 已經(jīng)存在了很長(zhǎng)時(shí)間痰哨,并且?guī)缀跛械闹髁髯烂婧鸵苿?dòng)瀏覽器都支持胶果。
事實(shí)證明,統(tǒng)計(jì)頁(yè)面被瀏覽的次數(shù)而不是被加載的次數(shù)能優(yōu)雅地解決掉傳統(tǒng)統(tǒng)計(jì)方式不能處理的很多問(wèn)題:
- 當(dāng)用戶打開的某個(gè)選項(xiàng)卡轉(zhuǎn)入后臺(tái)斤斧,然后在幾小時(shí)或幾天之后再切回來(lái)早抠,但不重新加載頁(yè)面;
- 當(dāng)用戶打開某個(gè)頁(yè)面作為參考撬讽,并來(lái)回切換以快速瀏覽其中的內(nèi)容蕊连,但不重新加載頁(yè)面;
- 當(dāng)用戶在后臺(tái)選項(xiàng)卡中打開頁(yè)面锐秦,然后忘記了咪奖,從來(lái)沒(méi)有實(shí)際瀏覽頁(yè)面內(nèi)容;
Page Visibility API 由 document.visibilityState 屬性以及 visibilitychange 事件組成酱床⊙蛘裕基于這兩個(gè) API,你可以確保只會(huì)在頁(yè)面的 visibilityState 可見時(shí)才發(fā)送 Page View 統(tǒng)計(jì)。此外昧捷,你還可以監(jiān)聽 visibilitychange 事件闲昭,在用戶重新切回到在后臺(tái)運(yùn)行有段時(shí)間的應(yīng)用時(shí)發(fā)送新的 Page View 統(tǒng)計(jì)。Page Visibility API 很好的解決了加載完成后幾乎不需要刷新的 WEB 應(yīng)用的 Page View 統(tǒng)計(jì)問(wèn)題靡挥。
解決方案的第二部分是 History API序矩,這是 SPA 應(yīng)用構(gòu)建的基礎(chǔ)技術(shù),目前主流瀏覽器都支持(詳見)跋破,因此統(tǒng)計(jì)工具可以通過(guò)監(jiān)聽 URL 變化來(lái)發(fā)送類似于傳統(tǒng)網(wǎng)站的頁(yè)面統(tǒng)計(jì)簸淀。
該怎么實(shí)現(xiàn)?
利用 Page Visibility 和 History API 來(lái)準(zhǔn)確統(tǒng)計(jì) Page View 的基本思路如下(這種思路適用于傳統(tǒng)網(wǎng)站毒返、SPA租幕、PWA):
- 頁(yè)面加載時(shí),如果頁(yè)面的 visibilityState 是可見的拧簸,發(fā)送 Page View 統(tǒng)計(jì)劲绪;
- 如果頁(yè)面的 visibilityState 是隱藏的,就監(jiān)聽 visibilitychange 事件盆赤,并在 visibilityState 變?yōu)榭梢姇r(shí)發(fā)送 Page View 統(tǒng)計(jì)贾富;
- 如果 visibilityState 由隱藏變?yōu)榭梢姡⑶易陨洗斡脩艚换ブ笠呀?jīng)過(guò)了“足夠長(zhǎng)”的時(shí)間牺六,就發(fā)送新的 Page View 統(tǒng)計(jì)颤枪;
- 如果 URL 發(fā)生變化(僅限于 pathname 或 search 部分發(fā)送變化, hash 部分則應(yīng)該忽略,因?yàn)樗怯脕?lái)標(biāo)記頁(yè)面內(nèi)跳轉(zhuǎn)的) 發(fā)送新的 Page View 統(tǒng)計(jì)兔乞;
上述步驟 3 是最重要的汇鞭,但同時(shí)也是最模糊的和頗具爭(zhēng)議的,關(guān)鍵的問(wèn)題是:究竟多長(zhǎng)才算是“足夠長(zhǎng)”庸追?一方面,你可能并不想在每次 visibilityState 發(fā)生變化的時(shí)候都發(fā)送新的 Page View 統(tǒng)計(jì)台囱,因?yàn)閷?duì)于用戶來(lái)說(shuō)淡溯,在選項(xiàng)卡之間來(lái)回切換是非常常見的,而實(shí)際情況是簿训,某些應(yīng)用同時(shí)在多個(gè)選項(xiàng)卡中打開使用是最方便的咱娶,而這就伴隨這大量的選項(xiàng)卡切換。另一方面强品,你又期望統(tǒng)計(jì)到在一段時(shí)間沒(méi)有和應(yīng)用交互之后用戶的回訪(returning)行為膘侮,也就是說(shuō)需要統(tǒng)計(jì)到用戶多次使用的行為。
幸運(yùn)的是的榛,所有的統(tǒng)計(jì)工具都定義了一種區(qū)分多次使用的方式琼了,即會(huì)話,或者叫 Session。會(huì)話是在給定時(shí)間窗口中發(fā)生的用戶交互的集合雕薪,當(dāng)某個(gè)預(yù)設(shè)的時(shí)間段過(guò)去時(shí)會(huì)話就結(jié)束了昧诱。比如,默認(rèn)情況下 Google Analytics 的會(huì)話在 30 分鐘無(wú)交互的情況下結(jié)束所袁。而大多數(shù)統(tǒng)計(jì)工具都提供了會(huì)話時(shí)長(zhǎng)自定義的功能盏档。
所以回到上面列表中的第三步,我的建議是燥爷,如果用戶會(huì)話已結(jié)束蜈亩,并且頁(yè)面的 visibilityState 從隱藏變?yōu)榭梢姡瑒t應(yīng)發(fā)送新的 Page View 統(tǒng)計(jì)前翎。在會(huì)話內(nèi)發(fā)生的 visibilityState 變更不應(yīng)被視為不同的 Page View勺拣。
注意:如果你使用 autotrack(特別是 pageVisibilityTracker 和 urlChangeTracker 插件),你就無(wú)需自己實(shí)現(xiàn)上面的邏輯鱼填。這些插件可以自動(dòng)處理所有這些情況药有,當(dāng)然你可以使用配置項(xiàng)來(lái)自定義插件的行為)。
如何減少誤報(bào)苹丸?
在為 autotrack 創(chuàng)建 pageVisibilityTracker 插件時(shí)愤惰,我對(duì)基于 Page Visibility API 的多種實(shí)現(xiàn)方案進(jìn)行了大量徹底的測(cè)試,發(fā)現(xiàn)利用啟發(fā)式信息在避免誤報(bào)上是非常必要的赘理。
例如宦言,用戶使用鍵盤快速在一堆打開的標(biāo)簽頁(yè)中來(lái)回切換,結(jié)果是很多頁(yè)面的 visibilityState 從隱藏變?yōu)榭梢娚棠#呛芸煊只謴?fù)原狀奠旺。在我的測(cè)試中,有相當(dāng)比例的 Page View 是由于在會(huì)話超時(shí)后 visibilityState 變?yōu)榭梢妼?dǎo)致施流,但是緊接著 visibilityState 又恢復(fù)為隱藏响疚。而 99% 類似這種的頁(yè)面從可見恢復(fù)為隱藏狀態(tài)的間隔都在 5 秒以內(nèi)。
當(dāng)我分析自己的使用模式之后瞪醋,這種現(xiàn)象的存在并不奇怪忿晕,很常見的操作有:意外的切換到一個(gè)選項(xiàng)卡,但是很快就離開了银受;切換到一個(gè)選項(xiàng)卡践盼,只因?yàn)槲乙袚Q到其他的選項(xiàng)卡,而這個(gè)選項(xiàng)卡剛好在夾在中間(這里使用鍵盤切換)宾巍;切換到某個(gè)選項(xiàng)卡咕幻,只是為了關(guān)閉它。在所有這些情況下顶霞,發(fā)送新的 Page View 并沒(méi)有任何意義肄程,而在上報(bào) Page View 統(tǒng)計(jì)之前設(shè)置 5 秒的超時(shí)可以防止 99% 以上的誤報(bào)。
Page View 和 Page Load
有時(shí)候你可能想了解你的網(wǎng)站加載(Page Load)了但從未被瀏覽過(guò)的頻率,你可能還想知道頁(yè)面瀏覽是由初始頁(yè)面加載觸發(fā)還是由 visibilityState 或 URL 變化導(dǎo)致的绷耍。
顯然你可以創(chuàng)建一個(gè)自定義維度來(lái)統(tǒng)計(jì)頁(yè)面加載(實(shí)際上我通常會(huì)這樣做)吐限,但是透過(guò)這個(gè)問(wèn)題我們能清楚的認(rèn)識(shí)到,我們真正需要的是兩個(gè)獨(dú)立的指標(biāo):頁(yè)面瀏覽(Page View)和頁(yè)面加載(Page Load)褂始。幸運(yùn)的是诸典,如今的大多數(shù)統(tǒng)計(jì)工具允許用戶自定義指標(biāo)來(lái)統(tǒng)計(jì)他們想要的任何數(shù)據(jù),而 autotrack 支持通過(guò)配置項(xiàng) 幫你把頁(yè)面瀏覽與頁(yè)面加載的統(tǒng)計(jì)分開崎苗。
通過(guò)將頁(yè)面瀏覽與頁(yè)面加載解耦狐粱,我們就能完全掌握 Page View 這個(gè)指標(biāo)的真實(shí)含義:測(cè)量用戶實(shí)際瀏覽頁(yè)面的次數(shù),而無(wú)論頁(yè)面加載了多少次胆数。
Page View 和 Session
有些讀者可能會(huì)嘀咕:只要你正確的統(tǒng)計(jì)到了初次頁(yè)面加載后用戶的所有交互肌蜻,只統(tǒng)計(jì)首次頁(yè)面加載又有什么關(guān)系呢?Page View 的正確統(tǒng)計(jì)為什么至關(guān)重要呢必尼?
雖然看起來(lái)似乎是一個(gè)合理的問(wèn)題蒋搜,但如果你了解大多數(shù)統(tǒng)計(jì)工具使用的數(shù)據(jù)模型,你將很快意識(shí)到這些問(wèn)題本身是站不住腳的判莉。
大多數(shù)分析工具假定每個(gè)會(huì)話都至少包含一個(gè) Page View豆挽,該 Page View 用于確定諸如 Landing Page(落地頁(yè))和 Exits(跳出頁(yè))等指標(biāo)。如果你僅僅統(tǒng)計(jì)了初次頁(yè)面加載券盅,然后后續(xù)所有會(huì)話只包含事件統(tǒng)計(jì)帮哈,則大多數(shù)會(huì)話報(bào)告變得一團(tuán)糟。而幾乎所有的傳統(tǒng) WEB 統(tǒng)計(jì)工具都使用這種模型來(lái)計(jì)算锰镀,這也從側(cè)面印證了傳統(tǒng)模型的局限性娘侍。
暫且把工具限制放在一邊,另外一個(gè)讓你信服的論據(jù)是:所有包含了用戶交互事件的會(huì)話都應(yīng)該至少包含一次 Page View泳炉,畢竟憾筏,如果沒(méi)有打開頁(yè)面,你怎么跟它交互呢胡桃?在會(huì)話超時(shí)踩叭、visibilityState 變?yōu)榭梢姇r(shí)發(fā)送新的 Page View 能好好的解決這個(gè)問(wèn)題。
總結(jié)和 TIPS
希望你讀完這篇文章翠胰,能重新思考 Page View 的正確姿勢(shì),如果你在自己項(xiàng)目中使用了統(tǒng)計(jì)工具自脯,可以結(jié)合本文的建議把統(tǒng)計(jì)做到準(zhǔn)確之景。
統(tǒng)計(jì)工具應(yīng)該衡量的是用戶參與度,而不應(yīng)該與網(wǎng)站的技術(shù)實(shí)現(xiàn)相耦合膏潮。當(dāng)用戶體驗(yàn)改善時(shí)锻狗,我們應(yīng)該可以通過(guò)統(tǒng)計(jì)工具的分析報(bào)告來(lái)證明。這是利用技術(shù)推動(dòng)業(yè)務(wù)發(fā)展最直接的方法。
如果你使用的是 Google Analytics轻纪,則可以通過(guò)使用 autotrack(強(qiáng)烈建議 SPA 或 PWA 項(xiàng)目使用)來(lái)將本文的解決方案運(yùn)用到項(xiàng)目中油额,要查看如何配置 autotrack 的示例?請(qǐng)移步 analyticsjs-boilerplate 倉(cāng)庫(kù)刻帚。
One More Thing
本文譯者王仕軍潦嘶,商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處崇众。如果你覺得本文對(duì)你有幫助掂僵,請(qǐng)點(diǎn)贊!如果對(duì)文中的內(nèi)容有任何疑問(wèn)顷歌,歡迎留言討論锰蓬。想知道我接下來(lái)會(huì)寫些什么?歡迎訂閱知乎專欄:《前端周刊:讓你在前端領(lǐng)域跟上時(shí)代的腳步》眯漩。