天天看点

小程序如何统计来源信息?

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第31天,​​点击查看活动详情​​。

背景

从用户认知的角度看,广义的小程序启动可以分为两种情况,一种是冷启动,一种是热启动。
  • 冷启动:如果用户首次打开,或小程序销毁后被用户再次打开,此时小程序需要重新加载启动,即冷启动。
  • 热启动:如果用户已经打开过某小程序,然后在一定时间内再次打开该小程序,此时小程序并未被销毁,只是从后台状态进入前台状态,这个过程就是热启动。

统计小程序来源信息并不容易,为什么?

  1. 小程序初次启动时,会调用App的onLaunch生命周期。里面有来源信息。
  2. 小程序有热启动和冷启动机制。冷启动时,并不会调用onLaunch这一生命周期,所以不能依赖onLoad做来源统计。
  3. 小程序每个页面都有onLoad生命周期,但是无论内部跳转、还是外部跳转,都会执行这一生命周期,我们无法区分,所以不能依赖onLoad做来源统计。

这样看,统计来源似乎是不可能的事情。

但是,如果你阅读过这篇文章​​《如何全局重写小程序 Page函数 wx对象?》​​​和这篇文章​​《小程序安全指南:如何禁止外部直接跳转到小程序某页面》​​,也许你能自己想到最佳方案。

方案

区分「内部跳转」还是「外部跳转」

先用一种方式,区分「内部跳转」还是「外部跳转」。

具体方案:全局改写内部跳转API(​

​wx.redirectTo​

​​、​

​wx.navigateTo​

​​),每次内部跳转时,都带个​

​特殊参数​

​​,在onLoad中,判断有没有这个​

​特殊参数​

​,就知道是来自内部还是外部了。

来源信息如何获得?

  1. 通过​​wx.getLaunchOptionsSync​​可以获得。
  2. 可以在​​App.onShow​​时获得。但这种方式需要把来源信息先保存到某个全局变量中(如app.globalData.xxx),才能方便的使用。

主要来源信息有什么?

  1. scene场景值,这是小程序官方定义的来源场景,还是比较全面的。参考​​场景值列表​​​,​​场景值指南​​。
  2. referrerInfo.appId。来源的公众号APPID或者小程序APPID。

在onLoad中统计来源

具体代码

全局修改跳转API增加特殊参数

function addFromInner(url) {
  const app = getApp();
  const symbol = url.includes('?') ? '&' : '?';
  return `${url}${symbol}fromInner=1`;
}

export function redirectToProxy(redirectTo) {
  return function (object) {
    return redirectTo({
      ...object,
      url: addFromInner(object.url),
    });
  };
}

function wxProxy(wx) {
  const newWx = { ...wx };
  newWx.navigateTo = redirectToProxy(wx.navigateTo);
  newWx.redirectTo = redirectToProxy(wx.redirectTo);
  return newWx;
}

wx = wxProxy(wx);      

全局修改onLoad自动上报外部跳转

function onLoadProxy(onLoad) {
  return function (options) {
    // 如果没有参数fromInner,表明是外部跳转来的,就上报一次来源
    if (!options.fromInner) {
      const launchOptions = wx.getLaunchOptionsSync();
      // 这里上报launchOptions
      // 可以通过this.route 获得当前页面的路由信息,一并上报
    }
    if (onLoad) {
      return onLoad.call(this, options);
    }
  };
}

const PageProxy = (Page) => function (options) {
  const newOptions = {
    ...options,
    onLoad: onLoadProxy(options.onLoad),
  };
  Page(newOptions);
};

Page = PageProxy(Page);      

继续阅读