神策的数据传输方式分析

1 篇文章 0 订阅
1 篇文章 0 订阅

神策会在内部集成sdk,并且在window上挂在一个方法(sd),sd内部封装了很多方法和初始化变量。在神策官网中可以自动生成sdk来帮助我们更好的使用他们暴露的接口。

  1. UUID
    神策数据的接口在每次发送数据时都会生成一个键值对,来保证每次发送的不同。
    它会在内部生成UUID标识的方法,来完成每次数据发送的携带。
_.UUID = (function() {
   var T = function() {
     // 当前系统时间 * 1
     var d = 1 * new Date(),
       i = 0;
     while (d == 1 * new Date()) {
       i++;
     }
     return d.toString(16) + i.toString(16);
   };
   var R = function() {
     return Math.random().toString(16).replace('.', '');
   };
   var UA = function(n) {
     var ua = navigator.userAgent,
       i, ch, buffer = [],
       ret = 0;

     function xor(result, byte_array) {
       var j, tmp = 0;
       for (j = 0; j < byte_array.length; j++) {
         tmp |= (buffer[j] << j * 8);
       }
       return result ^ tmp;
     }

     for (i = 0; i < ua.length; i++) {
       ch = ua.charCodeAt(i);
       buffer.unshift(ch & 0xFF);
       if (buffer.length >= 4) {
         ret = xor(ret, buffer);
         buffer = [];
       }
     }

     if (buffer.length > 0) {
       ret = xor(ret, buffer);
     }

     return ret.toString(16);
   };

   return function() {
     var se = String(screen.height * screen.width);
     if (se && /\d{5,}/.test(se)) {
       se = se.toString(16);
     } else {
       se = String(Math.random() * 31242).replace('.', '').slice(0, 8);
     }
     var val = (T() + '-' + R() + '-' + UA() + '-' + se + '-' + T());
     if (val) {
       return val;
     } else {
       return (String(Math.random()) + String(Math.random()) + String(Math.random())).slice(2, 15);
     }

   };
 })();
  1. 对原生xhr对象进行了底层封装
_.xhr = function(cors) {
  // 如需要跨域资源共享
  if (cors) {
  	// 如果浏览器支持XMLHttpRequest
    if (typeof window.XMLHttpRequest !== 'undefined' && ("withCredentials" in new XMLHttpRequest())) {
      return new XMLHttpRequest();
      // 大部分浏览器已经支持cors跨域请求,但在ie8,9还是不支持,可以使用XDomainRequest实例对象
    } else if (typeof XDomainRequest !== "undefined") {
      return new XDomainRequest();
    } else {
      return null;
    }
  // 如不需要
  } else {
    if (typeof window.XMLHttpRequest !== 'undefined') {
      return new XMLHttpRequest();
    }
    // 判断浏览器是否支持ActiveX对象,通过实例化ActiveX对象的新实例来创建xhr对象
    if (window.ActiveXObject) {
      try {
        // 这个对IE7一下会不支持,需要往下兼容恶心的IE
        return new('Msxml2.XMLHTTP')
      } catch (d) {
        try {
          // 可以兼容IE7以前的版本
          return new ActiveXObject('Microsoft.XMLHTTP')
        } catch (d) {
          sd.log(d);

        }
      }
    }
  }
};
  1. 发送ajax请求的封装
 _.ajax = function(para) {
   para.timeout = para.timeout || 20000;

   para.credentials = (typeof para.credentials) === 'undefined' ? true : para.credentials;
   // 对象化data传的参数(数据)
   function getJSON(data) {
     if (!data) {
       return '';
     }
     try {
       return JSON.parse(data);
     } catch (e) {
       return {};
     }
   }
   // 是否支持跨域
   var g = _.xhr(para.cors);

   if (!g) {
     return false;
   }

   if (!para.type) {
     para.type = para.data ? 'POST' : 'GET';
   }
   // 扩展para参数
   para = _.extend({
     success: function() {},
     error: function() {}
   }, para);

   try {
     if (typeof g === 'object' && ('timeout' in g)) {
       g.timeout = para.timeout;
     } else {
       setTimeout(function() {
         g.abort();
       }, para.timeout + 500);
     }
   } catch (e) {
     try {
       setTimeout(function() {
         g.abort();
       }, para.timeout + 500);
     } catch (e2) {
       sd.log(e2);

     };
   };
   // xhr对象的请求过程状态码
   g.onreadystatechange = function() {
     try {
       if (g.readyState == 4) {
         if ((g.status >= 200 && g.status < 300) || g.status == 304) {
           para.success(getJSON(g.responseText));
         } else {
           para.error(getJSON(g.responseText), g.status);
         }
         g.onreadystatechange = null;
         g.onload = null;
       }
     } catch (e) {
       g.onreadystatechange = null;
       g.onload = null;
     };

   };
   // 定义ajax类型,地址等
   g.open(para.type, para.url, true);

   try {
     if (para.credentials) {
       g.withCredentials = true;
     }
     if (_.isObject(para.header)) {
       for (var i in para.header) {
         g.setRequestHeader(i, para.header[i]);
       }
     }
     // 定义请求头部
     if (para.data) {
       if (!para.cors) {
         g.setRequestHeader("X-Requested-With", "XMLHttpRequest");
       }
       if (para.contentType === 'application/json') {
         g.setRequestHeader("Content-type", "application/json; charset=UTF-8");
       } else {
         g.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
       }

     }
   } catch (e) {
     sd.log(e);

   };
   // 发送请求
   g.send(para.data || null);

 };
  1. extend扩展方法
  _.extend = function(obj) {
    each(slice.call(arguments, 1), function(source) {
      for (var prop in source) {
        if (source[prop] !== void 0) {
          obj[prop] = source[prop];
        }
      }
    });
    return obj;
  };

最后会在神策封装的sdk里暴露出发送数据接口的方法,比如 var methods = ['track', 'quick', 'register', 'registerPage', 'registerOnce', 'trackSignup', 'setProfile', 'setOnceProfile', 'appendProfile', 'incrementProfile', 'deleteProfile', 'unsetProfile', 'identify', 'login', 'logout', 'trackLink', 'clearAllRegister'];

  1. 然后会遍历这些放在神策暴露的对象中
  var methods = ['track', 'quick', 'register', 'registerPage', 'registerOnce', 'trackSignup', 'setProfile', 'setOnceProfile', 'appendProfile', 'incrementProfile', 'deleteProfile', 'unsetProfile', 'identify', 'login', 'logout', 'trackLink', 'clearAllRegister'];

  _.each(methods, function(method) {
    var oldFunc = sd[method];
    sd[method] = function() {
      if (!sd.readyState.getState()) {
        try {
          console.error('请先初始化神策JS SDK');
        } catch (e) {
          sd.log(e);
        }
        return;
      }
      return oldFunc.apply(sd, arguments);
    };
  });



  if (typeof window['sensorsDataAnalytic201505'] === 'string') {
    sd.setPreConfig(window[sensorsDataAnalytic201505]);
    window[sensorsDataAnalytic201505] = sd;
    window['sensorsDataAnalytic201505'] = sd;
    sd.init();
  } else if (typeof window['sensorsDataAnalytic201505'] === 'undefined') {
    window['sensorsDataAnalytic201505'] = sd;
    return sd;
  } else {
    return window['sensorsDataAnalytic201505'];
  }




} catch (err) {
  if (typeof console === 'object' && console.log) {
    try {
      console.log(err)
    } catch (e) {
      sd.log(e);

    };
  }
}

比如调用 window.sensors.quick('trackAllHeatMap') 方法后会调用sd.quick = function()这个方法

 sd.quick = function() {
   // Array.prototype.slice.call(arguments)能将具有length属性的对象(key值为数字)转成数组
   // Array.prototype.slice.call()可以理解为:改变数组的slice方法的作用域,在特定作用域中去调用slice方法,call()方法的第二个参数表示传递给slice的参数即截取数组的起始位置。
   var arg = Array.prototype.slice.call(arguments);
   var arg0 = arg[0];
   // arg1是个数组
   var arg1 = arg.slice(1);
   // 如果arg0是字符串类型并且有这个方法
   if (typeof arg0 === 'string' && commonWays[arg0]) {
     // 相当于返回commonWays.trackHeatMap这个函数执行结果,apply方法会改变函数内的this指向,指向commonWays
     return commonWays[arg0].apply(commonWays, arg1);
   } else if (typeof arg0 === 'function') {
     arg0.apply(sd, arg1);
   } else {
     sd.log('quick方法中没有这个功能' + arg[0]);
   }
 };

在quick中会调用commonWays对象中的trackHeatMap的方法

 trackHeatMap: function(target, props, callback) {
   if ((typeof target === 'object') && target.tagName) {
     var tagName = target.tagName.toLowerCase();
     var parent_ele = target.parentNode.tagName.toLowerCase();
     if (tagName !== 'button' && tagName !== 'a' && parent_ele !== 'a' && parent_ele !== 'button' && tagName !== 'input' && tagName !== 'textarea' && !_.hasAttribute(target, 'data-sensors-click')) {
       heatmap.start(null, target, tagName, props, callback);
     }
   }
 },

在commonWays.trackHeatMap方法中调用了heatmap.start方法

start: function(ev, target, tagName, customProps, callback) {
  var userCustomProps = _.isObject(customProps) ? customProps : {};
  var userCallback = _.isFunction(callback) ? callback : _.isFunction(customProps) ? customProps : undefined;
  if (sd.para.heatmap && sd.para.heatmap.collect_element && !sd.para.heatmap.collect_element(target)) {
    return false;
  }

  var selector = this.getDomSelector(target);
  var prop = _.getEleInfo({
    target: target
  });

  prop.$element_selector = selector ? selector : '';
  if (sd.para.heatmap && sd.para.heatmap.custom_property) {
    var customP = sd.para.heatmap.custom_property(target);
    if (_.isObject(customP)) {
      prop = _.extend(prop, customP);
    }
  }
  prop = _.extend(prop, userCustomProps);
  // 在最后会判断点击事件是在和标签上发生的,来根据标签来判断发生的发送数据类型
  if (tagName === 'a' && sd.para.heatmap && sd.para.heatmap.isTrackLink === true) {
    _.trackLink({
      event: ev,
      target: target
    }, '$WebClick', prop);
  } else {
    sd.track('$WebClick', prop, userCallback);
  }

},
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
神策数据是一家专注于数据分析数据挖掘领域的公司,为各行业提供数据分析解决方案。他们布的《神策数据 十大数据分析模型详解 pdf》是一本介绍十种常用的数据分析模型的电子书。 这本电子书详细介绍了常见的数据分析模型,包括但不限于:线性回归模型、逻辑回归模型、决策树模型、聚类分析模型、关联规则模型等。它不仅解释了每种模型的原理和算法,还提供了实际案例和应用场景。 线性回归模型是一种用来预测数值型变量的模型,通过分析自变量和因变量的线性关系来进行预测。逻辑回归模型则是用来预测二分类或多分类问题,例如判断一个顾客是否会购买某个产品。决策树模型是一种用来做决策的模型,通过设置多个决策节点和叶节点来进行有序的判断。 聚类分析模型用于将对象按照相似性进行分组,一般用于市场细分分析。关联规则模型则是探索事物之间的关联关系,例如购物篮分析就是一种常见的关联规则挖掘应用。 这本电子书的目的是帮助读者了解各种数据分析模型,并且学会在实际应用中选择合适的模型。通过阅读这本电子书,读者可以学习到如何进行数据分析,如何选择合适的模型,以及如何解读和应用模型的结果。 总之,《神策数据 十大数据分析模型详解 pdf》是一本实用的电子书,对于想要学习和应用数据分析模型的人来说是一份很好的参考资料。无论是数据分析师、市场营销人员还是对数据分析感兴趣的人,都可以从中获得很多知识和实用技巧。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值