iT邦幫忙

2026 iThome 鐵人賽

DAY 7
0

上一篇我們透過 Goals-Signals-Metrics(GSM),從「希望使用者成功」一路往下找到可以觀察的信號與指標。

以商品頁面的案例來說,我們希望使用者能判斷商品是否符合自己的需求,而可能出現的信號包含:

  • 使用者做出購買決策。
  • 使用者調整原本考慮的商品。
  • 使用者直接告訴我們,自己是否已經完成判斷。

但知道要觀察什麼之後,還有一個很工程師的問題:

這些東西到底要怎麼寫進程式?

前一篇最後,我們很快地用了這段程式碼:

posthog.capture('update_cart', {
    action: 'add_item',
    item_id
})

PostHog 的 capture() 可以讓我們主動記錄一個事件(Event),第一個參數是事件名稱,第二個參數則可以帶入這次事件的屬性(Property)。

實際開發時,真正麻煩的通常不是怎麼呼叫 capture(),而是:到底什麼事情值得被記錄?

Autocapture 與自訂事件

在前面安裝 PostHog 時,其實我們還沒有寫多少事件追蹤的程式碼,PostHog 就已經可以取得不少資料。

其中一部分來自 Autocapture。PostHog 可以自動收集網頁上的部分互動,因此即使沒有為每個按鈕手動加入 capture(),我們仍然可以看到使用者在頁面上的一些操作。

這對剛開始使用產品分析來說非常方便。

例如今天想知道:

有沒有人使用新加入的按鈕?

如果相關操作已經被 Autocapture 收集,我們可能不需要為了回答這個問題立刻修改程式碼。

不過,Autocapture 看到的主要是「使用者操作了什麼介面」,不一定知道這個操作在產品中的意義。

假設商品頁面上有一個「加入購物車」按鈕,我們可能可以知道某個按鈕被點擊了,但真正想觀察的其實是:

使用者成功把商品加入購物車。

這兩件事情並不完全相同。

使用者可能點了按鈕,但後端請求失敗;也可能同一個操作之後改成選單、鍵盤快捷鍵,甚至由其他流程觸發。如果我們的指標綁在特定 DOM 元素上,介面一改,原本想觀察的行為也可能跟著失去意義。

這時候,自訂事件就比較適合。

例如:

posthog.capture('add_item_to_cart', {
    item_id,
})

比起記錄:

posthog.capture('click_add_to_cart_button')

前者描述的是產品中實際發生的行為,而不是這個行為目前剛好由哪個按鈕觸發。

並非是說記錄 UI 事件是不好的方法,如果我們現在想回答的問題就是:

使用者有沒有注意到這顆按鈕?

那麼追蹤這個事件就是合理的。

重點仍然是回到前一篇的問題:

我們想觀察的是什麼?

事件並不是因為「這裡可以埋點」就需要建立,而是因為我們需要它來回答某個問題。

Event 與 Property

除了決定事件要不要存在之外,另一個問題是事件應該怎麼設計。

例如購物車可能有很多操作:

posthog.capture('add_item_to_cart', {
    item_id,
})

posthog.capture('remove_item_from_cart', {
    item_id,
})

也可以像前一篇一樣寫成:

posthog.capture('update_cart', {
    action: 'add_item',
    item_id,
})

這兩種方式並沒有一個放諸四海皆準的答案。

如果我們經常想分別觀察「加入購物車」與「移除購物車」,拆成不同 Event 可能比較直接。

但如果它們本來就是同一類操作,而且分析時經常需要一起觀察,那麼使用同一個 Event,再利用 action Property 區分也可能比較方便。

Property 的用途就是補充事件發生時的資訊。

例如:

posthog.capture('update_cart', {
    action: 'add_item',
    item_id,
    product_category,
    quantity,
})

之後我們除了能知道 update_cart 發生幾次,也可以進一步詢問:

哪一類商品最常被加入購物車?

一次通常加入幾個?

加入與移除的比例有什麼不同?

這些資訊在下一篇介紹 Product Analytics 時就可以拿來進行 Filter 或 Breakdown。

不過,這也不代表 Property 越多越好。

很容易出現一種情況:既然都已經寫到這裡了,就順便把商品名稱、價格、庫存、賣家、建立時間、折扣、配送方式全部塞進去。

雖然這不會帶來額外成本,但如果現在完全想不到用途,不一定需要因為「以後可能會用到」就先收集。

後續我們也會介紹關聯查詢,來補足原先沒有紀錄,但實際上已經儲存的資料。

事件應該在什麼時候發生?

即使事件名稱一樣,觸發的時間點不同,也可能得到完全不同的資料。

例如:

posthog.capture('purchase_completed')

什麼叫做 purchase_completed

是使用者按下「付款」按鈕?

是前端收到付款 API 成功?

還是後端真的確認訂單已完成?

如果我們想用這個事件衡量「完成購買」,那麼在使用者按下按鈕時就 Capture 顯然太早了。

同樣的情況也會出現在檔案上傳:

開始上傳
→ 上傳中
→ Server 接收完成
→ 檔案處理完成

如果我們真正關心的是「使用者成功上傳檔案」,事件就應該盡量接近最後真正代表成功的時間點,而不是只因為前端最容易在按下按鈕時埋點,就選擇那個位置。

換句話說,事件的觸發條件也是 Metric 定義的一部分。

如果兩名工程師對 purchase_completed 的理解不同,即使事件名稱完全一樣,最後算出來的指標也可能完全不同。

先寫下來,再開始埋點

對規模很小的產品而言,不需要一開始就建立非常複雜的 Tracking 規範。

但至少可以在加入事件以前,簡單整理:

想觀察的 Signal Event 什麼時候觸發 Property
使用者把商品加入候選 update_cart 商品成功加入購物車後 action, item_id
使用者移除候選商品 update_cart 商品成功移除後 action, item_id
使用者完成購買 purchase_completed 訂單確認完成後 order_id, total

這張表真正重要的不是格式,而是讓我們在寫:

posthog.capture(...)

之前先確認:

這個 Event 對應哪個 Signal?

以及:

什麼情況下,這個 Signal 才算真的發生?

如此一來,事件就不只是散落在程式碼中的 Tracking Code,而是前一篇 GSM 中定義的觀察方式真正落到產品裡。

當然,實際系統還會遇到更多問題。

例如同一筆訂單會不會被前端與後端各送一次?使用者登入前後的事件是不是同一個人?瀏覽器擋掉 Tracking Request 時又該怎麼辦?

這些問題會直接影響資料是否可信,我們會在後面的文章再回來處理。

現在,我們已經先完成最基本的一步:把原本抽象的 Signal 轉換成 PostHog 可以收集的 Event 與 Property。

但資料收集進來之後,如果只是放在 PostHog 裡,也還沒有太大意義。

下一篇,我們就開始使用 Product Analytics,把這些 Event 轉換成真正可以觀察的指標與圖表。


如果你願意花 30 秒留下回饋,我會用這些意見來調整後續文章:分享你的意見


上一篇
Day 6|讓使用者成功(下):GSM
下一篇
Day 8|產品分析 Product Analytics
系列文
成為產品型工程師吧!從培養產品思維到 PostHog 數據實戰20
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言