分析脈絡
- 查詢 prod_by_keyword 月趨勢,定位斷裂時間點
- 追蹤上游 Click 事件的 page_component_name 分佈變化
- 驗證 Order 歸因鏈:session_id 匹配率、orderList prodOid 有效率、搜尋→下單商品交集
- 使用 Playwright MCP 實際攔截 KTM API payload 確認現行埋點行為
- dm_tableau.tableau_search_report_prodlist_prod_by_keyword
- dm_tableau.tableau_search_report_prodlist_session
- dw_analysis_record.kkday_ktm_journey_action
- Playwright MCP → api-ktm.kkday.com/api/v1/journey/action
核心發現
Click 掉落:前端將商品卡片元件從 ProductCard 改名為 ItemCard,SQL 硬編碼 page_component_name = 'ProductCard' 導致 95%+ click 被過濾。(ProdCardView 走推薦團隊的 XXXPg 路徑,不在 ListingPg 範圍內)
Order 掉落:~35% orderList 的 prodOid 變為 null + 同 session 搜尋→下單商品交集從 86% 崩潰至 9%,雙重影響。
session_id 重算機制本身沒有問題(匹配率穩定 88%),ConfirmdPg 事件量也正常(16-20K/天)。
上游資料鏈路
目標表 prod_by_keyword 的完整上游依賴關係
原始事件流
session 重算 + user_id 映射
search × click × order JOIN
最終聚合表
Click & Order 月趨勢
2025-03 起 total_click 開始下滑,2025-10 從 10 萬級驟降至千位數以下。total_order 從 2025-04 起持續下降,2025-10 後幾乎歸零。row_count 維持 5-6M/月,代表搜尋資料正常流入,問題出在 click 與 order 的匹配環節。
| 月份 | row_count | total_click | total_order |
|---|---|---|---|
| 2025-01 | 18,339,420 | 2,250,013 | 115,235 |
| 2025-02 | 15,997,698 | 1,952,820 | 99,977 |
| 2025-03 | 13,288,483 | 610,882 | 99,262 |
| 2025-04 | 2,309,099 | 56,423 | 16,765 |
| 2025-05 | 4,819,789 | 122,756 | 33,880 |
| 2025-06 | 6,280,400 | 264,207 | 20,151 |
| 2025-07 | 5,737,132 | 319,914 | 11,669 |
| 2025-08 | 5,239,376 | 288,967 | 9,975 |
| 2025-09 | 4,453,918 | 104,281 | 4,535 |
| 2025-10 | 6,161,964 | 1,602 | 39 |
| 2025-11 | 5,576,199 | 767 | 18 |
| 2025-12 | 6,037,718 | 465 | 15 |
| 2026-01 | 6,350,125 | 447 | 10 |
| 2026-02 | 5,728,297 | 307 | 5 |
資料來源與計算方式
SELECT FORMAT_DATE('%Y-%m', action_date) AS month,
SUM(total_click) AS total_click,
SUM(total_order) AS total_order,
COUNT(*) AS row_count
FROM `kkday-data-dap.dm_tableau.tableau_search_report_prodlist_prod_by_keyword`
WHERE action_date >= '2025-01-01'
GROUP BY month
ORDER BY month
影響嚴重度總覽
| 問題 | 影響指標 | 影響範圍 | 嚴重度 | 狀態 |
|---|---|---|---|---|
pageComponentName 改名 |
Click | ProductCard → ItemCard → ProdCardView,95%+ click 丟失 | Critical | 需修改 SQL 過濾條件 |
pageName 改為 XXXPg |
Click | 推薦團隊 Click 事件不走 ListingPg | Medium | 推薦團隊事件,暫不影響 |
orderList prodOid 變 null |
Order | ~35% 訂單丟失 prodOid,無法歸因 | High | 需前端確認原因 |
| 搜尋→下單 prod 交集崩潰 | Order | 匹配率從 86% 降至 9% | High | 用戶行為變化 + JOIN 過嚴 |
結論與下一步行動
Click 掉落根因
- page_component_name 從 ProductCard → ItemCard,SQL 未跟進更新(Critical)
- ProdCardView 屬於推薦團隊事件(走 XXXPg 路徑),不在 ListingPg 範圍內,暫不納入
Order 掉落根因
- ~35% 的 ConfirmdPg orderList prodOid 變為 null(2025-06 起)
- 同 session 搜尋→下單商品交集從 86% 降至 9%
立即可執行的修復
- Click:過濾改為 IN ('ProductCard', 'ItemCard')(ProdCardView 走 XXXPg,不在 ListingPg 範圍)
- Order:考慮放寬 session_id 限制,改用 user_id + prod_oid + 時間窗口歸因
- 修復後需回刷至少 2025-05 起的歷史資料
需跨團隊協調
- 與前端團隊確認 pageComponentName 命名規範,避免反覆改名
- 與前端團隊排查 35% orderList prodOid 為 null 的原因
- 與推薦團隊確認 XXXPg 事件的長期規劃
根因:page_component_name 改名
前端團隊從 2025 年中將搜尋結果頁的商品卡片元件從 ProductCard 改名為 ItemCard。目前最新版本則走推薦團隊的 XXXPg 路徑,元件名稱為 ProdCardView。
SQL 硬編碼 page_component_name = 'ProductCard'(tableau_search_report_prodlist_session.sql 第 78 行),導致 95%+ 的 click 事件被過濾掉。
這是 Click 下降的最主要原因。
| 日期 | ProductCard | ItemCard | 其他 |
|---|---|---|---|
| 2025-01-04 | 120,770 | 0 | 2,552 |
| 2025-06-04 | 11,452 | 62,976 | 12,947 |
| 2025-09-26 | 388 | 49,926 | 53,688 |
| 2026-01-04 | 34 | 85,115 | 22,598 |
資料來源與計算方式
SELECT DATE(action_time) AS dt,
page_component_name,
COUNT(*) AS cnt
FROM `kkday-data-dap.dw_analysis_record.kkday_ktm_journey_action`
WHERE (
(action_time >= '2025-01-04' AND action_time < '2025-01-05')
OR (action_time >= '2025-06-04' AND action_time < '2025-06-05')
OR (action_time >= '2025-09-26' AND action_time < '2025-09-27')
OR (action_time >= '2026-01-04' AND action_time < '2026-01-05')
)
AND page_name = 'ListingPg'
AND page_type = 'Click'
GROUP BY dt, page_component_name
ORDER BY dt, cnt DESC
Playwright 前端實測證據
透過 Playwright MCP 瀏覽器自動化工具,實際訪問搜尋頁面並攔截 KTM 追蹤 API 的請求 payload,確認前端埋點的真實行為。
透過 Playwright MCP 實際訪問 kkday.com/zh-tw/product/productlist/福島%20櫻花,
攔截 KTM API (api-ktm.kkday.com/api/v1/journey/action) 的 payload:
PageLoad 事件 — 正常
{
"pageName": "ListingPg",
"pageType": "PageLoad",
"productProperty": {
"prodList": [
{"prodOid": 535389, "prodName": "遊覽福島著名賞櫻景點..."},
{"prodOid": 535397, ...},
... (共 10 個商品)
]
}
}
pageName = ListingPg, pageType = PageLoad, prodList 正常攜帶商品資訊
Click 事件 — 異常
{
"pageName": "XXXPg",
"pageType": "Click",
"pageComponentName": "ProdCardView",
"recommendProperty": {
"targetId": "535389",
"sectionName": "ProdList"
}
}
pageName 從 ListingPg 變為 XXXPg(推薦團隊事件);pageComponentName 從 ProductCard 變為 ProdCardView
排除的假設
| 假設 | 驗證方式 | 結果 |
|---|---|---|
| ListingPg 的 Click 事件量本身減少 | 查詢 page_name = 'ListingPg' AND page_type = 'Click' 的總事件量 | 排除 — 事件量穩定,只是 page_component_name 改名 |
| Click 事件的 pageName 改為 XXXPg | Playwright 實測攔截 KTM API payload | 確認 — 但屬推薦團隊事件,非搜尋團隊的 bug |
Click 修復建議
SQL 修復
- Click 過濾條件(
prodlist_session.sql第 78 行):
現行:page_component_name = 'ProductCard'
建議:page_component_name IN ('ProductCard', 'ItemCard')
註:ProdCardView 走 XXXPg 路徑(推薦團隊事件),被 page_name = 'ListingPg' 過濾,不需納入 - page_name 過濾:維持
ListingPg,XXXPg為推薦團隊事件暫不納入
需前端/SDK 團隊確認
pageComponentName為何反覆改名(ProductCard → ItemCard → ProdCardView)?未來命名規範?- Click 事件走
XXXPg路徑的長期規劃(推薦團隊已確認是他們的事件)
根因 A:orderList prodOid 大量變 null
ConfirmdPg 事件的 consumerUxProperty.orderList 中,prodOid 從 2025-06 起有 ~35% 變為 null。SQL 透過 CAST(JSON_EXTRACT_SCALAR(order_item, '$.prodOid') AS INT64) 取得 prod_oid,null 值會被排除,導致訂單無法歸因到搜尋結果。
| 日期 | orderList 總數 | 有 prodOid | prodOid = null | 有效率 |
|---|---|---|---|---|
| 2025-01-04 | 13,080 | 13,004 | 76 | 99.4% |
| 2025-06-04 | 18,117 | 12,271 | 5,846 | 67.7% |
| 2025-09-26 | 17,028 | 10,622 | 6,406 | 62.4% |
| 2026-01-04 | 16,677 | 10,700 | 5,977 | 64.2% |
資料來源與計算方式
SELECT DATE(action_time) AS dt,
COUNT(*) AS total_order_items,
COUNTIF(JSON_VALUE(order_item, '$.prodOid') IS NOT NULL
AND JSON_VALUE(order_item, '$.prodOid') != 'null') AS has_prod_oid,
COUNTIF(JSON_VALUE(order_item, '$.prodOid') IS NULL
OR JSON_VALUE(order_item, '$.prodOid') = 'null') AS null_prod_oid
FROM `kkday-data-dap.dw_analysis_record.kkday_ktm_journey_action`,
UNNEST(JSON_EXTRACT_ARRAY(additional_json, '$.consumerUxProperty.orderList')) AS order_item
WHERE (...)
AND page_name = 'ConfirmdPg'
AND page_type = 'PageLoad'
GROUP BY dt
ORDER BY dt
根因 B:搜尋→下單商品交集崩潰
即使 session_id 匹配率穩定(88%),同一 session 內搜尋結果的 prod_oid 和下單的 prod_oid 重疊率卻從 86% 暴跌至 9%。
這代表用戶即使在同一 session 內完成搜尋和下單,最終購買的商品也不在搜尋結果的 prodList 中——可能是透過推薦、分類或相似商品等路徑找到商品,而非直接從搜尋結果點擊購買。
| 日期 | 同天搜尋+下單 kkud | 同 session_id | session 匹配率 | orderList prodOid 有效率 | 同 session prod 匹配率 |
|---|---|---|---|---|---|
| 2025-01-04 | 6,336 | 5,616 | 88.6% | 99.4% | 86.4% |
| 2026-01-04 | 5,111 | 4,513 | 88.3% | 64.2% | 8.8% |
資料來源與計算方式
-- session_id 匹配分析
WITH search_events AS (
SELECT DATE(action_time) AS dt, user_id, kkud, session_id, action_time
FROM `kkday-data-dap.dw_analysis_record.kkday_ktm_journey_action`
WHERE (...) AND page_name = 'ListingPg' AND page_type = 'PageLoad'
),
order_events AS (
SELECT DATE(action_time) AS dt, user_id, kkud, session_id, action_time
FROM `kkday-data-dap.dw_analysis_record.kkday_ktm_journey_action`
WHERE (...) AND page_name = 'ConfirmdPg' AND page_type = 'PageLoad'
)
SELECT s.dt,
COUNT(DISTINCT s.kkud) AS kkuds_with_both,
COUNT(DISTINCT CASE WHEN s.session_id = o.session_id THEN s.kkud END) AS same_session,
...
FROM search_events s JOIN order_events o ON s.kkud = o.kkud AND s.dt = o.dt
WHERE o.action_time > s.action_time
GROUP BY s.dt
排除的假設
| 假設 | 驗證方式 | 結果 |
|---|---|---|
| session_id 格式改變 | 比較不同時期 session_id 的 LENGTH 和格式 | 排除(UUID 36 字元,格式一致) |
| session_id 重算機制故障 | 比較 ListingPg ↔ ConfirmdPg 的 session_id 匹配率 | 排除(88.6% → 88.3%,穩定) |
| ConfirmdPg page_name 改名 | 查 ConfirmdPg 事件量趨勢 | 排除(一直是 ConfirmdPg,16-20K/天) |
| user_id 映射異常 | 比較同天搜尋+下單的 kkud,檢查 user_id 一致性 | 排除(99.5% user_id 一致) |
| orderList JSON 結構改變 | 檢查 consumerUxProperty.orderList 解析結果 | 排除(解析正常) |
Order 修復建議
SQL 修復
- Order JOIN 條件:考慮放寬
session_id限制,改用user_id + prod_oid + 時間窗口進行歸因 - 處理 prodOid null:排除
prodOid IS NULL的訂單項目,或改用order_master_mid關聯
需前端/SDK 團隊確認
- 35% ConfirmdPg orderList 的
prodOid為何是 null?何時改變的? - 搜尋→下單路徑中,用戶是否越來越多走推薦/分類頁下單而非搜尋結果頁?
分析方法說明
透過逐層追蹤上游資料鏈路(prod_by_keyword → prodlist_session → kkday_ktm_journey_action → ktm_stream_action),結合 BigQuery 數據查詢與 Playwright 前端實測,定位 click 和 order 數據下降的根本原因。