前端埋點統計方案思考

呆戀小喵_sunmy發表於2018-12-17

埋點即監控使用者在應用表現層的行為,於產品迭代而言至關重要。埋點資料分析是產品需求的 來源,檢驗功能是否達預期的 佐證。前端較服務端更接近使用者,本小白將在此對前端埋點統計方案述說一二。

採集埋點資料可做如下分析(以百度統計為例):

前端埋點統計方案思考

使用者屬性使用者行為 轉化各類視覺化圖表:

前端埋點統計方案思考

前端埋點統計方案思考

不同產品對資料的關注角度不同,可按需採集。如資訊流產品對停留時長的關注度更高(統計頁面訪問 & 跳出時間),商城類較注重“復購率”(統計新老使用者),廣告類更追求最大限度。

埋點統計通常分兩類:

  • 頁面訪問量統計

  • 功能點選量統計


頁面訪問量統計

頁面訪問量統計通常分兩類:

  • PV:頁面訪問人次

  • UV:頁面訪問人數

頁面訪問量,並非僅僅取決於其內容吸引力,影響因素包含入口 外觀位置深度 等等(在此不考慮剛需)。入口外觀屬 UI 設計範疇,入口位置可通過分析使用者點選熱力圖調整,入口深度可通過分析使用者訪問路徑調整。

使用者點選 熱力圖 形如:

前端埋點統計方案思考

將核心頁面入口置於熱力圖紅色區域?

採集頁面載入 fromto 以獲知使用者訪問路徑:

前端埋點統計方案思考

分析可知使用者普遍 訪問深度、每一深度 & 每一頁面的 流失率 等,依照結果調整核心頁面入口源、入口深度?

頁面訪問量,也並非僅僅取決於產品設計。假若 PV 穩定的頁面訪問量 爆跌,便需考慮其載入成功率了(或許是枚技術 bug)。


前端如何實現全域性 PV 統計,以 Vue 應用為例。

方案一

通過在入口檔案 index.js 全域性定義 Router.beforeEach

import App from './app'
import Router from './router'

Router.beforeEach((to, from, next) => {
    App.logEvent({
        type: 'visit',
        name: to.name,
        time: new Date().valueOf(),
        params: {
            from: {
                name: from.name,
                path: from.path,
                query: from.query
            },
            to: {
                name: to.name,
                path: to.path,
                query: to.query
            }
        }
    })
    next()
})
複製程式碼

停留時長可通過 (跳轉頁 time - 當前頁 time) 獲知,但關閉應用時如何統計?監聽應用關閉 onbeforeunload + onunload

其中 App.logEvent 為自定義 Vue 外掛 App 中的 method,用於向伺服器發起 埋點上報請求

import Request from './utils/request'

const App = {
    // ...
    logEvent (opts) {
        Request({
            url: '/log/event',
            method: 'POST',
            data: {
                type: opts.type,
                name: opts.name,
                time: opts.time,
                params: opts.params || {}
            }
        })
    }
}
App.install = (Vue, options) => {
    Vue.prototype.$app = {
        // ...
        logEvent: App.logEvent
    }
}

export default App
複製程式碼

方案二

通過在入口檔案 index.js 全域性註冊混入 beforeRouteEnterbeforeRouteLeave 物件:

import Vue from 'vue'

Vue.mixin({
    beforeRouteEnter (to, from, next) {
        next(vm => {
            vm.$app.logEvent({
                type: 'visit',
                name: to.name,
                time: new Date().valueOf(),
                params: {
                    from: {
                        name: from.name,
                        path: from.path,
                        query: from.query
                    },
                    to: {
                        name: to.name,
                        path: to.path,
                        query: to.query
                    }
                }
            })
        })
    },
    beforeRouteLeave (to, from, next) {
        this.$app.logEvent({
            type: 'visit',
            name: to.name,
            time: new Date().valueOf(),
            params: {
                from: {
                    name: from.name,
                    path: from.path,
                    query: from.query
                },
                to: {
                    name: to.name,
                    path: to.path,
                    query: to.query
                }
            }
        })
        next()
    }
})
複製程式碼

關閉應用時 beforeRouteLeave 是否觸發?

上述方案存在明顯缺陷:

  • 官方曰慎用全域性混入物件!!!

  • 對於頁面同名鉤子函式 beforeRouteEnterbeforeRouteLeave,如何 merge?如何 next

  • 含子路由的頁面將呼叫 2beforeRouteEnterbeforeRouteLeave,PV 無形翻倍...

我猜此刻有打全域性混入 createddestroyed 並通過 this.$route 獲知訪問物件主意的人了,試試看?

前端埋點統計方案思考

令人不知所措的輸出,列印次數與 路由表 長度一致嗷~

其中 this.$app.logEvent(vm.$app.logEvent) 等同方案一中 App.logEvent,不再贅述。


如何恰當選取全域性 PV 統計方案?

  • SPA 應用:僅單入口,在入口檔案全域性定義 Router.beforeEach 方便可行。

  • MPA 應用:多入口,在每個入口檔案定義 Router.beforeEach?可封裝公用邏輯(偽裝單入口),免去重複構造 entry 的成本。

前端埋點統計方案思考

  • SPA + MPA 混合應用:emmmmmm...採用 MPA 應用的統計方案。

  • SSR 應用:為追求更好的 SEO 而採用服務端渲染(SSR)。以 Jinja(Python 模板)為例,呼叫 TemplateView 則為渲染頁面(不同於前後端分離專案,服務端無法獲知介面呼叫與頁面渲染的對應關係),統計其呼叫次數及 TemplateName 可知頁面 PV。

至於 UV,統計 PV 時採集 userId 去重即可。若應用無使用者管理體系,採集 IPdeviceId 也可粗略得知 UV(不精準)。


功能點選量統計

不同功能的點選量不同,同一功能不同區域的點選量也不同:

前端埋點統計方案思考

按鈕點選量,影響因素包含按鈕 外觀位置入口 等等(在此不考慮剛需)。按鈕外觀屬 UI 設計範疇,按鈕位置可通過分析使用者點選熱力圖調整,按鈕入口可通過分析觸發源分佈調整。

舉一例項:

前端埋點統計方案思考

運營同學會將一張圖片裁切成 n 個區域,點選每一區域所推薦商品不同。統計區域點選座標,據熱力圖調整商品排序以求 利益最大化


前端如何實現功能點選量統計?

本人將功能點選分兩類:

  • 帶業務介面請求

  • 無業務介面請求

方案一

將埋點上報混入業務介面請求,無介面請求的點選採用自定義上報:

前端埋點統計方案思考

其中 param keys 指代需上報的業務請求引數 key list(並非全部引數均需隨埋點上報)。

上述方案大大節約請求數,但存在明顯缺陷:

  • 將埋點上報混入業務介面,上報 crash 不僅丟失統計資料,還將影響主功能。

  • 統計與業務 高耦合,兩者儘量不混於同一服務。

方案二

將所有點選事件視為同一類,走統一上報介面:

logEvent (opts) {
    Request({
        url: '/log/event',
        method: 'POST',
        data: {
            type: opts.type,
            name: opts.name,
            time: opts.time,
            params: opts.params || {}
        }
    })
}
複製程式碼

上述方案也存在明顯缺陷:

  • 請求量翻倍:但統計與業務服務拆分後,請求並非同一組伺服器承擔。

  • 待上報的點選事件函式均需呼叫 logEvent:封裝一枚附帶埋點上報的 元件,以 Vue 為例。

<template>
    <div class="vc-trace" @click="triggerClick">
        <slot></slot>
    </div>
</template>

<script>
import Request from './utils/request'

export default {
    name: 'Trace',
    props: {
        type: {
            type: String,
            default: ''
        },
        name: {
            type: String,
            default: ''
        },
        from: {
            type: String,
            default: ''
        },
        params: {
            type: Object,
            default: () => ({})
        }
    },
    methods: {
        triggerClick () {
            Request({
                url: 'XXX/log/event',
                method: 'POST',
                data: {
                    type: this.type,
                    name: this.name,
                    from: this.from,
                    time: new Date().valueOf(),
                    params: this.params
                }
            })
        }
    }
}
</script>
複製程式碼

方案本無優劣,適合才更重要,需綜合考慮 產品設計產品使用度服務利用率 等等。例使用度較低應用可將統計與業務混於同一服務以節約成本,使用度較高應用可採取 本地快取批量上報 以降低服務壓力,但批量上報是否加大統計 誤差

本文所述僅冰山一角,歡迎大家留言寶貴經驗~

2018/12/19 續更

看到幾篇不錯的文章:

頁面跳轉時,統計資料丟失問題探討

Page Lifecycle API 教程


作者:呆戀小喵

我的後花園:sunmengyuan.github.io/garden/

我的 github:github.com/sunmengyuan

原文連結:sunmengyuan.github.io/garden/2018…

前端埋點統計方案思考

相關文章