大数据埋点sdk封装(一)


一、初始化sdk配置

    window._jt_ = window.jimoTracker = new Tracker({
      env_name: process.env.APP_ENV || 'test', // 环境名称 dev,test,test2,test3,uat,prod
      node_env: process.env.NODE_ENV || 'production', // 环境变量 production,development
      enableBodyClick: true, // 开启事件委托
      enableBlockExposure: true, // 开启模块曝光
      enableHideElementExposure: true, // 开启隐藏元素曝光
    });

二、初始化主对象

this._mainObj = {
      env_name: options.env_name, // dev,test,test2,test3,uat,prod
      device_id: '', // 设备浏览器id
      open_id: '',
      union_id: '',
      user_id: '', // 企微后台用户userId
      main_id: '', // 我们后台区别用户
      user_type: '', // 用户类型:企业员工、企业客户、潜在客户、游客
      identity: '', // 身份类型 非同事,同事,员工自己
      corp_id: '',
      staff_id: '',
      sub_session_id: '', // 隐藏后重新显示 会话子id
      event_type: '', // 事件类型
      page_desc: '', // 当前页面路径
      block_desc: '', // 模块
      button_desc: '', // button
      parameters: {}, // 附加参数
    };

三、jimo-sdk传入数据

    _jt_.setData(obj); // jimo-sdk传入数据
  public setData(obj: MainObj) {
      this._mainObj = { ...this._mainObj, ...obj, parameters: { ...this._mainObj.parameters, ...obj.parameters } };
  }

四、冷启动发送埋点

    _jt_.coldStart(); // 执行冷启动
  public coldStart() {
      const start_source = this._mainObj.start_source;
      if (start_source) {
        this.sendTracker({
          event_type: 'cold_start',
        });
      }
  }

五、淘宝SPM超级定位模型

六、手动埋点

_jt_.sendTracker({
      event_type: 'page_exp',
      block_desc: '',
      button_desc: '',
      parameters: { objId },
    });
	public sendTracker(data: Data) {
    const trackData = { ...this._mainObj, ...data, parameters: { ...this._mainObj.parameters, ...data.parameters } };
     window.trackInfo(trackData);
  }

七、属性埋点,body添加事件委托监听

data-jt-sender={JSON.stringify({
        event_type: 'popup_window',
        block_desc: 'tel_page',
        button_desc: 'enter_btn',
        parameters: { objId },
})}
document.body.addEventListener('click', (e: any) => {
    let target = e.target;
    const spmObj: any = {};
    while (target && target.dataset) {
      target.dataset.jtSpmb && (spmObj.page_desc = target.dataset.jtSpmb);
      target.dataset.jtSpmc && (spmObj.block_desc = target.dataset.jtSpmc);
      target.dataset.jtSpmd && (spmObj.button_desc = target.dataset.jtSpmd);
      target.dataset.jtSender && (spmObj.jtSender = target.dataset.jtSender);
      // 向上冒泡
      target = target.parentNode;
    }
    if (spmObj.jtSender) {
      const data = JSON.parse(spmObj.jtSender);
      // 优先使用业务参数data,其次spmObj
      const newSpmObj = {
        page_desc: spmObj.page_desc,
        block_desc: spmObj.block_desc,
        button_desc: spmObj.button_desc,
      };
      ctx.sendTracker({ ...newSpmObj, ...data });
    }
  });

八、模块曝光

{children}
/** * 建立模块曝光观察者 */ ctx._blockExposureObserver = new IntersectionObserver( (changes) => { changes.forEach((change: any) => { if (change.intersectionRatio < 0.5) return; ctx.sendTracker(handleDomSpmCache(ctx, change)); }); }, { threshold: 0.5 } ); /** * 刷新模块曝光 */ export function refreshBlockExposure(this: any) { clearTimeout(this._blockExposureTimer); // 防抖 this._blockExposureTimer = setTimeout(() => { this._blockExposureObserver.disconnect(); const doms = document.querySelectorAll('[data-jt-block-exposure]'); doms.forEach((item) => { this._blockExposureObserver.observe(item); }); }, 500); } /** * 查找spm缓存信息 */ tracker._domSpmCache = new WeakMap(); // dom的spm位置信息缓存,dom移除或切换页面自动清除 const handleDomSpmCache = (ctx, change) => { let target = change.target; let spmObj: any = {}; const alreadyDatasetObj = ctx._domSpmCache.get(change.target); if (!alreadyDatasetObj) { while (target && target.dataset) { target.dataset.jtSpmb && (spmObj.page_desc = target.dataset.jtSpmb); target.dataset.jtSpmc && (spmObj.block_desc = target.dataset.jtSpmc); target.dataset.jtSpmd && (spmObj.button_desc = target.dataset.jtSpmd); // 向上冒泡 target = target.parentNode; } ctx._domSpmCache.set(change.target, spmObj); } else { spmObj = alreadyDatasetObj; } const data = JSON.parse(change.target.dataset.jtBlockExposure); // 优先使用业务参数data,其次spmObj return { ...spmObj, ...data }; };

九、隐藏元素曝光

/** * 建立隐藏元素曝光观察者 */ ctx._hideElementExposureObserver = new IntersectionObserver((changes) => { changes.forEach((change: any) => { if (change.intersectionRatio <= 0) return; ctx.sendTracker(handleDomSpmCache(ctx, change)); }); }); /** * 刷新隐藏元素曝光 */ if (!this._options.enableHideElementExposure) return; clearTimeout(this._hideElementExposureTimer); // 防抖 this._hideElementExposureTimer = setTimeout(() => { this._hideElementExposureObserver.disconnect(); const doms = document.querySelectorAll('[data-jt-hide-element-exposure]'); doms.forEach((item) => { this._hideElementExposureObserver.observe(item); }); }, 200);

十、react通用埋点组件

{'被包裹的模块'}
/**
 * Tracker组件
 */
export default function Tracker({ type = 'click', tagName = 'div', ...args }: TrackerProps) {
  const newProps = {
    ...args,
    tagName,
    data: { ...args.data, type },
  };
  return handleTypeFn[type](newProps);
}
/**
 * type策略类型(放组件外面减少组件编译后代码量)
 */
const handleTypeFn = {
  // 点击埋点
  click: ({ data, children, tagName, className, display, ...args }: TrackerProps) => {
    return React.createElement(
      tagName,
      {
        'data-jt-sender': JSON.stringify(data),
        className: handleClassName(className, display),
        ...args,
      },
      children
    );
  },
  // 模块曝光
  block: ({ data, children, tagName, className, display, ...args }: TrackerProps) => {
    return React.createElement(
      tagName,
      {
        'data-jt-block-exposure': JSON.stringify(data),
        ref: _jt_.refreshBlockExposure,
        className: handleClassName(className, display),
        ...args,
      },
      children
    );
  },
};