網站數據統計分析之二:前端日誌採集是與非

在上一篇《網站數據統計分析之一:日誌收集原理及其實現》中,我們詳細的介紹了整個日誌採集的原理與流程。可是不是這樣在真實的業務環境中就萬事大吉了呢?事實每每並不是如此。好比針對前端採集日誌,業務的同窗常常會有疑問:大家的數據怎麼和後端日誌對不上呢?後端比大家多了 N%!技術的同窗也會問:大家怎麼不打後端記日誌呢?後端比大家效率和準確性更高。帶着這些疑問今天我們就來聊聊前端日誌採集中的這些是是非非。javascript

一、前端 VS 後端到底哪一個準?該用誰?

這應該算是統計分析同窗最爲關注的問題之一了,到底哪一個準咱們應該從技術和業務兩個角度來看待這個問題。前端

1.1 從技術架構層面日誌分類

日誌採集從技術架構層面而言就兩種,前端與後端。前端日誌採集說白了也就是頁面部署統計代碼,經過java

 <img src='/log_xxx.gif?k=v'> 或者 javascript 發送 ajax 請求的方式來發送日誌請求。後端通常在 webCGI 中經過日誌 API 接口輸出日誌(好比 java 中 log4j),或者直接 webServer 中打印日誌(好比 Tomcat)。那這兩種技術方案各有何優劣呢?git

1.1.1 前端 JS 採集

優點:輕量,調試友好,可擴展性維護性好github

劣勢:數據不安全,易丟失,客戶端環境複雜兼容成本高web

1.1.2 後端服務採集

優點:數據完整性有保證,業務數據安全ajax

劣勢:對後端業務代碼有必定侵入性,容易受爬蟲影響,非後臺交互行爲日誌採集不到數據庫

經過上面比較咱們能夠看到先後端採集方案各有優劣,僅從數據量角度而言,後端日誌採集方案能保證日誌更爲完整準確。編程

1.2 從業務架構層面日誌分類

從業務架構出發,日誌主要分爲三大類:後端

  • 行爲日誌:瀏覽、點擊、各類交互行爲等

行爲日誌通常側重於用戶各類行爲交互、用戶屬性採集,用來評估用戶體驗、運營效果或者最後數據挖掘。好比漏斗、留存分析。

  • 業務日誌:用戶、帖子、訂單、庫存等

業務日誌每每和後端數據庫、應用服務強關聯,而且每每對日誌有特別高的安全、性能、穩定、準確性要求,好比計費、支付等。

  • 系統日誌

這類日誌通常用來衡量監控系統健康情況,好比磁盤、帶寬是否滿了,機器負載是否很高,或者RD本身經過程序輸出的應用日誌,用來監控應用服務是否異常,好比接口是否有超時,是否有惡意訪問等。

1.3 先後端差別的緣由

1.3.1 記錄日誌時機不一樣

對於行爲日誌而言,前端 js 採集腳本爲了避免影響主體業務邏輯以及取得相應業務參數,通常放在頁面底部。假設我們某個頁面200個請求,後端日誌會在某個請求返回給客戶端以前就記錄日誌,而前端日誌此時就比較吃虧了,須要等到瀏覽器執行完200個請求到頁面底部 js 時,才能發出請求,這當中的時間差是日誌差距的主要緣由之一。那麼問題就來了,若是一個頁面用戶打開後沒加載執行完(由於前置js錯誤、性能延時、主動關閉等),應該算一個 pv/uv 嗎?這種場景下,通常是認爲不該該算的,很顯而後端「搶跑」了,並且會比前端多很多。這個差別和你的頁面複雜程度,用戶網絡質量密切相關,就實測數據來看,頁面頂部到頁面底部會有 10%左右差別,前端與後端會有20%以上差別。

1.3.2 爬蟲影響

這個和公司的業務密切相關,通常都會有競品或者其它商業、科研目的的爬蟲抓取網站信息,低級的爬蟲不會觸發 js 請求,但會記錄服務器日誌,高級的爬蟲封裝了瀏覽器內核的纔會執行 js 代碼,這也是先後端日誌差別的重要緣由之一。

1.3.3 網絡質量的緣由

在移動端前端 js 請求丟失率更高,由於網絡情況很是複雜,2G、3G、4G、WiFi 等等,請求從客戶端發出來,因爲不穩定的網絡條件,不必定能到前端JS日誌服務器。

1.3.4 平臺差別

M端部分瀏覽器默認是單標籤的瀏覽方式,任何一個點擊、上一頁、下一頁按鈕都會致使下一個頁面會覆蓋上一個頁面,進而致使後端有日誌可是前端沒法記錄到用戶日誌的狀況。

另外一種狀況是可能部分老的移動端瀏覽器甚至都不支持 js,這就徹底丟失了這部分日誌。

1.3.5 其它差別

緩存、以及其它的用戶行爲也可能致使請求執行到了,可是沒有發送成功,好比用戶在頁面加載完成後,請求還未發送完成時關掉頁面,可能致使請求被 cancel 掉,這對一些用戶黏性不是很強,跳出率很高的網站而言是另外一個差別來源。

1.4 究竟該用誰? 

 

綜上所述,到底哪一個準實際上是相對而言的,得分業務場景來看,不可能有一個絕對值,至於用哪一個就看你具體的業務訴求了。

  • 前端 JS 日誌只適合用來作全流量分析與統計,更多的是用來反應總體的流量趨勢與用戶行爲,並不能精確到單個的用戶行爲與單次的訪問軌跡。它的優點在於與後端解耦,調試、擴展、採集方便,額外的開發成本很低,適合作成 SAAS 模式。這也是爲何百度統計、GA它們採用這套方案能作成一款行業通用,甚至全球化的數據產品。

  • 若是對日誌有特別高要求的業務場景好比計費、支付等等,要求日誌一條不丟同時日誌安全穩定,那就必須依賴數據庫或者後端日誌,但相應的開發維護成本會大些。

二、GA、百度統計、本身的日誌,到底哪一個準?

記得幾年前流行過一句經典語錄:幸福是個比較級,要有東西墊底才感受的到。言外之意也就是說凡事通過比較後,才能區分出優劣。回到我們的話題,早期創業公司通常會選擇第三方統計系統,一來成本低,二來投資人每每須要看第三方數據對你公司的業務運營狀態做出評估或者估值。但第三方統計只能作通用統計,對個性化的統計與深度數據挖掘無能爲力,並且企業的商業機密堪憂。所以業務作大後公司每每會選擇本身搭建數據平臺和日誌採集系統。那麼問題立刻接踵而至:本身的日誌怎麼和 GA、百度統計對不上呢?甚至這幾者中任意兩個都存在必定差距。

其實緣由大抵都是1.3中提到的緣由,除此以外還有比較細節的技術實現差別,好比請求大小,域名是否被屏蔽(好比去年 5月開始 GA 就被牆了)、第三方 Cookie、埋碼是否徹底、統計口徑與規則等等。

當你發現其中存在差別時,須要驗證各類可能緣由去校驗數據,如無特殊緣由,最終應該以本身採集的爲準。

三、數據丟了嗎?丟多少?

在 1.3.1 中提到了一些內部線上測試數據,外界也有一些同窗作過相似的測試,結論都差很少,部分業務場景下丟失率高到難以想象。好比點擊前發送日誌而後當即跳轉,若是不作任何優化處理,這種場景的丟失率巨高,每每超過 50%。

四、前端日誌採集丟失問題能解決嗎?

4.1 傳統解決方案

從技術角度能夠概括爲兩點:

  • 用戶關閉頁面過早,統計腳本還未加載/初始化完成

  • 用戶關閉或者跳出頁面的時候,請求未發出

針對第一點,機率較小,通常的處理方式就是,不要把統計腳本參合到其餘腳本中,單獨加載,而且放在前頭,讓它優先加載。不少公司的作法是,不讓開發者關心統計腳本的加載,用戶請求頁面的時候,Nginx 會在 Body 開始標籤位置注入一段腳本。或者把 js 動態請求換成 <img src> 硬編碼的方式發送請求。

對於問題二,處理方案就有不少了。

4.1.1 阻塞式的 Ajax 請求

還記得 XMLHttpRequest::open 方法的第三個參數吧,若是設置爲 false 就是同步加載,

window.addEventListener('unload', function(event) {
  var xhr = new XMLHttpRequest(),
  xhr.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");
  xhr.open('post', '/log', false); // 同步請求
  xhr.send(data);
});

 

阻塞頁面關閉,固然能夠在 readState 爲 2 的時候就 abort 請求,由於咱們不關心響應的內容,只要請求發出去就好了。

4.1.2 暴力的死循環

原理跟上面相似,只不過是使用一個空的死循環阻塞頁面關閉,

window.addEventListener('unload', function(event) {
  send(data);
  var now = +new Date;
  while(new Date - now >= 10) {} // 阻塞 10ms
});

 

4.1.3 發一個圖片請求阻塞

大部分瀏覽器都會等待圖片的加載,趁這個機會把統計數據發送出去

window.addEventListener('unload', function(event) {
  send(data);
  (new Image).src = 'http://example.com/s.gif';
});

 

以上提到的幾個方案都是一個原理,讓瀏覽器繼續保持阻塞狀態,等數據發送出去後再跳轉,這裏存在的問題是:

  • 少許瀏覽器下可能不奏效

  • 等待一下子再跳轉,用戶體驗上打了折扣,尤爲是移動端上

是否有更好的方案解決這個問題呢,前端同窗秉着「小強精神」也提出了兩個可實踐的方案。

4.2 優化方案

不就是埋點統計數據嘛,非得在當前頁面發送出去?優化方案的思路具備必定的跳躍性,咱們考慮將數據在下跳頁中發送,那麼問題就轉換爲,如何將數據傳遞給下跳頁?

對於連接點擊量的統計,咱們能夠將連接信息經過 url 傳遞給下跳頁,傳遞思路以下:

4.2.1 url 傳參

經過數組標識一個連接的位置信息,如 [站點id,頁面id,模塊id,連接index],經過四個參數能夠唯一標識連接位置屬性,使用 URL param 參數將數組數據傳遞給下跳頁,等待由下跳頁將數據發送出去。

這裏存在的問題是,下跳頁中必須部署一樣的統計腳本,但對一個系統來講,這是很容易作到的。咱們也不會在本身的網頁上放其餘網站的連接吧,因此整個數據的統計都在一個閉環內。還有就是若是統計業務複雜的狀況下,這種方案的維護成本與用戶體驗不好。

4.2.2 經過 window.name 傳遞數據

window.name 是瀏覽器給咱們開放的一個接口,設置該屬性的值後,即使頁面發生了跳轉,這個值依然不會變化,而且能夠跨域使用。

這裏存在的問題是,該屬性可能被開發者用於其餘途徑。咱們能夠限制開發者直接使用 window.name,封裝接口,經過接口調用,如 aralejs 提供的 nameStorage

nameStorage.setItem(key, value);
nameStorage.getItem(key);
nameStorage.removeItem(key);

儲存形式爲:

    scheme                  nameStorage datas
      |                            |
------------           ------------------------
nameStorage:origin-name?key1=value1&key2=value2
            -----------
                 |
         window origin name

 

以上雖然基本解決了數據丟失和體驗差的問題,可是這也很大程度依賴於開發者的編程習慣,如不能隨便玩耍 window.name ,業務複雜的場景下容易出問題,好比容易被覆蓋;也對系統有必定的要求,必須在全部頁面上部署一樣的埋點腳本。

4.2.3 localstorage 存儲重發

localstorage 是 HTML5 提供的兩種在客戶端存儲數據的新方法之一,對於丟失率高的場景,我們能夠先把請求日誌存儲在 localstorage 中,失敗後在下個頁面重發,而且能夠添加劇試機制,這樣日誌的完整性能很大程度上提升。從性能角度講還能夠統一發送,減小鏈接。

可是針對跳出率高的場景,這種方式實測效果並不明顯。

4.3 這件事情應該交給瀏覽器來解決

上面提到的各類方案,不乏黑科技,然而存在的問題仍是一大堆,若是團隊的開發者執行力不夠,中途容易出現各類麻煩。因此真正可以解決這個問題的,必然仍是瀏覽器自己!

爲何不能給用戶提供這樣一個 API,即便頁面跳轉了,也可以將上個頁面的請求發出去呢?慶幸的是,W3C 工做組也想到了這個問題,提出了 Beacon API 的 草案

Beacon API 容許開發者發送少許錯誤分析和上報的信息,它的特色很明顯:

  • 在空閒的時候異步發送統計,不影響頁面諸如 JS、CSS Animation 等執行

  • 即便頁面在 unload 狀態下,也會異步發送統計,不影響頁面過渡/跳轉到下跳頁

  • 可以被客戶端優化發送,尤爲在 Mobile 環境下,能夠將 Beacon 請求合併到其餘請求上,一同處理

sendBeacon 函數掛在在 navigator 上,在 unload 以前,這個函數必定是被初始化了的。其使用方式爲:

window.addEventListener('unload', function(event) {
  navigator.sendBeacon('/collector', data);
});

 

navigator.sendBeacon(url, data);,第一個參數爲數據上報的地址,第二個參數爲要發送的數據,支持的數據格式有:ArrayBufferView, Blob, DOMString, 和 FormData。

Beacon 的還有一個很是實用的移動端使用場景,當用戶從瀏覽器切換到其餘 app 界面或者 Home 屏的時候,部分瀏覽器默認會中止頁面腳本的執行,若是在這個時候使用了 unload 事件,可能會讓你失望,由於 unload 事件並不會觸發,此時,Beacon 就派上用途了,它是不會受影響的。

本節是對頁面打點丟失問題的簡單探討,枚舉了咱們一般會用到的一些解決方案,可能不是很完善,若是你有更好的建議,能夠提出來。

不少問題,咱們絞盡腦汁,可能不多會考慮,這個問題是否是應該由咱們來解決,或者說這個問題交給誰處理是最恰當的。本文的探討能夠看到,瀏覽器自己纔是最好的問題解決方,當網站流量變大以後,上面提到的丟失問題就更加明顯,這也迫使瀏覽器自己作了改善,天然也在情理之中。

五、總結

至此,本文探討了前端日誌採集過程當中的一些常見問題,解釋了數據分析以及RD同窗一些常見困惑,並提供了一些相應的優化思路與方案。文中提到的各類問題仍是以 PV 爲主,其實還存在另外一個常見的指標差別:UV,這個指標的差別緣由更爲複雜,改天有空再詳細分享下。總之日誌採集與統計分析沒有部分同窗想象的那麼簡單,這裏面的坑其實不少,須要你們不斷的去探索,從技術和業務角度去不斷優化改進,前路漫漫。

說明:本文第四節結合了 Refer [1] 以及本文做者的實際經驗整理而成,在此致謝,感謝分享。

六、Refer:

[1] 頁面跳轉時,統計數據丟失問題探討

http://www.barretlee.com/blog/2016/02/20/navigator-beacon-api/

[2] 網站數據統計分析之一:日誌收集原理及其實現

http://my.oschina.net/leejun2005/blog/292709

[3] 站長統計、百度統計、騰訊統計、Google Analytics 哪一統計的數據相對準確些?

https://www.zhihu.com/question/19955915

[4] 網站分析——咱們的數據準確嗎?

http://bit.ly/1RZnvWi

[5] 爲何兩個監測工具報告中的數據不一樣

http://bit.ly/1QebUBe

[6] JavaScript API 調用說明

http://help.dplus.cnzz.com/?p=62#dplus.track

[7] 數據採集與埋點

http://www.sensorsdata.cn/blog/shu-ju-jie-ru-yu-mai-dian/

[8] Beforeunload打點丟失緣由分析及解決方案:

http://blogread.cn/it/article/6804?f=wb

[9] beforeunload丟失率統計:

http://ued.taobao.org/blog/2012/11/beforeunload%E4%B8%A2%E5%A4%B1%E7%8E%87%E7%BB%9F%E8%AE%A1/

[10] 互聯網數據分析的底層應用架構

https://zhuanlan.zhihu.com/p/24018306

[11] 數據處理中的準確性問題

http://bit.ly/2vkImzb

相關文章
相關標籤/搜索