Every company that wants to grow its users needs to collect and analyze data about their actions, so burying them is essential. For the front-end career development, the traditional manual burying point, is undoubtedly tedious and boring things, can simplify to simplify.

One, manual burying point

Manual burying is to add a code to report the burying point at each place where it is needed. It affects the reading experience of the code, and the scattered buried code is not convenient to manage.

Take page PV as an example, we reported PV in each page previously:

// src/manual/home/index.tsx

import tracking from "./tracking";

// pageSn is the unique identifier of the page in the buried point system agreed by the front end and the product. For example, the identifier of the front page of this project is the number 11664
const pageSn = 11111;

export default() = > {// useDidShow is an Taro proprietary Hook, equivalent to the native componentDidShow lifecycle, which is called when the page is displayed.
  useDidShow(() = > {
    // sendPv buried points through unified encapsulation sendPv method
    sendPv(pageSn);
  });
  return <View>Manual burying page</View>;
};
Copy the code

Two, automatic burying point

Automatic burying point can be divided into automatic burying point and semi-automatic burying point. Fully automatic burying is to bury all points, whether needed or not. The front end must be happy “don’t look for me after burying some products”, but the data students will cry chiri.

For example, Tencent and the Taro team jointly launched Tencent Wowu automation points, which are super easy to access. For example, set proxyPage to true to report browse, Leave, share, and other events on all pages. Set autoTrack to true to automatically report tap, change, Longpress, and Confirm events of all elements.

In terms of data volume and validity, “full burying” is equal to “no burying”, because “full burying” on the one hand has a high requirement for data storage, on the other hand, it will bring a lot of work to our classmates who are responsible for data cleaning.

So next, or to seek balance, focus on semi-automatic buried point.

1. Page exposure (PV)

Page exposure (PV), the ideal reporting method is:

  • In a unified place (e.gtrackingConf.ts), configure the identifier for each page to be buried (i.epageSn)
  • After the page is displayed, it automatically determines whether to report (whether to report intrackingConf.tsConfiguration file), if you want to report directly.

The specific implementation

(1) Uniformly configure the buried field. PageSn represents the identifier of the page in the buried system

// trackingConf.ts
export default {
  "auto/home/index": {
    pageSn: 11111,}};Copy the code

Of course, if your business allows thirty-seven twenty-one, reported all pages PV (with path to let the product screening), that (1) this step can be saved, directly look at (2), this way can be called “PV automatic buried point”.

(2) Package usePv hook. When the page is displayed, obtain the pageSn of the current page, judge whether to bury PV or not, and send PV if necessary

// usePv.ts

// Get the current page path using Taro's getCurrentInstance
export const getPath = () = > {
  constpath = Taro.getCurrentInstance().router? .path ||"";
  // Remove the leading /, such as '/auto/home/index' to 'auto/home/index'.
  return path.match(/ ^ \ / * /)? path.replace(/ ^ \ / * /."") : path;
};

// Get the pageSn of the current page, determine whether to bury PV, if yes, send PV
GetExtra supports additional arguments
const usePv = ({ getExtra, }: { getExtra? : () = >any;
} = {}) = > {
  // Page exposure
  useDidShow(() = > {
    const currentPath = getPath();
    // Get pageSn from trackingConf
    constpageSn = trackingConf[currentPath]? .pageSn;console.log("Automatically get pageSn", currentPath, pageSn);
    if (pageSn) {
      constextra = getExtra? . ();// sendPv buried points through unified encapsulation sendPv methodextra ? sendPv(pageSn, extra) : sendPv(pageSn); }}); };Copy the code

(3) Then wrap the page component WrapPage, using the usePv() above:

import React from "react";
import { View } from "@tarojs/components";
import usePv from "./usePv";

function WrapPage(Comp) {
  return function MyPage(props) {
    usePv();
    return (
      <View>
        <Comp {. props} / >
      </View>
    );
  };
}

export default WrapPage;
Copy the code

(4) Finally, in all page components, package a layer of WrapPage to achieve “all pages on demand burying point” :

// src/auto/home/index.tsx

const Index = WrapPage(() = > {
  return <View>Automatic buried page</View>;
});
Copy the code

In addition to wrapping a new page with WrapPage, you only need to add the pageSn of the page in the trackingconf.ts of step (1).

For questions

Curious babies might want to ask:

(1) WrapPage encapsulates usePv(), how should we support reporting custom fields?

For example, the product wants the SRC /auto/home/index. TSX page to report pv, in addition to reporting the current page URL query parameter params.

Instead of wrapping the page with WrapPage, call the usePv function when you get params:

// src/auto/home/index.tsx

const Index = () = > {
  usePv({
    getExtra: () = > {
      constparams = Taro.getCurrentInstance().router? .params;return{ params }; }});return <View>Automatic buried page</View>;
});
Copy the code

(2) here each Page component, have to use WrapPage package, or have an invasion of the business, native small program can rewrite Page, in the Page directly usePv(). The Taro project should be able to do the same, to achieve zero business intrusion, right?

In the Taro project, it is possible and possible to uniformly intercept native pages in the App like native applet, but in this case, “some pages need to calculate additional parameters and report” is not easy to solve.

2. Page sharing

There are two kinds of sharing in wechat mini programs:

  • Share with friends:useShareAppMessage.
  • Share on moments:useShareTimeline. Applet base library v2.11.3 start support, currently only available on the Android platform.

The specific implementation

Take useShareAppMessage as an example (the same is true for useShareTimeline) :

(1) Add the identification field eleSn (and additional parameters) of sharing buried point in trackingconf. ts unified configuration file.

// trackingConf.ts
export default {
  "auto/home/index": {
    pageSn: 11111.shareMessage: { eleSn: 2222.destination: 0 }, // Add shareMessage containing the eleSn of the shared friend and the extra business parameter destination}};Copy the code

(2) Encapsulate the useShareAppMessage method, and globally replace the place where businesses call Taro. UseShareAppMessage with the useShareAppMessage.

// Share it with your friends
export const useShareAppMessage = (
  callback: (payload: ShareAppMessageObject) => ShareAppMessageReturn
) = > {
  let newCallback = (payload: ShareAppMessageObject) = > {
    const result = callback(payload)

    const currentPath = getPath();	// getPath To obtain the current page path, see getPath in 1. Page Exposure (PV)
    // Get pageSn, shareMessage, etc from trackingConf
    const { pageSn, shareMessage } = trackingConf[currentPath]
    const{ eleSn, ... extra } = shareMessage || {}let page_el_sn = eleSn
    const { imageUrl: image_url, path: share_url } = result
    const { from: from_ele } = payload

    const reportInfo = {
      from_ele,
      share_to: 'friend'.// 'friend' means to share with friendsimage_url, share_url, ... extra }console.log('... useShareAppMessage tracking', { pageSn, page_el_sn, reportInfo })
    sendImpr(pageSn, page_el_sn, reportInfo) // Can encapsulate sendImpr method, send share buried point information
    return result
  }
  Taro.useShareAppMessage(newCallback)
}
Copy the code

In this way, if a page needs to add a buried point for sharing friends, add the eleSn of shareMessage in Trackingconf. ts and useShareTimeline.

For questions

Curious kids may want to ask: if the page needs to be added to share friends/circle of friends, can 0 be configured (i.e. the above trackingconf.ts file is not modified)?

Similar to the previous article “PV automatic burying point”, as long as the product and the agreement on the way to retrieve data can also be, such as the author and the product agreement:

Each page shares friends/circle of friends, eleSn is 444444, and the product determines which page it is by pageSn, and determines which page it is to share friends/circle of friends by share_to. For the scene of sharing friends, Then use from_ele to determine whether to share through the upper right corner or click the button in the page.

This page sharing can also be fully automatic buried point.

3. Element burial point

The investigation of the automatic burying point of elements has encountered resistance and has not yet landed. The following is mainly about the problems encountered in different ideas, and good suggestions are welcome to communicate in the comment section.

Our element burying point, high frequency has exposure, click events, low frequency has rolling, hovering and other events.

The method of manual burying point is to manually execute sendImpr to report burying point (with page unique identifier pageSn and element unique identifier eleSn) when the element specified event is triggered.

Can this link save some trouble? No intrusion on the business, the general approach is:

Add a hook to Component to trigger the event -> determine whether to report the buried point -> report the event if the condition is met

The problem is divided into two parts:

(1) Intercepting element event callbacks

You can intercept and iterate over options.methods received by the Component applet and, if it’s a custom function, determine when the function is called whether the type of the first argument (let’s say named e) is equal to tap, etc. At this time, we can decide whether to meet the conditions of burying point reporting according to e and other information.

Native applet implementation, roughly as follows:

// App.js
App({
  onLaunch() {
    let old = Component
    Component = function(config) {
      // Intercepts the config passed by the service
      const newConf = proxyConfig(config)
      old(newConf)
    }
  }
})

const proxyConfig = function(conf) {
  const methods = conf.methods
  // Get custom methods (exclude some unburied methods as needed)
  let diyMethods =  Object.entries(methods).filter(function (method) {
    let methodName = method[0]
    return! ["onLoad"."onShow"."onReady"."onHide"."onUnload"."onPullDownRefresh"."onReachBottom"."onPageScroll"."onShareAppMessage"."onResize"."onTabItemTap"."observer",
    ].includes(methodName);
  })
  diyMethods.forEach(function(method) {
    const [methodName, methodFn] = method
    // Modify methods in conf
    methods[methodName] = function (. args) {
      const e = args && args[0]
      if (e && e.type === 'tap') {
        console.log('... tapping', methodName, args) // When the click event is triggered, the buried point is reported as required
      }
      methodFn.call(this. args) } });// Returns the modified conf
  return conf
}
Copy the code

In the Taro project, you can’t use Component directly in Component code, but you can do the same thing in a roundabout way. For example:

// myProxy.js
module.exports = (function() {
  let OriginPage = Page
  let OriginComponent = Component

  return (Page = function(conf) {
    conf.forEach(function(e) {
      let [methodName, methodFn] = e

      if (typeof methodFn === 'function') {
        conf[methodName] = function(. args) {
          // Do what you want to do, such as rewriting the conf, etc
          methodFn.call(this. args) } } })return OriginPage(conf)
  })(
    (Component = function(conf) {
      const methods = conf.methods
      methods.forEach(function(e) {
        // Do what you want to do, such as rewriting the conf, etc
      })

      OriginComponent(conf)
    })
  )
})()
Copy the code

Add myproxy.js directly to app.tsx

(2) How to automatically generate unique identifiers of elements

At present, elements are uniquely identified by eleSn applied in the buried point system. If automatic identification is required, it can be subdivided into:

  • XPath: It works fine in PC/Mobile, but XPath to get nodes directly/get nodes by XPath is not supported in applets.Can wechat applet support DOM element acquisition through XPath?
  • Automatic access toComponent method nameIn the Taro project, methods are propped up and the name of the method is displayed after the event is triggeredeh.
  • ASTAnalyze the source code to identify elements by analyzing the page name, method name and corresponding annotation of the method: The Taro project can only use this method visually, but the cost is high, and “whether the stock data can still be used after the code is constantly iterated” is also a problem, so the author did not try.

Third, summary

This article summarizes the idea of wechat small program (Taro) from manual burying point to automatic burying point. And according to the page buried point (PV, share) and element buried point, analysis of the implementation method:

  • Page pv:
    • encapsulationusePv, read pageSn from the configuration file based on the current page path
    • Encapsulating page componentsWrapPagecallusePv()
  • Share friends or circles of friends: Customize the useShareAppMessage and useShareTimeline. Read the pageSn and share eleSn from the configuration file according to the path of the current page. Then obtain the input parameters and report them
  • Element burying: Provides the idea of rewriting Component methods to intercept event callbacks, but is not suitable for automatic burying because element unique identifiers cannot be obtained automatically.