搜尋報表 Click/Order 下降根因分析

tableau_search_report_prodlist_prod_by_keyword | 2025-01 ~ 2026-02
KKday Data Team
Generated: 2026-03-09 02:42

分析脈絡

對應提問
為什麼 tableau_search_report_prodlist_prod_by_keyword 從 2025 下半年開始,total_click 和 total_order 大幅下降?
拆解方式
  1. 查詢 prod_by_keyword 月趨勢,定位斷裂時間點
  2. 追蹤上游 Click 事件的 page_component_name 分佈變化
  3. 驗證 Order 歸因鏈:session_id 匹配率、orderList prodOid 有效率、搜尋→下單商品交集
  4. 使用 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
資料區間
2025-01 ~ 2026-02

核心發現

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 的完整上游依賴關係

ktm_stream_action
原始事件流
kkday_ktm_journey_action
session 重算 + user_id 映射
prodlist_session
search × click × order JOIN
prod_by_keyword
最終聚合表

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
資料來源與計算方式
SQL 查詢
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
關鍵發現
2025-01:ProductCard 佔 98%(120,770 次)。到 2025-09:ProductCard 僅剩 388 次(< 0.4%),ItemCard 有 49,926 次。2026-01:ProductCard 僅 34 次,ItemCard 85,115 次。SQL 的硬編碼過濾條件導致幾乎所有 click 被丟棄。
資料來源與計算方式
SQL 查詢
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 修復

  1. Click 過濾條件prodlist_session.sql 第 78 行):
    現行:page_component_name = 'ProductCard'
    建議:page_component_name IN ('ProductCard', 'ItemCard')
    註:ProdCardView 走 XXXPg 路徑(推薦團隊事件),被 page_name = 'ListingPg' 過濾,不需納入
  2. page_name 過濾:維持 ListingPgXXXPg 為推薦團隊事件暫不納入

需前端/SDK 團隊確認

  1. pageComponentName 為何反覆改名(ProductCard → ItemCard → ProdCardView)?未來命名規範?
  2. 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%
關鍵發現
prodOid 有效率從 99.4%(2025-01)驟降至 67.7%(2025-06),之後穩定在 62-64%。約三分之一的訂單因缺少 prodOid 而完全無法被歸因。
資料來源與計算方式
SQL 查詢
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 匹配率 88% → 88%(穩定),但 prodOid 有效率從 99% 降至 64%,同 session prod 匹配率從 86% 降至 9%。Order 下降是 prodOid null + 商品交集崩潰的雙重影響。
資料來源與計算方式
SQL 查詢
-- 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 修復

  1. Order JOIN 條件:考慮放寬 session_id 限制,改用 user_id + prod_oid + 時間窗口 進行歸因
  2. 處理 prodOid null:排除 prodOid IS NULL 的訂單項目,或改用 order_master_mid 關聯

需前端/SDK 團隊確認

  1. 35% ConfirmdPg orderList 的 prodOid 為何是 null?何時改變的?
  2. 搜尋→下單路徑中,用戶是否越來越多走推薦/分類頁下單而非搜尋結果頁?

分析方法說明

透過逐層追蹤上游資料鏈路(prod_by_keyword → prodlist_session → kkday_ktm_journey_action → ktm_stream_action),結合 BigQuery 數據查詢與 Playwright 前端實測,定位 click 和 order 數據下降的根本原因。