preface

The buried point is to collect information on a particular process within an application to track application usage and then to further optimize the product or provide data support for operations. So how can we elegantly bury points in the application compiled by the Taro framework?

Outline of the content

  1. What buried point data needs to be collected.
  2. Add global buried points through quick application plug-ins.
  3. Add global buried points by way of lifecycle injection.
  4. Handle page switchingrouter.getState()The value is incorrect.

What buried point data needs to be collected

What buried point data need to be collected? I believe that this content does not need to say more, a lot of mature Web side without trace buried point SDK has a description, and this kind of article has been a lot of.

This is how to get the page route, or page path, which is the most important part of buried data. This chapter describes how to collect the behavior data of users entering and leaving the page, opening and leaving the application. (The user behavior data, i.e. click classes, swipe classes, etc., will be explained in a later chapter, because there are many stories to be told.)

Each entry or start event will generate a new sessionId, and the current page route will be reported to the system. The system will calculate the time of leaving and entering. It can also count how long the current page user stays.

Statistics application startup and exit code:

// SRC /app.ux Start the file in the root directory of the application

onShow() {
    let arg = {
        PAGE_NAME: router.getState().name, // Access the page path
        sessionId, // The session ID that distinguishes buried data is mainly used for statistics
    }
    // Application startup buried point reported
}

onHide(){
    let arg = {
        PAGE_NAME: router.getState().name, // Access the page path
        sessionId, // The session ID that distinguishes buried data is mainly used for statistics
    }
    // Report the application leaving the buried point
}
Copy the code

Statistics page entry and exit code:

// SRC /pages/xxxpage

onShow() {
    let arg = {
        PAGE_NAME: router.getState().name, // Access the page path
        sessionId, // The session ID that distinguishes buried data is mainly used for statistics
    }
    // The page enters the buried point and reports
}

onHide(){
     let arg = {
        PAGE_NAME: router.getState().name, // Access the page path
        sessionId, // The session ID that distinguishes buried data is mainly used for statistics
    }
    // The page is reported when it leaves the buried point
}
Copy the code

Add global buried points through quick application plug-ins

In a practical scenario, it would be impossible to add onShow and onHide lifecyclone to every page file, which would create a lot of redundant code and be difficult to maintain. So we searched through the documentation and found that the Fast App Alliance has provided an easy way to fast app plug-ins.

// src/plugins/utm.js

import router from '@system.router'
import { getStorage, setStorage } from '.. /utils/storage'

const Utm = {
  // Install entry
  install(VmClass) {
    // Page life cycle
    VmClass.mixin({
      async onShow() {
        let sessionId = `The ${Math.floor(100000 * Math.random())}The ${Date.now()}`
        await setStorage('sessionId', sessionId) // Number of the session that opens the application once
        let arg = {
          PAGE_NAME: router.getState().name, // Access the page path
          sessionId, // The session ID that distinguishes buried data is mainly used for statistics
        }
        // The page enters the buried point and reports
      },
      async onHide() {
        let sessionId = (await getStorage('sessionId')) || ' ' // Number of the session that opens the application once
        let arg = {
          PAGE_NAME: router.getState().name, // Access the page path
          sessionId, // The session ID that distinguishes buried data is mainly used for statistics
        }
        // The page is reported when it leaves the buried point}})// Application lifecycle
    VmClass.mixinApp({
      async onShow() {
        let sessionId = `The ${Math.floor(100000 * Math.random())}The ${Date.now()}`
        await setStorage('sessionId', sessionId) // Number of the session that opens the application once
        let arg = {
          PAGE_NAME: router.getState().name, // Access the page path
          sessionId, // The session ID that distinguishes buried data is mainly used for statistics
        }
        // Application startup buried point reported
      },
      async onHide() {
        let sessionId = (await getStorage('sessionId')) || ' ' // Number of the session that opens the application once
        let arg = {
          PAGE_NAME: router.getState().name, // Access the page path
          sessionId, // The session ID that distinguishes buried data is mainly used for statistics
        }
        // Report the application leaving the buried point}}})},module.exports = Utm
Copy the code
// SRC /app.js root startup file to import the plugin

export default {
  plugins: [require('./plugins/utm')]},Copy the code

Attention: key! The point! The point! Huawei Quick Application does not support plug-in writing. (Because of this, I also consulted huawei Express app developers and they said they didn’t think it was necessary to implement this feature. Ah, big guy is bull. So we’re gonna have to figure something out.

Add global buried points by way of lifecycle injection

Since Huawei does not support the form of plug-ins, and we do not want to add a section of life cycle code to every page, so we change the idea, add the life cycle method to the fast application global attribute, and then automatically inject into every page logic.

// src/app.js
// Note that the 'quickappPageLifecycle' property here is custom, the implementation of which is explained in the previous chapter
global.quickappPageLifecycle = {
  onShow: async() = > {let sessionId = `The ${Math.floor(100000 * Math.random())}The ${Date.now()}`
    await setStorage('sessionId', sessionId) // Number of the session that opens the application once
    let arg = {
      PAGE_NAME: router.getState().name, // Access the page path
      sessionId, // The session ID that distinguishes buried data is mainly used for statistics
    }
    // The page enters the buried point and reports
  },
  onHide: async() = > {let sessionId = (await getStorage('sessionId')) || ' ' // Number of the session that opens the application once
    let arg = {
      PAGE_NAME: router.getState().name, // Access the page path
      sessionId, // The session ID that distinguishes buried data is mainly used for statistics
    }
    // The page is reported when it leaves the buried point}},Copy the code
// dist/quickapp/src/pages/xxx.jx
// The main code after the transformation of Taro's lifecycle is as follows;

var quickappPageLifecycle = global.quickappPageLifecycle || {} // The global injection lifecycle is obtained here

exports.default = Object.assign(
  require('.. /.. /npm/@tarojs/taro-quickapp/index.js').default.createComponent(
    Container,
    '/pages/xxx'
  ),
  quickappPageLifecycle
) // Finally derived are Taro's lifecycle and the lifecycle method we injected into the interception
Copy the code

Handle page switchingrouter.getState()The value is incorrect

The logic principle of the above code program is no problem, but after practice, it is found that there are some problems in obtaining the route of the current page through router.getState().

The main scenario is: When pageA -> pageB, then we want to count the pageA leaves the onHide cycle and reports the pageA page route. However, the actual route to the page obtained from the router.getState() API in onHide is pageB.

For this phenomenon, in fact, it is easy to understand, is a small flaw in the underlying design of fast application. If the onHide life cycle has not been triggered but the route to the next page has been added to the routing stack, the route to the current page obtained through the API must be the route to the next page. So we can’t change the bottom, and it’s probably not easy to change. I also consulted the quick application specialized in the development of this logic, he thinks I use this way to achieve it, that is probably not easy to change.

The implementation is as follows:

import router from '@system.router'
import { getStorage, setStorage } from '.. /utils/storage'

export default {
  async onShow() {
    const page = router.getState()
    let sessionId = `The ${Math.floor(100000 * Math.random())}The ${Date.now()}`
    await setStorage('sessionId', sessionId) // Number of the session that opens the application once
    await setStorage('current_pageName', page.name) // Enter the page to archive the current page route
    let arg = {
      PAGE_NAME: page.name, // Access the page path
      sessionId, // The session ID that distinguishes buried data is mainly used for statistics
    }
    // The page enters the buried point and reports
  },
  async onHide() {
    let sessionId = (await getStorage('sessionId')) || ' ' // Number of the session that opens the application once
    let pageName = (await getStorage('current_pageName')) || ' ' // Get the archived current page route
    let arg = {
      PAGE_NAME: pageName, // Access the page path
      sessionId, // The session ID that distinguishes buried data is mainly used for statistics
    }
    // The page is reported when it leaves the buried point}},Copy the code

The last

Through the above series of buried data, we have been able to analyze the target user’s page-level behavior in the current application. Obviously, these data are far from supporting our operational requirements. How to monitor users’ clicking, sliding and other operations without trace in the quick application will be developed in the following chapters.

If it helps, give it a like!