background

With the development of the Internet, the importance of data no longer needs to be emphasized, so how to do a good job in data collection is a problem that every company has to face.

There are different options for data collection. Some companies choose to use third-party statistical SDK, such as Umeng, Shence, etc. Some companies choose to inject statistical codes into their products and build query systems. Of course, the cost of the latter will be relatively large, but the advantage is closer to the company’s business.

Data burying technology

Code buried point

Code burying point is to embed data reporting code where data statistics are needed to count user behavior.

Advantages: Very precise choice of when to send data. Disadvantages: High maintenance cost, each update to the buried code maintenance, otherwise the probability of not collecting the data of the old version.

Visual burial point

Use visual interactive means instead of writing code, separate core code from configuration and resources, and update configuration and resources through the network every time you open it.

Advantages: solve the problem of high cost of burying and maintenance. Disadvantages: Limited coverage, not all controls can be customized with this solution.

No burial site

That is, the meaning of full buried point, no buried point as far as possible to collect all control operation data, and then in the system for data analysis.

Advantages: buried all elements of the page, you can obtain the page element click probability, and further analysis. Disadvantages: Data transfer and server pressure is relatively large.

Building ideas and core code

Again, start with a mind map.

Self-executing method

Make sure the buried tool can plug and play and automatically report some data as soon as it is loaded. The specific implementation is as follows:

(function (win, doc) {
    var BP = {
        // Open interface code}; win.BP = BP; }) (window.document);
Copy the code

This way, when the JS file is loaded, you can call the buried tool’s methods directly in the global BP.

Buried point

Use code burying to report data, defined in the tool:

    var BP = {
        send: function () {
            // Send data method}};Copy the code

Called through bp.send () in the page’s key action method.

At the same time, the page may be output directly from the back end, given the server-side rendering. Back-end developers can also directly add the attribute BP-data to the tag to realize data reporting when users have interactive operations.

    /** * capture the node click event */ with the bP-data attribute
    var buryingPoint = function () {
        var attr = 'bp-data';
        var evtType = utils.mobile ? 'touchstart' : 'mousedown';
        utils.addEvent(doc, evtType, function (evt) {
            var target = evt.srcElement || evt.target;
            while (target && target.parentNode) {
                if (target.hasAttribute(attr)) {
                    BP.send();
                    break; } target = target.parentNode; }}); };Copy the code

In order to accommodate both PC and mobile browsers, utils.addEvent is designed as a method that can listen for events across browsers, as follows:

    var utils = {
        /** * cross-browser event listening */
        addEvent: function () {
            if (doc.attachEvent) {
                return function (ele, type, func) {
                    ele.attachEvent('on' + type, func);
                };
            } else if (doc.addEventListener) {
                return function (ele, type, func) {
                    ele.addEventListener(type, func, false); }; (1)}}}Copy the code

Data collection

Regardless of the business, the most common data that needs to be counted is usually UV and PV, and sometimes the time spent on the page. Based on these basic requirements, the following data to be collected are sorted out:

  • Client Information

Client information for front-end development belongs to a relatively headache, all kinds of magic UserAgent seriously affect the developer’s mood. I believe that the major companies also have a mature process for UserAgent judgment, as a personal development to recommend a code library UA-Device, can reduce a lot of work in this area. The only drawback is that referencing this library will increase the size of the packaged JS file by about 150KB, which I think is not a concern in the current network environment.

    // Browser information
    var CI = {
        size: function () {
            return scr.width + 'x'+ scr.height; } (),// Network type
        network: function () {
            return (nav.connection && nav.connection.type) ? nav.connection.type : The '-'; } (),/ / language
        language: function () {
            return nav.language || ' '; } (),timezone: function () {
            return new Date().getTimezoneOffset() / 60 || ' '; } (),ua: function () {
            return encodeURIComponent(ua); } (),os: function () {
            var o = uaOutput.os;
            return encodeURIComponent(o.name + '_'+ o.version.original); } (),browser: function () {
            var b = uaOutput.browser;
            return b.name + '_'+ b.version.original; } (),engine: function () {
            var e = uaOutput.engine;
            return e.name + '_' + e.version.original;
        }()
    };
Copy the code
  • Traffic sources

  • Page address

  • The session id

The session ID is used to calculate the UV and generate a UUID when the tool is initialized. Since the session ID is not updated after the page is opened, it is implemented using class VUE to evaluate properties.

    var BP = {
        /** * Session ID, refresh page will update */
        sessionId: function () {
            return UUID.create();
        }()
    }
Copy the code
  • Device id

Device IDS are used to concatenate user behavior. For example, when a user views several pages and reports several pieces of data, the device ID can be used to link these actions together. Because the front end can’t really get a unique identifier for the device being used, it uses a uUID that doesn’t repeat itself, just like the session ID. Also a calculated property of class Vue.

    BP = {
        /** * device id, read cookie, if not exist in cookie */
        deviceId: function () {
            var did = utils.getCookie(cookieName);
            if(! did) { did = UUID.create(); utils.setCookie(cookieName, did, year); }return did;
        }()
    }
Copy the code
  • The time stamp

  • Page duration

The least expensive way to record the time spent on a page is to use polling to report data, and the interval of requests can be determined according to the business requirements. After all, the smaller the interval, the greater the load on the server, but the more accurate the data will be.

    /** * The Ticker hook function is used to report the page duration * @param dt interval */
    var calStayTime = function (dt) {
        totalTime += dt;
        if(totalTime >= stayTime) { BP.send(); totalTime -= stayTime; }};/ / start the ticker
    ticker.start();
    ticker.register(calStayTime);
    
    // The page is no longer timed when it leaves
    utils.addEvent(doc, 'visibilitychange'.function () {
        if (doc.visibilityState === 'hidden') {
            ticker.stop();
        } else{ ticker.start(); }});Copy the code

In order to report as accurate a dwell time as possible, the timer should be stopped when leaving the page (such as minimizing or switching tabs). A separate, simplified version of Ticker is used to maintain the timeline. For more questions about maintaining the timeline, see the links below.

Implement a Ticker in TypeScript

Data storage and reading

Cookies are used to store persistent data, such as device ids.

    var utils = {
        /** * Set cookie * @param name name * @param value value * @param days Save time * @param domain domain */
        setCookie: function (name, value, days, domain) {
            if (value === null) {
                return;
            }
            if (domain === undefined || domain === null) {
                // Remove the port part of host
                domain = utils.stringSplice(win.location.host, ' '.':'.' ');
            }
            if (days === undefined || days === null || days === ' ') {
                doc.cookie = name + '=' + value + '; domain=' + domain + '; path=/';
            } else {
                var now = new Date(a);var time = now.getTime() + DAY * days;
                now.setTime(time);
                doc.cookie = name + '=' + value + '; domain=' + domain + '; expires=' + now.toUTCString() + '; path/'; }},/** * read cookie * @param name name */
        getCookie: function (name) {
            if (name === undefined || name === null) {
                return;
            }
            var reg = RegExp(name);
            if (reg.test(doc.cookie)) {
                return utils.stringSplice(doc.cookie, name, '; '.' '); }}}Copy the code

Reported data

Buried data reporting can be viewed as a one-way request in nature, that is, data can be sent to the server in the form of image tags without concern for server feedback, while avoiding additional cross-domain problems.

    var utils = {
        /** * send the request with the image tag across the domain * @param URL interface address */
        sendRequest: function (url) {
            if (page.length === 0) {
                console.error('Please configure valid page parameters'.'@burying-point');
                return;
            }
            var img = newImage(); img.src = url; }}Copy the code

extension

  • White list

Add a whitelist filter to specify that only domain names in the whitelist can send requests. This is just a trick to avoid reporting too much dirty data during development and increase the workload of data analysis.

    var utils = {
        /** * Whitelist verification */
        checkWhiteList: function () {
            if (whiteList.length === 0) {
                return true;
            }
            var href = win.location.href;
            var flag = false;
            for (var i = 0; i < whiteList.length; i++) {
                if (href.indexOf(whiteList[i]) > - 1) {
                    flag = true;
                    break; }}returnflag; }}Copy the code

use

Buried tools are built to report data in two different ways.

First, direct reporting via code:

    <script>
        BP.send();
    </script>
Copy the code

Add the BP-data attribute to the DOM tag:

    <div bp-data>Click and I'll report a data</div>
Copy the code

conclusion

Developing a front-end data burying tool does not require particularly complex technology, but is more based on business thinking. Here are some of the key parts as a reference:

  • Self-executing method
  • Cross-browser event listening
  • Maintenance timeline
  • Cookie, speaking, reading and writing
  • One-way cross-domain request
  • Class vue computes attributes

Complete code and usage, please go to GitHub, thank you.