天天看點

小程式如何統計來源資訊?

攜手創作,共同成長!這是我參與「掘金日新計劃 · 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);      

繼續閱讀