前端埋點實現及原理分析

正如在宏觀介紹的博客中寫到的,做用戶行爲分析的方式有“前端埋點”和“後端埋點”的區分,真好今天敲了一個坤哥整理的“前端埋點”的程序,理解了之後結合demo來簡單講解“前端埋點”如何做。

前端埋點原理圖:

在這裏插入圖片描述
如上所示,從broswer到page,再到javascript以及後端backend,瀏覽器返回正常程序運行結果,本地文件中返回最終的log,這很像是在用戶程序中埋下了一段“暗代碼”,無形之中“竊取”了用戶的行爲信息,淘寶、網易等都有這樣的功能。
可以參考google做的Google Analysis這塊產品)

步驟:

  • 埋點階段
  • 數據收集階段
  • 後端處理階段

如上,針對“前端埋點”,主要分爲這麼三部,對應到上面的原理圖,步驟一即(create script element),步驟二即collect client data,步驟三即backend和log.

下面,分別按照上述三步來展示代碼:

埋點階段

<script type="text/javascript">
    var _maq = _maq || [];
    _maq.push(['_setAccount', 'uuid']);
    (function () {
        var ma = document.createElement('script');
        ma.type = 'text/javascript';
        ma.async = true;
        ma.src = "http://localhost:8091/data/js/ma.js";
        var s = document.getElementsByTagName('script')[0];
        s.parentNode.insertBefore(ma, s);
    })();
</script>

這裏是正常的jsp、html頁面,在頁面的下端,往往插入一小段js代碼,即我們的“埋點”,如上所示,“埋點”中的全局數組,用於收集該頁面中需要被回傳的用戶行爲,比如:域名、ip、url、搜索的內容、常按的按鈕名稱……,(這裏暫時通過‘_setAccount’來傳遞了一個值爲‘vincent’的用戶名)

之後匿名的js函數,是埋點代碼的重中之重,如上代碼所示,在Dom節點添加名爲‘script’的元素,設置"ma.async = true",表示讓其異步執行,並將其src屬性指定爲一個單獨的js文件(將ma.js引入進來),最終將該element插到當前Dom樹上。而這個過程最終的目的即請求並執行上述的ma.js文件。

數據收集階段

(function () {
    var params = {};
    //Document對象數據
    if (document) {
        params.domain = document.domain || ''; //獲取域名
        params.url = document.URL || '';       //當前Url地址
        params.title = document.title || '';
        params.referrer = document.referrer || '';  //上一跳路徑
    }
    //Window對象數據
    if (window && window.screen) {
        params.sh = window.screen.height || 0;    //獲取顯示屏信息
        params.sw = window.screen.width || 0;
        params.cd = window.screen.colorDepth || 0;
    }
    //navigator對象數據
    if (navigator) {
        params.lang = navigator.language || '';    //獲取所用語言種類
    }
    //解析_maq配置
    if (_maq) {
        for (var i in _maq) {                      //獲取埋點階段,傳遞過來的用戶行爲
            switch (_maq[i][0]) {
                case '_setAccount':
                    params.account = _maq[i][1];
                    break;
                default:
                    break;
            }
        }
    }
    //拼接參數串
    var args = '';
    for (var i in params) {
        // alert(i);
        if (args != '') {
            args += '&';
        }
        args += i + '=' + params[i];           //將所有獲取到的信息進行拼接
    }
    //通過僞裝成Image對象,請求後端腳本
    var img = new Image(1, 1);
    var src = 'http://localhost:8091/data/dataCollection/log.gif?args=' + encodeURIComponent(args);
    alert("請求到的後端腳本爲" + src);
    img.src = src;
})();

如上代碼所示,是ma.js文件中的代碼,如上我做的註釋,可以將這個過程分爲3步驟;

  1. 解析、獲取用戶各種信息,如上:1.通過dom樹,獲取到的url,域名,上一跳信息;2.通過windows,獲取到的顯視屏的分辨率、長寬(前兩類通過內置的js對象獲取);3.通過_maq全局數組,獲取埋點時埋下的用戶行爲數據。
  2. 將上步的用戶信息按特定格式拼接,裝到args這個參數中。
  3. 僞裝成圖片,請求到後端controller中,並將args作爲http request參數傳入,做後端分析。

之所以使用圖片請求後端controller而不是ajax直接訪問,原因在於ajax不能跨域請求,ma.js和後端分析的代碼可能不在相同的域內,ajax做不到,而將image對象的src屬性指向後端腳本並攜帶參數,就輕鬆實現了跨域請求。

後端處理階段

@Controller
@RequestMapping("/dataCollection")
public class DataCollection {
    @RequestMapping(value = "log.gif")
    public void analysis(String args, HttpServletResponse response) throws IOException {
        System.out.println(args);
         
		//日誌收集 
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);
        response.setContentType("image/gif");
        OutputStream out = response.getOutputStream();
        BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
        ImageIO.write(image, "gif", out);
        out.flush();
    }
}

如上所示, 通過解析http request中的參數,即將在前端獲取到的用戶信息拿到了後端,這個爲了驗證,將其打印到控制檯,接下來就是做日誌收集工作了,到此前端獲取用戶信息已經完成。之後,生成一副1×1的空gif圖片作爲響應內容並將響應頭的Content-type設爲image/gif,返回到前端代碼中。

如圖,是在控制檯我拿到的用戶信息:
在這裏插入圖片描述
至此,前端埋點的實現以及原理就ok了,包括Google Analytics也是這麼個原理來做的。目前我跑的程序已經收集到了用戶的行爲信息,但是存在一個問題就是用戶刪除cookie信息,比如清楚瀏覽器緩存,會造成收集到的數據比實際訪問的行爲數據要多得多,這個問題接下來會繼續深入研究。

這個程序已經上傳到我的GitHub上,感興趣的朋友可以去下載,另外感謝網絡上的關於這塊的資料貢獻者,能讓我對行爲分析有深入的認識,多謝。
github地址:[email protected]:zhangzhenhua92/datacollection.git

發佈了412 篇原創文章 · 獲贊 65 · 訪問量 25萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章