Calculate exposure time (dwell time) for each module within a page

The product wants to see the active page put out, and the user is interested in what information is on the page, and not at all interested in what information is on the page. => Calculate the residence time of each module on the page

When I heard this requirement for the first time, my brain started to work crazily, and then I thought of Plan 1, Plan 2, Plan 3… There are a lot of bad ideas in between that I’ve forgotten, but plan three is the way I ended up doing it. If you have any better idea, welcome to give advice, sincerely!!

Scheme 1: divide the page into modules according to the DOM

var bodyChildrenLists = $('body').children()
var bodyChildDomLsit = []
var initHeight = 0
for (var i = 0; i < bodyChildrenLists.length; i++) {
    if(bodyChildrenLists[i].tagName ! = ='SCRIPT') {
        bodyChildDomLsit.push({
        className: bodyChildrenLists[i].className,
        height: bodyChildrenLists[i].offsetHeight
      })
    }
}
Copy the code

Existing problems: The code styles of different people vary greatly, so this scheme is not suitable for such code styles

<body>
    <div class="container">
        <div class="header"></div>
        <div class="nav"></div>
        <div class="footer"></div>
    </div>
</body>
Copy the code

This is a good way to use it if everyone has the same code style.

Scheme 2: calculate all behaviors of users after opening the page

var scrollTop = 0
var time = Date.now()
window._stayStatus = {
Down > 1 Move down Move up, sliderDis move distance, time move time, initDis initial distance, initTime initial time
    moveData: [],
    enterTime: Date.now()
}
var moveData = window._stayStatus.moveData
var currentMoveIndex = 0
function move () {
    var currentTime = Date.now()
    var currentScrollTop = $(window).scrollTop()
    var dis = currentScrollTop - scrollTop
    var disTime = currentTime - time
    // If the time difference between the last slide and this slide is greater than 100ms, the user is considered to have stopped at a certain time
    if (disTime > 100) {
        if (moveData[currentMoveIndex] && moveData[currentMoveIndex].down === 0) {
            moveData[currentMoveIndex].time += disTime
        } else {
            moveData.push({
                down: 0.initTime: time, // initTime indicates the initial time to enter the state
                initDis: currentScrollTop, //initDis indicates the initial position to enter the state
                sliderDis: dis, // The distance to slide in this state
                time: disTime // Time spent in this state (ms)}}})else {
        // Slide down
        if (dis >= 0) {
            // If it is already sliding down, just add the sliding distance and sliding time to the original data
            if (moveData[currentMoveIndex] && moveData[currentMoveIndex].down > 0) {
                moveData[currentMoveIndex].sliderDis += dis
                moveData[currentMoveIndex].time += disTime
            } else {
                moveData.push({
                    down: 1.initTime: currentTime,
                    initDis: currentScrollTop,
                    sliderDis: dis,
                    time: disTime
                })
            }
        } else {
            if (moveData[currentMoveIndex] && moveData[currentMoveIndex].down < 0) {
                moveData[currentMoveIndex].sliderDis += dis
                moveData[currentMoveIndex].time += disTime
            } else {
                moveData.push({
                    down: - 1.initTime: currentTime,
                    initDis: currentScrollTop,
                    sliderDis: dis,
                    time: disTime
                })
            }
        }
    }
    currentMoveIndex = moveData.length - 1
    time = currentTime
    scrollTop = currentScrollTop
  }
  window.onscroll = function (e) {
    move()
  }
Copy the code

The obtained data is as follows: 1559048450563_ image.png

Existing problems: Although the amount of data finally obtained is not very large, it is difficult to send such data to the data group for analysis. This is in the absence of product docking, their own way to think, a bit complicated. But this way you can more vividly simulate the user’s behavior.

Plan three: fixed module size, calculate the residence time of each module

With my product docking basic provisions:

  • Every 1300px height (about one screen height) as a module, the buried point statistics.
  • Each screen exposure greater than 400px (about a third of the screen height) is considered a valid exposure and the duration is recorded.
  • The reporting time of each module is the sum of sliding time and stationary time in the module.
  • The current module is set as module 0. When the user does not reach module 1, the time of repeated sliding is recorded as the time in module 0.
  • The current module is set as module 0. When the user reaches module 1 and returns to module 0 by sliding behavior, the data of module 0 will be recorded again
  • The last time when a user leaves the page (go to the next flow page or close the browser) is reported. You need to collect statistics on the monitored user exit behaviors and scenarios.

According to the requirements of the above, I made a demo, you can clearly see the effect, I link to see munan2. Making. IO/computeStay…

According to the above requirements, my code is as follows:

new Vue({
    el: '#app'.data: {
        movedata: [].scrollTop: $(window).scrollTop(),
        time: Date.now(),
        stayTime: 0
    },
    mounted () {
        // When the page is rolled to a certain height, the page will remain at the same height after being refreshed. Initialize moveData
        var index = parseInt(this.scrollTop / 1300) + 1
        for (var i = 0; i <= index; i++) {
          this.movedata.push({
            pos: i * 1300.time: 0})}window.onscroll = (a)= > {
          this.scrollTop = $(window).scrollTop()
        }
        setInterval((a)= > {
          var currentTime = Date.now()
          var disTime = currentTime - this.time
          // Calculate the number of modules currently displayed on the screen
          var currentIndex = parseInt(this.scrollTop / 1300)
          // Calculate how much the current scrolling height exceeds the full screen
          var length = this.movedata.length
          if (currentIndex + 1 >= length) {
            for (var i = length; i <= currentIndex + 1; i++) {
              this.movedata.push({
                pos: 1300 * i,
                time: disTime
              })
            }
          } else {
            var modeDis = this.scrollTop - this.movedata[currentIndex].pos
            if ((1300 - modeDis) > 400) {
              this.movedata[currentIndex].time += disTime
            }
            if (modeDis > 400) {
              this.movedata[currentIndex + 1].time += disTime
            }
          }
          this.time = currentTime
        }, 1000)}})Copy the code

The core ideas of this method are as follows:

  1. When entering the page, calculate the scrolling height of the page and determine which module is currently in the page. The current page displays a maximum of two modules (parseInt(this.scrolltop / 1300)), so we assume that two modules are already in the page. We need to give parseInt(this.scrollTop / 1300)+1
  2. The data in the array is sorted by position, so after calculating the value of the module, add all data less than or equal to index to moveData
  3. Turn on the timer for 1s to calculate the dwell time of the current position
  4. Calculate every 1s which module is currently scrolled to (currentIndex) and compare it to moveData
  5. If currentIndex+1 is greater than moveData. length, the page will scroll to the bottom of the page
  6. If less than, it indicates that the scrolling range of the page is still in the existing module data, so as to determine whether the height of the upper module exposed is more than 400, and the height of the lower module exposed is more than 400.

The calculation idea of step6 can be summarized as the picture:

Reasons for using this method:

  1. The amount of data is small, generally an active page is at most five or six screens high, so the amount of data in moveData array is also five or six, when we send logs, we generally request the form of picture resources (GET request), get request in the data amount is too large, there will be data loss problem;
  2. Due to the demand of the products is in a page, if there are two modules, the hope can give this two modules of the residence time, if the use of the form of shunt, assume that I will send the data, the former 10 data array so that I can clear of the top 10, but if you stay within a module are also exposed before, Then the calculation of residence time will be difficult.

Disadvantages of this method: this method cannot simulate all the behavior of the user when entering a page. If such a requirement is needed, the second method is better