连续复制
一键复制
一键打包

js 埋点统计数据

/*
 *  埋点数据: { timestamp,  actionName, actionValue, function1, function2, function3, * platform, * source, * userId, * userMobile, * userName }
 */

;(function () {

  var dataPool = [];      // 需上传数据池
  var configOption = {};  // 配置信息

  var uploadDataLimit = 20;             // 条数限制
  var uploadTimeLimit = 1 * 60 * 1000;  // 时间限制

  var uploadInited = false;
  var ua = navigator.userAgent;
  var dev = location.host !== "chat.zmlearn.com";
  var uploadPath = '//log' + (dev && '-test' || '') + '.zmlearn.com/api/pcAnalytics';

  window.zmClientAcc = zmClientAcc;
  window.uploadServer = uploadServer;
  window.initZmClientAcc = initZmClientAcc;

  // 绑定点击事件,记录点击操作
  window.addEventListener('click', function (event) {
    var target = event.target;
    var actionName = target && target.getAttribute('data-accAction') || '点击事件';
    var functions = target && target.getAttribute('data-accFunctions');
    var clickId = target && target.getAttribute('data-clickId');
    while (target && !functions) {
      target = target.parentElement;
      functions = target && target.getAttribute('data-accFunctions');
      clickId = target && target.getAttribute('data-clickId');
    }
    try {
      functions = eval("(" + functions + ")");
      functions && zmClientAcc(actionName, functions, '', clickId);
    } catch(e) {}
  }, true);

  // 缓存有历史数据,获取并提交
  try {
    var localData = localStorage.getItem('zmAccData');
    var tempData = (JSON.parse(tempData) || {}).datas;
    if (tempData && tempData.length) {
      dataPool = tempData;
      uploadServer();
    }
  } catch(e) {}

  // 记录埋点信息,暂存内存或本地或上传
  /*
   * actionName 事件类型
   * functions 功能点
   * event_type 0表示统计事件次数,1表示统计事件时长
   * actionValue event_type为0时,每点击1次,记录1次;event_type为1时,记录时长,按秒计算
   * event_id 事件id
   * tracker_type 1表示设备信息,2表示事件信息
   * eventPara 用来统计自定义分析维度
   */
  function zmClientAcc(actionName, functions, actionValue, event_id, event_type) {
    var newItem = {
      timestamp: +new Date,
      actionName: actionName || '点击次数',
      actionValue: actionValue || 1,
      event_id: event_id || '',
      tracker_type: 2,
      event_type: event_type || 0,
      eventPara: '',
      userAgent: ua,
      requestPath: location.href
    };
    forEach(functions || [], function(fun, index) {
      newItem['function' + (index + 1)] = fun;
    });
    dataPool.push(newItem);
    checkForUpload();
    window.debugZmClientAcc && console.log(actionName, functions, dataPool, newItem);
  }

  // 用户相关信息完整,根据阈值上传服务器,否则记录本地
  function checkForUpload() {
    var dataPoolLength = dataPool.length;
    var timeNow = +new Date;
    uploadServer.lastUploadTime = uploadServer.lastUploadTime || (timeNow + uploadTimeLimit);
    var hitLimit = dataPoolLength > uploadDataLimit || (timeNow - uploadServer.lastUploadTime) > uploadTimeLimit;
    if (uploadInited && hitLimit) {
      uploadServer();
    } else {
      tryKeepLocal(dataPoolLength);
    }
  }

  // 记录上传数据,清空临时数据池,更新本地缓存,上传数据
  function uploadServer() {
    uploadServer.lastUploadTime = +new Date;
    var uploadData = dataPool;
    dataPool = [];
    tryKeepLocal(-1, 1);

    // 扩展每条提交数据的内容
    forEach(uploadData, function (item) {
      for (var key in configOption) {
        configOption.hasOwnProperty(key) && (item[key] = configOption[key]);
      }
    });

    var xhr = new XMLHttpRequest();
    xhr.timeout = 3000;
    xhr.open('POST', uploadPath, true);
    xhr.setRequestHeader("Content-type","application/json; charset=utf-8");
    xhr.onreadystatechange = xhr.onload = xhr.ontimeout = xhr.onerror = xhr.upload.onprogress = function(event) {
      window.debugZmClientAcc && console.log(event);
    };
    xhr.send(JSON.stringify(uploadData));
  }

  function tryKeepLocal(dataPoolLength, checkTime) {
    tryKeepLocal.timer && clearTimeout(tryKeepLocal.timer);
    // 按间隔暂存统计数据到本地,防止数据丢失,设置检测阈值,防止频繁更新
    tryKeepLocal.timer = setTimeout(function () {
      if (dataPoolLength != dataPool.length) {
        try {
          localStorage.setItem('zmAccData', JSON.stringify({
            timestamp: +new Date,
            datas: dataPool.slice(-500)
          }));
        } catch(e){}
      }
    }, checkTime || 1000);
  }

  function initZmClientAcc(paramMap) {
    Object.assign(configOption, paramMap);
    uploadInited = Object.values(paramMap).every(it => it);
  }

  function forEach(list, cb) {
    if (!(list instanceof Array) || (typeof cb != 'function')) return;
    for (var i = 0; i < list.length; i++) {
      cb(list[i], i);
    }
  }
})();