計算頁面內各模塊的曝光時間

計算一個頁面內每一個模塊的曝光時間(停留時間)

產品但願看到投放出去的活動頁,用戶對其頁面內的什麼信息比較感興趣,對什麼信息徹底不感興趣。=> 計算頁面內每模塊的停留時間git

第一次聽到這個需求,個人大腦開始瘋狂運轉,而後想到了plan 1, plan 2, plan3...中間還有不少失敗想法我已經忘記了,這裏方案三是我最終採用的方法。
若是你們有什麼更好的想法,歡迎賜教,真心的!!!github

方案一:根據頁面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
      })
    }
}
複製代碼

存在的問題: 不一樣人的代碼風格差別性大,該方案不適合這類代碼風格數組

<body>
    <div class="container">
        <div class="header"></div>
        <div class="nav"></div>
        <div class="footer"></div>
    </div>
</body>
複製代碼

這種方式很好,就是,,,若是你們的代碼風格很一致的狀況下使用比較好。瀏覽器

方案二:計算出用戶打開頁面後的全部行爲

var scrollTop = 0
var time = Date.now()
window._stayStatus = {
// 記錄運動軌跡, down > 1 向下移動 down 向上移動, sliderDis 移動距離, time 移動耗時, initDis 初始距離, initTime 初始時間
    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
    // 上一次滑動頁面和此次滑動頁面的時間差大於100ms,就視做用戶在某一個段時間作了停留
    if (disTime > 100) {
        if (moveData[currentMoveIndex] && moveData[currentMoveIndex].down === 0) {
            moveData[currentMoveIndex].time += disTime
        } else {
            moveData.push({
                down: 0,
                initTime: time, // initTime表示進入該狀態的初始時間
                initDis: currentScrollTop, //initDis 表示進入該狀態的初始位置
                sliderDis: dis, // 在該狀態內滑動的距離
                time: disTime // 在該狀態經歷的時間(ms)
            })
        }
    } else {
        // 向下滑動
        if (dis >= 0) {
            // 若是以前已是向下滑動的狀態,只須要在原來的數據上累加滑動距離和滑動時間
            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()
  }
複製代碼

根據以上方法獲取到的數據以下: 1559048450563_圖片.png bash

表示:用戶在距頂部2px時停留了2728ms後,向下滑動了612px,滑動時間爲595ms,而後又在距頂部612px停留了8649ms,最後向上滑動了604px,經歷了167ms。

存在的問題: 最後獲得的數據量雖然不會很大,可是將這樣的數據給數據組分析,存在必定的難度。這是在沒有和產品對接時,本身想的辦法,有點想複雜了。可是這種方式能夠比較生動模擬出用戶的行爲。app

方案三: 固定模塊尺寸,計算每模塊的停留時間

與個人產品對接了基本的規定:dom

  • 每1300px高度(大約一屏高度)做爲爲一個模塊,進行埋點統計。
  • 每屏曝光範圍大於400px(大約三分之一屏高度)時做爲有效曝光,開始記錄時長。
  • 每一模塊的上報時間均爲在模塊內滑動時間及靜止停留時間加和。
  • 設當前模塊爲模塊0,當用戶未到達模塊1時,反覆滑動時間均記作模塊0內時間。
  • 設當前模塊爲模塊0,當用戶到達模塊1後又經過滑動行爲返回模塊0,此時會從新記錄一次模塊0數據
  • 最後一次上報時間爲用戶離開該頁面(進入下一流程頁面或關閉瀏覽器),需統計可以監測到的用戶離開行爲及場景。

根據上面的要求我作了一個demo,能夠清晰看到我計算效果,連接可看 munan2.github.io/computeStay…ide

根據以上需求,個人代碼如:ui

new Vue({
    el: '#app',
    data: {
        movedata: [],
        scrollTop: $(window).scrollTop(),
        time: Date.now(),
        stayTime: 0
    },
    mounted () {
        // 部分頁面存在頁面滾動到某一高度時,刷新後頁面也會固定在該高度的問題,初始化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 = () => {
          this.scrollTop = $(window).scrollTop()
        }
        setInterval(() => {
          var currentTime = Date.now()
          var disTime = currentTime - this.time
          // 計算當前是展示在屏幕中的模塊序號
          var currentIndex = parseInt(this.scrollTop / 1300)
          // 計算當前的滾動高度超出滿屏的多少
          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)
    }
})
複製代碼

該方法的核心思想:this

  1. 剛進入頁面時,計算頁面的滾動高度,並肯定當前在哪一個模塊中,當前頁面中最多展現兩個模塊(parseInt(this.scrollTop / 1300)),因此,咱們假設已經在展現兩個模塊了,須要給parseInt(this.scrollTop / 1300)+1
  2. 數組中的數據的排序是按照位置來排序的,因此計算到模塊的值後,將小於等於index的數據都補到movedata中
  3. 開啓定時器1s,計算一下當前的位置的停留時間
  4. 每隔1s計算一下當前滾動到哪個模塊中了(currentIndex),與movedata的長度作比較
  5. 若是currentIndex+1(默認一屏內展現了兩個模塊)大於movedata.length,說明頁面又滾動到了下面,movedata裏尚未下面模塊的數據,就補上
  6. 若是小於的話,說明頁面滾動的範圍還在現有的模塊數據中,這樣判斷一下上面的模塊暴露出來的高度是否超過400,下面的模塊暴露出來的高度是否超過400。

step6的計算思想可概括爲圖片:

使用該方法的緣由:

  1. 數據量小,通常一個活動頁最多五六屏高度,這樣movedata數組中的數據量也就五六條,咱們在發送日誌時,通常請求圖片資源的形式(get請求),get請求在數據量過大時會存在數據丟失的問題;
  2. 因爲產品的需求是在一個頁面內停留時,若是有兩個模塊存在,但願能夠給這兩個模塊都記上停留時間,若是使用分流的形式,假設我將前10個數據發給了數據,這樣我會清除數組中前10條,可是若是停留的時候前一個模塊也在曝光內,那麼停留時間的計算會有必定的難度。

該方法的缺點: 該方法沒辦法模擬到用戶進入到一個頁面的全部行爲,若是須要這樣的需求,第二種方案比較好

相關文章
相關標籤/搜索