现在市面上已经有很多成熟全局埋点的分析系统支持,比如腾讯移动端分析-小程序分析
若让我们自己封装一个全局浏览记录上报呢?
小程序的页面由Page({})构成,页面的生命周期有onLoad,每次页面加载会调用onLoad。
要做浏览记录的上报,可以利用onLoad做文章。
onLoad() {
pageBrowse() // 上报浏览记录方法 --- 后面再讲这个方法怎么写,可以根据业务需求变动
}
但是如果在每个页面的onLoad都调用上报方法,未免太低效。若有50个页面,便要写50次pageBrowse(),很显然不符合程序员“避免做重复工作”的思想。
我们可以重写小程序的Page方法,一次封装,处处调用。
const MyPage= function (config) {
config.onLoad = function (options) { // 页面创建时执行
pageBrowse() // 浏览记录上报
}
return Page(config)
}
export default MyPage
MyPage重写了小程序的Page,在onLoad函数里调用了浏览记录上报方法。需要做页面浏览上报的,可以通过import我们自己封装的Page来覆盖原生的Page,达到浏览记录上报的目的。
// pageA
import Page from 'MyPage'
Page({
onLoad() {}
})
// pageB
import Page from 'MyPage'
Page({
onLoad() {}
})
可能有人会说,那这玩意不也是我有50个页面要import50次?先别急看完下面的操作。你就知道import50次的代价比单独在页面的onLoad里做处理真的高效很多。几乎所有的全局操作我们都可以放到这个自己封装的MyPage里面。要多感人有多感人。
根据各自业务的不同,浏览记录上报的参数也有所不同。以下举个例子。
function pageBrowse() { // 页面浏览记录上报
let pages = getCurrentPages() // 获取页面信息栈
let currentPage = pages[pages.length - 1] // 获取当前访问页面的信息
let prevPage = pages[pages.length - 2] // 获取上一个页面信息栈
return HTTP.get('project/api/page/browse', {
appId: 'wx23451e1w11521', // 代表那个小程序
openId: wx.getStorageSync('openId'), // 用户id
referer: currentPage.route + getQueryString(currentPage.options), // 当前浏览的页面路径
_pageName: currentPage.data.title, // 当前浏览的页面名称
_referer: prevPage?(prevPage.route + getQueryString(prevPage.options)):'', // 上级页面路径
_referer_name: prevPage?prevPage.data.title:'', // 上级页面名称
})
}
这里是一个简单的浏览上报,小程序appid + 用户身份openId + 当前页面路径 + 当前页面标题 + 上级页面路径 + 上级页面标题
做过小程序的都知道,页面标题是无法获取的。这就是小程序的硬伤,包括世面上很多埋点分析系统也做不到这点,当然我们也可以不上报页面标题。但是业务需要呢?
这就需要我们去维护一套页面路径与页面标题的映射文件
// pageConfig.js
//由于官方没有提供页面标题的获取方式,不再支持全自动获取,为确保 page_title 获取,需要开发维护页面的配置列表
export default [
{
title: '首页',
path: 'pages/Home/Home',
},
{
title: '购物车',
path: 'pages/ShopCart/ShopCart',
},
// ........
]
再通过全局封装的MyPage将页面的标题set到页面的data里。
const MyPage= function (config) {
const { onLoad } = config
config.onLoad = function (options) { // 页面创建时执行
if (typeof onLoad === 'function') {
this.setData({
title: PageUtil.getPageTitleByPath(PageUtil.getCurrentPagePath())
})
onLoad.call(this, options)
}
WGTRACK.pageBrowse() // 浏览记录上报
}
return Page(config)
}
export default MyPage
需要特别提到的是,小程序有个场景带参,不会直接set到onLoad的options里面,在这里可以做个全局的优化。以后再也不会遇到场景参数通过options.xxx拿不到的情况了。
再次赘述一下,重写Page除了可以优化场景带参,还可以做更多的操作,例如①用户静默授权;②版本更新提示;③一些用户公共信息的操作等等。
const MyPage= function (config) {
const { onLoad } = config
config.onLoad = function (options) { // 页面创建时执行
if (typeof onLoad === 'function') {
this.setData({
title: PageUtil.getPageTitleByPath(PageUtil.getCurrentPagePath())
})
//添加公共场景值取参方法
if (options.scene) { //如果获取到场景值,则将场景值取出赋值给自定义参数
let scene = decodeURIComponent(options.scene).split('&')
for (let i in scene) {
let item = scene[i].split('=')
let itemKey = item[0]
let itemVal = item[1]
options[itemKey] = itemVal
}
}
onLoad.call(this, options)
}
WGTRACK.pageBrowse() // 浏览记录上报
}
return Page(config)
}
export default MyPage