Skip to content

資料埋點:記錄使用者在應用中做了什麼

本章要解決的問題

我們怎麼知道使用者在應用裡做了什麼?

想像你開了一家線上手搖飲店。你可以站在櫃台後面,親眼觀察每位顧客:他們走進來先看了菜單多久?點了哪款飲品?有沒有猶豫後放棄離開?

但如果你的「店鋪」是一個手機 App 或網站,你無法親眼看到使用者的操作。這時候就需要一種技術手段,在應用的關鍵位置「埋」下記錄點,自動幫你記錄使用者的每一步操作。這就是資料埋點(Event Tracking)

「埋點」這個詞聽起來很專業,但它的核心思路很簡單:在使用者可能操作的地方,放一個「記錄器」,把使用者做了什麼記下來。

本章將分四步講解這個過程:

  1. 選擇採集方案 — 決定在哪裡放記錄器、怎麼放
  2. 設計資料格式 — 決定每條記錄應該包含哪些資訊
  3. 傳輸與快取 — 把記錄從使用者手機安全送到伺服器
  4. 清洗與入庫 — 整理資料,去掉重複和錯誤,存入資料庫

第一步:選擇採集方案 — 在哪裡放記錄器?

目標:決定用什麼方式來記錄使用者的操作。

舉個例子:產品經理想知道「有多少使用者點擊了購買按鈕」。要回答這個問題,開發者需要在「購買按鈕」的程式碼裡加上一段記錄邏輯 — 每當使用者點擊這個按鈕,就自動記一筆。

但這裡有一個選擇題:我們是只在重要的地方放記錄器(比如只記錄「購買」和「註冊」),還是在所有地方都放記錄器(記錄使用者的每一次點擊、滑動、停留)?

不同的選擇,對應不同的埋點方案。

场景:用户在电商 App 点击了「加入购物车」按钮
捕获到的信息代码埋点可视化埋点全埋点
点击了哪个按钮
点击发生的时间
用户停留了多久
商品名称 / 价格
用了哪张优惠券
账户余额
页面滑动轨迹

三種主流的埋點方式

行業中常用的埋點方案有三種,各有優劣:

方式一:程式碼埋點(Code Tracking)— 手動精確記錄

開發者在程式碼中手動指定:當使用者做了某個操作時,記錄一條資料。

打個比方:這就像在手搖飲店的收銀台專門安排一個人,只記錄「誰買了什麼、花了多少錢」。記錄的資訊非常詳細和準確。

  • 優勢:可以記錄非常詳細的業務資訊,比如使用者用了哪張優惠券、帳戶餘額是多少
  • 代價:每增加一個新的記錄點,都需要開發者寫程式碼、測試、發布新版本,流程較長

方式二:視覺化埋點(Visual Tracking)— 點擊圈選記錄

不需要寫程式碼。系統提供一個視覺化工具,營運人員可以直接在應用介面上「圈選」想要監測的按鈕或區域,系統自動開始記錄。

打個比方:這就像在手搖飲店的監控畫面上,用滑鼠框選「收銀台區域」,系統就自動開始統計這個區域的人流量。

  • 優勢:不需要開發者參與,營運人員自己就能設定,效率很高
  • 代價:只能記錄「使用者點了什麼」這類介面操作,無法記錄「訂單金額」等深層業務資料

方式三:全埋點(Auto Tracking)— 自動記錄一切

在應用中整合一個 SDK(可以理解為一個「工具包」),它會自動記錄使用者的所有操作:每一次點擊、每一次滑動、在每個頁面停留了多久。

打個比方:這就像在手搖飲店的每個角落都裝上攝影機,記錄顧客的一舉一動。

  • 優勢:不會遺漏任何操作,覆蓋最全面
  • 代價:資料量非常大,其中很多是無用資訊(比如使用者無意識的滑動),後續需要花大量精力篩選和清理

本步小結:選好了埋點方式後,我們的應用就具備了「記錄使用者操作」的能力。

但這裡有一個新問題:記錄器雖然能捕獲到使用者的操作,但如果每個記錄器記下來的格式都不一樣(比如有的寫「使用者ID」,有的寫「userID」,有的根本沒記),後續就沒辦法統一分析。所以下一步,我們需要規定一個統一的記錄格式。


第二步:設計資料格式 — 每條記錄應該包含什麼?

前置條件:我們已經選好了埋點方式(比如程式碼埋點),應用已經能夠捕獲使用者的操作了。

本步目標:規定一個統一的「記錄模板」,讓所有埋點記錄的格式保持一致。

為什麼需要統一格式? 想像一下:如果手搖飲店有三個店員同時記錄銷售情況,一個寫「小明買了珍珠奶茶 15 元」,另一個寫「15,奶茶,珍珠」,第三個寫「珍珠奶茶一杯」。到了月底彙總的時候,這些記錄格式完全不同,整理起來會非常痛苦。所以我們需要一張統一的「記錄表」,規定每條記錄必須填寫哪些欄位。

What"event": "add_to_cart"
Who"user_id": "u_98765"
When"time": "2025-08-12T10:33:09Z"
Where"device": "iPhone 15", "network": "5G"
What"product": "新款手机", "price": 2999
点击上方按钮,观察一条埋点记录是如何被组装出来的

核心原理:4W1H 記錄模板

無論記錄什麼操作,每條資料都需要回答以下五個問題(簡稱 4W1H):

Who — 誰做的?

我們需要知道這條記錄是哪個使用者產生的。

  • 如果使用者已經登入,就用他的帳號 ID(比如 user_id: "zhangsan123"
  • 如果使用者沒有登入,就用裝置的唯一識別碼(比如手機的裝置編號),這樣至少能區分「這是同一台手機上的操作」

When — 什麼時候做的?

記錄操作發生的精確時間,精確到毫秒。

這裡有一個細節:如果你的應用有海外使用者,台北時間下午 3 點和紐約時間下午 3 點其實差了 13 個小時。為了避免混亂,所有時間統一轉換為 UTC 標準時間(可以理解為「世界統一時間」)。

Where & How — 在什麼環境下做的?

這部分記錄使用者操作時的裝置和網路環境,稱為公共屬性。之所以叫「公共」,是因為無論使用者做了什麼操作,這些資訊都會自動附帶上去。例如:

  • 裝置型號:iPhone 15 / 小米 14
  • 網路類型:WiFi / 5G / 4G
  • App 版本號:v1.2.3
  • 作業系統:iOS 18 / Android 15

這些資訊的價值在於:如果發現某個 Bug 只在特定機型上出現,公共屬性可以幫助快速定位問題。

What — 具體做了什麼?

這部分記錄操作的具體業務細節,稱為自訂屬性。不同的操作需要記錄不同的資訊。例如:

  • 使用者點擊「加入購物車」:需要記錄商品名稱、商品價格、商品數量
  • 使用者完成付款:需要記錄訂單金額、付款方式、優惠券編號

本步小結:透過 4W1H 模板,我們把使用者的每一個操作都轉化成了一條格式統一的資料記錄。在技術實作中,這條記錄通常以 JSON 格式儲存(JSON 是一種通用的資料格式,上方的互動元件展示了它的樣子)。

但這裡又有一個新問題:資料格式統一了,但如果應用的使用者量很大(比如促銷活動期間,每秒鐘可能產生上萬條記錄),使用者手機不可能每產生一條記錄就立刻發送一次 — 這樣既費電又費流量,伺服器也撐不住。所以下一步,我們需要設計一個更聰明的傳輸方式。


第三步:傳輸與快取 — 怎麼把資料安全送到伺服器?

前置條件:使用者的每個操作已經被記錄成了格式統一的 JSON 資料。

本步目標:把這些資料從使用者的手機(或瀏覽器)可靠地傳輸到我們的伺服器,即使在網路不好的情況下也不丟資料。

為什麼不能直接發送? 如果每產生一條記錄就立刻發一次網路請求,就像每寫一封信就跑一趟郵局一樣 — 效率太低了。更合理的做法是:攢一批信,一次性送過去。

📱
手机
📦
打包
🌐
发送
🚦
排队
🗄️
入库
产生数据攒一批网络传输消息队列数据仓库

核心原理:資料傳輸的三道保障

資料從使用者手機到伺服器,需要經過三道保障機制,確保既高效又不丟資料:

第一道:攢一批再發(批量聚合)

SDK(埋點工具包)不會每產生一條記錄就發送一次,而是先把記錄暫存在手機記憶體裡。當攢夠一定數量(比如 30 條),或者等待超過一定時間(比如 5 秒),再把這一批資料打包,一次性發送出去。

這就像寄快遞:你不會買一件東西就跑一趟快遞站,而是攢幾件一起寄,省時省力。對手機來說,這樣做能減少網路請求次數,省電省流量。

第二道:斷網也不丟(本地儲存)

使用者在電梯裡、捷運隧道中,手機經常沒有網路訊號。如果資料只存在記憶體裡,使用者一關閉 App,資料就沒了。

所以 SDK 會把還沒發送的資料存到手機的本地儲存中(類似於把信先放進抽屜)。等網路恢復後,再自動把這些資料補發出去。這樣即使使用者短暫斷網,資料也不會遺失。

第三道:伺服器不被壓垮(訊息佇列)

資料到達伺服器後,並不會直接寫入資料庫。為什麼?因為在促銷活動等高峰期,可能每秒有幾萬條資料同時湧入,資料庫如果直接處理這麼大的量,可能會崩潰。

解決方案是在中間加一個「緩衝區」,技術上叫訊息佇列(常用的工具叫 Kafka)。它的作用就像餐廳的取號排隊系統:高峰期顧客(資料)先排隊等候,廚房(資料庫)按自己的節奏一個一個處理,不會被同時湧入的訂單壓垮。

本步小結:透過「攢一批再發 → 斷網本地儲存 → 訊息佇列緩衝」這三道保障,資料已經安全抵達了伺服器。

但還有一個問題:因為斷網重連後會自動補發資料,同一條記錄有可能被發送了兩次。如果不處理就直接存入資料庫,資料就會重複(比如一筆 100 元的訂單被記成了兩筆,營收就虛高了)。所以下一步,我們需要對資料進行「清洗」。


第四步:清洗與入庫 — 整理資料,去掉「髒資料」

前置條件:資料已經透過傳輸管道安全抵達伺服器。

本步目標:在資料正式存入資料庫之前,先做一次「健檢」— 去掉重複的、修復格式有問題的,確保最終儲存的資料乾淨、準確。

為什麼需要清洗? 就像收到一箱快遞後,你需要檢查一下:有沒有重複發貨的?有沒有發錯的?有沒有包裝破損的?資料也是一樣,直接存入資料庫之前,需要先檢查和整理。

這個過程在技術上叫做 ETL,是三個英文單字的縮寫:

  • Extract(提取):從訊息佇列中取出資料
  • Transform(轉換):檢查和修復資料格式
  • Load(載入):把清洗好的資料寫入資料庫
原始数据(服务器收到的)
id-001 userId: "zhang" add_to_cart ¥2999
id-001 userId: "zhang" add_to_cart ¥2999重复
id-002 user_id: "li" click_buy ¥0
id-003 userId: "wang" pay 1970-01-01时间异常
id-004 user_id: "zhao" click_buy ¥599
ETL 清洗
清洗后(写入数据仓库的)
id-001 user_id: "zhang" add_to_cart ¥2999
id-002 user_id: "li" click_buy ¥0
id-004 user_id: "zhao" click_buy ¥599

核心原理:清洗資料的兩個關鍵動作

動作一:去重 — 去掉重複的記錄

前面提到,斷網重連後 SDK 會自動補發資料,這可能導致同一條記錄被發送了多次。怎麼識別哪些是重複的?

方法很簡單:在客戶端打包資料時,給每條記錄分配一個全球唯一的編號(叫做 dedup_id,類似於快遞單號)。伺服器在儲存資料前,先檢查這個編號是否已經存在 — 如果已經存在,說明是重複資料,直接丟棄。

動作二:校驗與格式統一 — 修復不規範的記錄

應用會不斷更新版本,不同版本的埋點程式碼可能存在細微差異。比如:

  • 舊版本把使用者 ID 欄位命名為 userId,新版本改成了 user_id
  • 某些記錄的時間戳記明顯不合理(比如顯示為 1970 年)
  • 某些欄位的值無法識別

在這一步,系統會編寫轉換規則來統一處理這些問題:欄位名不一致的統一對齊,時間戳記異常的記錄予以丟棄,無法識別的值標記為 unknown

本步小結:經過去重和格式校驗後,資料以乾淨、統一的形式寫入資料倉儲(一種專門用於儲存和分析大量資料的資料庫,常見的有 ClickHouse、Hive 等)。資料分析師可以直接用 SQL 語句查詢這些資料,獲得可靠的分析結果。


完整流程回顧

以下是資料埋點從採集到入庫的四步流程總結:

步驟做了什麼得到了什麼還剩什麼問題
1. 選擇採集方案決定用哪種方式記錄使用者操作應用具備了記錄能力各記錄器的資料格式不統一
2. 設計資料格式用 4W1H 模板統一記錄格式每條記錄都是標準的 JSON使用者量大時逐條發送撐不住
3. 傳輸與快取攢批發送、斷網儲存、佇列緩衝資料安全抵達伺服器重試可能導致資料重複
4. 清洗與入庫去重、校驗、格式統一乾淨的資料存入資料倉儲

結語

當使用者在應用中點擊一個按鈕時,表面上看只是一個瞬間的動作。但在這背後,一條完整的資料鏈路已經開始運轉:

  1. 埋點程式碼捕獲到這次點擊,按照 4W1H 模板產生一條標準記錄
  2. 記錄被暫存在手機本地,攢夠一批後統一發送到伺服器
  3. 伺服器透過訊息佇列平穩接收,再經過去重和格式校驗
  4. 最終,一條乾淨、準確的資料被寫入資料倉儲

這就是資料埋點的完整過程。它把使用者分散的、看不見的操作行為,轉化成了可以查詢、可以分析的結構化資料。產品經理可以據此了解使用者喜歡什麼功能、在哪裡流失;營運人員可以評估活動效果;開發者可以定位問題出現在哪個版本。

這套「採集 → 建模 → 傳輸 → 清洗」的體系,是資料驅動決策的基礎設施。