preface

Behavior traceable system first appeared in the insurance sales industry, and its definition and scope refers to that insurance institutions record and save the transaction behaviors of selling insurance products on self-operated network platforms by means of sales page management and sales process records, so that they can be examined. In this way, the risk of online sales model and its problems can be reduced and the corresponding factors can be found quickly after the problems occur.

The behavior traceback system provides us with effective pictures, audio or video related effective materials for investigation and inspection. By record user behavior sequence, using the session replay restore user operation real scene, analysis the core process and presents the user behavior preference, based on user behavior to optimize the user experience, according to user’s operation path know the whole process of the exception occurs, r&d personnel positioning to deal with abnormal issues, realized through the behavior analysis of abnormal tracking way.

We will understand the traceback system, its principle and application mode through the following contents.

The system design

Behavioral traceability analysis platform:

1. Data dashboard:

The data dashboard is used to collect statistics on the number of data submitted by integrated terminals, the number of data queried and archived by operators and administrators, and the geographical distribution of submitted data. The above indicators can be used to monitor and analyze whether sampling/archiving meets the standard, the active situation of system use and the regional distribution of system use, so as to facilitate further targeted investigation and analysis.

2. Behavior analysis:

The behavior analysis module mainly designs three sub-modules: key behavior analysis, common behavior analysis and other behavior analysis to manage respectively. It is recommended that operations that are strongly associated with the business, such as order and payment, contract preview, etc., be classified as key actions by business code. It is recommended that actions associated with system modules, such as page jumps and address changes, be classified as common actions according to the system code. When some records are not associated with the service or system code, they will be uniformly recorded to other behaviors to ensure that the recorded data can be checked.

3. Archiving management:

Based on the purpose of the system design and have integrated terminal iterative speed is different, we need to key business backdating design must spot check index and file, data archive would be persistent storage, avoid terminal back problems caused by rapid iteration, the subsequent will increase the timing task to automatically archive to avoid such problems.

4. User Management:

Common management platform functions can be used to add operation personnel and authorize functions.

Module distribution map of behavior analysis platform:

Note: Backtracking is converted to video when archived, as demonstrated in the data services section below.

Behavior can be backtracked and reported to SDK:

SDK API definitions:

1. Start back record [startRecord] :
  1. Single page application: it is called once when the service starts. The parameter first is set to true, recording is enabled, and UID is returned for self-storage and the UID of the current recording is stored in the cookie.

  2. Multi-page application: When the service starts on a single page, the call is required when each page is entered after the service starts. The parameter first is false and the recorded data of the same UID is bound.

  3. After recording starts, the SDK automatically reports recorded data at the default interval of 3 seconds to ensure data integrity.

    startRecord(first = false) {
      if (first) {
        this.uid = uuidv4()
        docCookies.setItem('behavior-record-uid'.this.uid)
      } else {
        this.uid = docCookies.getItem('behavior-record-uid')}if (!this.uid) {
        throw new Error('Unable to get UID, refer to development documentation.')}const ctx = this
      this.stopFn && this.stopFn()
      this.stopFn = rrweb.record({
        emit(event) {
          ctx.events.push(event)
        }
      })
      this.timer = setInterval(() = > {
        if (ctx.events.length > 0) {
          this._requestEvents(this.uid, ctx.events)
          ctx.events = []
        }
      }, config.INTERVAL_TIME)
      return this.uid
    }
    Copy the code
2. Stop backtracking records:
  1. Single page application: call once when the service ends. Parameter last is set to true to end recording. UID stored in cookie will be cleared.

  2. Multi-page application: if the service ends on a single page, it needs to be called when each page leaves before the service ends. Parameter Last is set to false, and the UID stored in the cookie will not be cleared.

    stopRecord(last = false) {
      if (!this.stopFn) {
        throw new Error(
          'No startup recording found, refer to development documentation.')}this.stopFn()
      clearInterval(this.timer)
      this.timer = null
      if (this.events.length > 0) {
        this._requestEvents(this.uid, this.events)
        this.events = []
      }
      if (last) {
        if (docCookies.hasItem('behavior-record-uid')) {
          docCookies.removeItem('behavior-record-uid')
          this.uid = ' '}}}Copy the code
3. Report backtracking records [Report] :
  1. After the call to stop the backtracking API (last=true), some public data used for statistics and analysis needs to be extracted and reported, and associated with the relevant business ID.

  2. If the recorded scenario is not a service scenario, you can generate the system ID and report the module or function name for query and analysis.

    _requestEvents(uid, events) {
      this._request('track/update', {
        uid,
        timestamp: events[0].timestamp,
        events,
        userAgent: navigator.userAgent
      })
    }
    
    async _request(action, data) {
      return await fetch(`${config.EVENT_API}/${action}`, {
        method: 'POST'.headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(data)
      })
    }
    Copy the code
  • After installing the plug-in on the client that needs to be traceback, a simple configuration can start the traceback operation:

    import { BehaviorRecord } from './behavior-record/index'
    window.rb = new BehaviorRecord()
    
    // Called when starting/restarting traceback
    start(bool) {
      if (bool) {
        const uid = window.rb.startRecord(true)
        console.log('[ uid true ] >', uid)
      } else {
        const uid = window.rb.startRecord(false)
        console.log('[ uid false ] >', uid)
      }
    }
    
    // Pause/end traceback
    stop(bool) {
      if (bool) {
        window.rb.stopRecord(true)}else {
        window.rb.stopRecord(false)}}Copy the code

SDK API usage flowchart:

Data Services:

The data service is used to connect the SDK and analysis platform to provide user management and behavior management data support for the analysis platform. After the SDK is integrated with the terminal to be reported, the data source is periodically reported according to the scenario. As a large amount of the stored content is JSON documents that do not need strong relationship. It is recommended to use MongoDB as the storage medium with higher efficiency.

Because DOM recording is affected by large version iteration of terminal, part of content cannot be traced back, such as real-time pictures and real-time scripts, etc., it is necessary to add scheduled tasks to do periodic data archiving. Although persistent data loses the advantage of direct DOM playback, it is also an indispensable part of content at present.

Data Service function flow diagram:

  • Scheduled archiving task (demo) :
    const Subscription = require('egg').Subscription;
    const { spawn } = require('child_process');
    
    // Implement a timed task in EggJs, currently executing the SUBSCRIBE function every hour
    // subscribe is a demonstration function, which is limited by transcoding speed in practice
    class RegularlyArchive extends Subscription {
    
      // Configure the trigger rule
      static get schedule() {
        return {
          interval: '60m'.// Minute interval
          type: 'all'.// specify that all workers need to be executed
        };
      }
    
      // Task execution function
      async subscribe() {
        console.log('[execution time] >'.new Date().getTime());
        /** * execute the video conversion command with spawn * input: events data array * output: video file output address ** conversion logic: * 1 Puppeteer to load DOM using rrWeb-player for background video playback * 2 Get data streams * 3 from the DOM element screenshot function at a timer 15 times per second. Write each intercepted data stream to the ffmpegProcess process */
        spawn(
          'rrvideo.cmd'['--input'.'./data.json'.'--output'.'./rrvideo-output.mp4'] and {stdio: [ process.stdin, process.stdout, process.stderr ], } ); }}Copy the code

Converting video flow charts using FFMPEG:

Through background DOM replay and regular screenshots, ffMPEG library is used to synthesize pictures into videos and upload them to the object storage service to achieve the purpose of persistent storage of data.

The video generation process is a little slow, please wait for a moment (for demonstration) :

Examples of headless browser using and extending global functions:

export async function openPage(
  input: string,
  output: string,
  resolve: Function,
  reject: Function
) {
  _input = input;
  _output = output;
  _resolve = resolve;
  _reject = reject;

  try {
    browser = await puppeteer.launch({
      headless: true}); page =await browser.newPage();
    await page.goto("about:blank");
    // Extend the start recording function
    await page.exposeFunction("onReplayStart".async() = > {await startReplay();
    });
    // Extend the end recording function
    await page.exposeFunction("onReplayFinish".async() = > {await finishReplay();
    });
    // Read the original data
    const events = JSON.parse(
      fs.readFileSync(path.resolve(process.cwd(), _input), "utf-8"));await page.setContent(getHtml(events));
  } catch (error) {
    console.log("The openPage.", error); }}Copy the code

Examples of video processing using FFmpeg:

async function startReplay() {
  state = "recording";
  const wrapperEl = await page.$(".replayer-wrapper");
  console.log("Please wait for a moment...");
  const ffmpegProcess = spawn("D:\\ffmpeg\\bin\\ffmpeg"[// fps
    "-framerate"."15".// Enter the configuration
    "-f"."image2pipe"."-i"."-".// Output configuration
    "-y",
    _output,
  ]);
  let processError: Error | null = null;

  // 15 times per second (frame rate) timed execution
  const timer = setInterval(async() = > {if (state === "recording" && !processError) {
      try {
        const buffer = awaitwrapperEl? .screenshot({encoding: "binary"}); ffmpegProcess.stdin.write(buffer); }catch (error) {
        // ignore}}else {
      clearInterval(timer);
      if (state === "closed" && !processError) {
        console.log("End of conversion"); ffmpegProcess.stdin.end(); }}},1000 / 15);

  ffmpegProcess.on("close".() = > {/* End callback */});
  ffmpegProcess.on("error".(error) = > {/* Error callback */});
  ffmpegProcess.stdin.on("error".(error) = > {/* Error callback */});
}
Copy the code

Understand rrweb

Record and replay the web

rrweb is an open source web session replay library, which provides easy-to-use APIs to record user’s interactions and replay it remotely. — rrweb官网

Rrweb is short for ‘Record and Replay the Web’ and, as the name suggests, rrWeb is an open source library for recording and replaying user actions on Web pages.

Introduction:

  1. Rrweb consists of three main parts:
    • Rrweb-snapshot: : Contains the snapshot and rebuild functions
    • Rrweb: contains both record and replay functions
    • Rrweb-player: UI suite that provides full playback capabilities
  2. Support for Typescript, which naturally supports strong typing to ensure consistent recording and playback of data structures.
  3. Support privacy protection, about the recording process of some privacy content, for developers to provide a wealth of privacy protection options.
  4. Mainstream open source library, the number of Star on GitHub has reached 11.2K, and a stable version has been released. In an interview with the author (RRWeb documentary), the author mentioned that rrWeb’s total session submissions reached 1 billion per month and the insurance industry accounted for the largest proportion. Is this a good test for RRWeb?

Application Scenarios:

  1. User analytics: It’s easy to understand users and optimize their experience with perfect pixel-level replays of what they do on the site.
  2. Reproduce bugs: Problems can be played back remotely and debugged with consistent behavior in the browser.
  3. Web presentation: Provides a more lightweight and pixel-perfect way to present your Web pages instead of recording videos.
  4. Real-time collaboration: With rrWeb’s powerful features, it is easy to interact and share with others on the web in real time.

Working principle analysis

Rrweb’s recording scheme from the initial determination of snapshot recording to the solution of the storage space waste caused by long invalid recording caused by periodic snapshot and the performance pressure caused by a large number of complex DOM to DIFF, so as to determine the final version of a DOM snapshot + listening DOM and other related changes combined.

What are the concerns of Oplog?

  1. The MutationObserver is used to monitor DOM structure changes.
  2. By listening to global events to get mouse movement, window zooming, view scrolling, media interaction;
  3. Log changes to the input component by listening for input events and hijacking the set;
  4. The stylesheet changes are recorded by proxy stylesheet related functions;
  5. Special Canvas components and fonts also need proxy methods to handle them.

MutationObserver API:

  • The MutationObserver API makes it easy to listen for DOM changes, and its callback function returns data that matches the MutationRecord interface:
attribute type instructions
type String For attribute changes, return “Attributes”; If the characterData node changes, “characterData” is returned. If the child tree childList changes, “childList” is returned.
addedNodes NodeList Returns the added node.
removedNodes NodeList Returns the removed node.
previousSibling Node Returns the sibling of the node that was added or removed, or null.
nextSibling Node Returns the sibling node after the added or removed node, or null.
attributeName String Returns the property name of the property being modified, or NULL.
attributeNamespace String Returns the namespace of the modified attribute, or NULL.
oldValue String The return value depends on mutationRecord.type. For attribute changes, return the value of the attribute before the change. For characterData changes, the data before the change is returned. For child tree childList changes, null is returned.
  • The compatibility of the MutationObserver API is shown below:

Write in the last

During this exploration we learned about the benefits of rrWeb open source products through research and verified them by building a complete front and back end system. The data recorded using RRWeb needs to build a special playback system to realize DOM replay, so the propagation is low. In this case, puppeteer+FFmpeg can be used to transfer the data to videos and then distribute them.

Behavioral traceable system can add data support in product experience optimization, system stability, user operation specifications and other aspects, so that we can intuitively analyze and summarize and pave the way for the next improvement. There are also many products or functions that can be realized based on RRWeb recording scheme, such as conference screen sharing based on Web platform, system monitoring based on Web platform and sales behavior tracing system of financial insurance companies.

About us

GFE trading Compliance Front End Team (GFE), which belongs to the BUSINESS line R&D Department of Trading Compliance business of GFE (Beijing), is a team with passion, creativity and adherence to technology-driven comprehensive growth. The average age of the team is 27 years old. Some have been working in their respective fields for many years, and some have just graduated from the cow, we actively explore in engineering, coding quality, performance monitoring, micro service, interactive experience and other directions, the pursuit of technology-driven product landing purpose, to create a perfect front-end technology system.

  • Vision: To be the most trusted and influential front-end team
  • Mission: Adhere to customer experience first, create more possibilities for business
  • Culture: courage to undertake, in-depth business, brainstorming, simple and open

Github: github.com/gfe-team Email: [email protected]

  • Articles with source code and case studies are available at GFE-Team.
  • If the article has quoted content but not declared the phenomenon, please contact us directly.
  • At present, all sections are under construction, please look forward to…

Refer to the reading

  1. rrweb-io
  2. ​Rrweb: Open the black box for web page recording and playback
  3. How do I convert a recorded DOM to a video file
  4. Brief analysis of Web screen recording technology scheme and implementation
  5. Rrweb takes you back to the problem spot
  6. The probe realizes the front-end abnormal video recording and playback function based on RRWeb

This article is published by the Transaction Compliance Front End Team (GFE) of Highlight Technology. Any unauthorized republication of this article is prohibited. If you’re ready to change jobs and you like it here, join us! ! !