「BigQuery?那不是大公司才用的東西嗎?」
很多人聽到 BigQuery 就覺得遙不可及,覺得那是 Netflix、Airbnb 這種等級的公司才需要的基礎設施。但實際上,GA4 免費版就內建 BigQuery 串接功能,而且 Google Cloud 的免費方案對一般網站的資料量來說幾乎夠用。
GA4 的標準報表有很多限制:資料最長只保留 14 個月、探索報表有取樣限制、某些複雜的多維度查詢做不到。把資料匯出到 BigQuery,這些限制就消失了——你可以查詢任意時間範圍、零取樣、用 SQL 做你想要的任何分析。
1. 為什麼需要 BigQuery
先說清楚,如果你的網站月流量在 5 萬以下,而且你只需要基本的流量分析,GA4 標準報表大概就夠了。但以下幾種情況,BigQuery 幾乎是必要的:
GA4 的資料保留限制:探索報表的原始事件數據只保留 14 個月。如果你需要做年對年的詳細分析,或是要追蹤超過一年的用戶生命週期,就需要把資料匯出到 BigQuery 長期保存。
資料取樣問題:GA4 的探索報表在資料量超過一定門檻時會啟用取樣,也就是用一部分數據代表全部,分析結果不夠精確。BigQuery 的查詢是對完整的原始數據做運算,沒有取樣問題。
複雜查詢:GA4 的介面讓你只能做它設計好的分析維度組合。但有時候你需要的分析很客製化——例如「在 30 天內訪問了 A 頁面超過 3 次、且購買了 B 產品、但沒有開啟 C 優惠券的用戶,他們的後續行為是什麼」,這種查詢在 GA4 介面做不到,用 SQL 很直觀。
整合其他數據源:BigQuery 可以把 GA4 數據和你的 CRM、訂單系統、廣告數據整合在一起做分析,這是 GA4 介面永遠做不到的事情。
根據一份針對電商分析師的調查,有 73% 的受訪者表示他們把 GA4 串接 BigQuery 最主要的原因是「需要整合多個數據源」,第二名是「歷史資料保留」(58%)。
2. 串接步驟
前置準備:
- 一個 Google Cloud Platform(GCP)帳戶(第一次申請有免費試用額度)
- GA4 的「編輯者」權限
- 一個 BigQuery 專案(在 GCP Console 建立)
步驟一:建立 GCP 專案和啟用 BigQuery
- 前往 console.cloud.google.com
- 建立新專案(或使用現有專案)
- 在左側選單搜尋「BigQuery」,進入並確認已啟用 BigQuery API
步驟二:在 GA4 設定 BigQuery 連結
- GA4 → 管理 → 產品連結 → BigQuery 連結
- 點「連結」
- 選擇你的 GCP 專案
- 選擇資料位置(建議選亞太地區,例如
asia-east1台灣、asia-southeast1新加坡) - 設定匯出頻率:
- 每日匯出:每天把前一天的資料批次匯出
- 串流匯出:幾乎即時匯出(需要 BigQuery 的串流計費,費用較高)
- 選擇要匯出的事件(可以選全部或特定事件)
- 儲存連結
設定完成後,第一批資料通常在 24 小時內開始匯出。
注意事項:資料匯出到 BigQuery 後,BigQuery 的儲存和查詢費用由你的 GCP 帳戶負擔,GA4 本身是免費的。
3. GA4 在 BigQuery 的資料結構
理解資料結構是寫 SQL 查詢的前提。
資料集和表格命名:
- 資料集名稱:
analytics_{PROPERTY_ID}(例如analytics_123456789) - 表格命名:
events_YYYYMMDD(例如events_20260319) - 另有
events_intraday_*表格存放當天即時的資料
每個 Event 記錄的結構:
GA4 在 BigQuery 的資料是「巢狀結構(Nested Structure)」,每一行是一個事件,事件參數存在 event_params 欄位裡,它是一個陣列。這和一般的關聯式資料庫表格不太一樣,需要用 BigQuery 的 UNNEST 語法來展開。
主要欄位:
| 欄位 | 說明 |
|---|---|
event_date |
事件日期(格式 YYYYMMDD) |
event_timestamp |
事件時間戳(微秒) |
event_name |
事件名稱 |
event_params |
事件參數陣列(RECORD 類型) |
user_id |
自訂 User ID(如果有設定) |
user_pseudo_id |
GA4 自動生成的匿名用戶 ID |
geo |
地理位置資訊 |
device |
裝置資訊 |
traffic_source |
流量來源(首次工作階段的來源) |
user_properties |
用戶屬性陣列 |
4. 5 個入門 SQL 查詢範例
查詢 1:計算特定日期範圍的頁面瀏覽量
SELECT
event_date,
COUNT(*) AS page_views
FROM
`your-project.analytics_123456789.events_*`
WHERE
_TABLE_SUFFIX BETWEEN '20260101' AND '20260319'
AND event_name = 'page_view'
GROUP BY
event_date
ORDER BY
event_date
查詢 2:取出頁面 URL 和各頁面的瀏覽次數
SELECT
(SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'page_location') AS page_url,
COUNT(*) AS views
FROM
`your-project.analytics_123456789.events_*`
WHERE
_TABLE_SUFFIX = '20260319'
AND event_name = 'page_view'
GROUP BY
page_url
ORDER BY
views DESC
LIMIT 20
查詢 3:計算各流量來源的工作階段數
SELECT
traffic_source.source,
traffic_source.medium,
COUNT(DISTINCT CONCAT(user_pseudo_id, (SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'ga_session_id'))) AS sessions
FROM
`your-project.analytics_123456789.events_*`
WHERE
_TABLE_SUFFIX BETWEEN '20260301' AND '20260319'
GROUP BY
traffic_source.source,
traffic_source.medium
ORDER BY
sessions DESC
查詢 4:找出購買用戶的首次接觸來源
SELECT
user_pseudo_id,
MIN(event_date) AS first_visit_date,
MAX(CASE WHEN event_name = 'purchase' THEN event_date END) AS purchase_date,
MAX(CASE WHEN event_name = 'purchase' THEN (SELECT value.double_value FROM UNNEST(event_params) WHERE key = 'value') END) AS purchase_value,
ARRAY_AGG(traffic_source.source ORDER BY event_timestamp LIMIT 1)[OFFSET(0)] AS first_touch_source
FROM
`your-project.analytics_123456789.events_*`
WHERE
_TABLE_SUFFIX BETWEEN '20260101' AND '20260319'
GROUP BY
user_pseudo_id
HAVING
purchase_date IS NOT NULL
ORDER BY
purchase_value DESC
查詢 5:計算用戶的 30 天留存率
WITH first_visits AS (
SELECT
user_pseudo_id,
MIN(event_date) AS first_visit_date
FROM
`your-project.analytics_123456789.events_*`
WHERE
_TABLE_SUFFIX BETWEEN '20260101' AND '20260319'
GROUP BY
user_pseudo_id
),
return_visits AS (
SELECT DISTINCT
e.user_pseudo_id,
f.first_visit_date
FROM
`your-project.analytics_123456789.events_*` e
JOIN
first_visits f ON e.user_pseudo_id = f.user_pseudo_id
WHERE
_TABLE_SUFFIX BETWEEN '20260101' AND '20260319'
AND PARSE_DATE('%Y%m%d', e.event_date)
BETWEEN DATE_ADD(PARSE_DATE('%Y%m%d', f.first_visit_date), INTERVAL 25 DAY)
AND DATE_ADD(PARSE_DATE('%Y%m%d', f.first_visit_date), INTERVAL 35 DAY)
)
SELECT
f.first_visit_date,
COUNT(DISTINCT f.user_pseudo_id) AS total_users,
COUNT(DISTINCT r.user_pseudo_id) AS retained_users,
ROUND(COUNT(DISTINCT r.user_pseudo_id) / COUNT(DISTINCT f.user_pseudo_id) * 100, 2) AS retention_rate
FROM
first_visits f
LEFT JOIN
return_visits r ON f.user_pseudo_id = r.user_pseudo_id
GROUP BY
f.first_visit_date
ORDER BY
f.first_visit_date
5. 費用估算
BigQuery 的費用分兩部分:儲存費用和查詢費用。
免費額度(每月重置):
- 儲存:前 10 GB 免費
- 查詢:前 1 TB 的查詢資料量免費
超過免費額度的費用:
- 儲存:約 $0.02 美元 / GB / 月
- 查詢:約 $5 美元 / TB(掃描的資料量)
一般網站的費用估算:
月流量 10 萬的網站,每天大約產生 50-100 MB 的 GA4 事件資料。一年累積約 18-36 GB,儲存費用大約每月 $0.5-0.7 美元。查詢費用取決於你的查詢頻率和效率——善用 BigQuery 的分區(Partition)和叢集(Cluster)特性,可以大幅減少每次查詢掃描的資料量,把費用控制在很低的範圍內。
如果你是第一次申請 GCP,Google 提供 $300 美元的免費試用額度,可以用來學習和測試,不用擔心費用問題。
費用控制小技巧:
- 查詢時盡量指定
_TABLE_SUFFIX BETWEEN限定日期範圍,避免掃描所有歷史表格 - 用
SELECT指定需要的欄位,不要用SELECT *(GA4 的表格欄位很多,SELECT *會掃描大量不需要的資料) - 建立物化視圖(Materialized View)儲存常用的彙總結果
6. FAQ
Q:我沒學過 SQL,可以用 BigQuery 嗎?
A:BigQuery 的基本 SQL 語法入門門檻不高,網路上有大量免費的學習資源。特別是 GA4 的常用查詢,只需要掌握 SELECT、FROM、WHERE、GROUP BY 和 UNNEST 這幾個語法就能做大部分的分析。如果你完全不想寫 SQL,也可以考慮用 Looker Studio 連接 BigQuery,用拖拉介面做視覺化,或是用 AI 輔助生成 SQL 查詢。
Q:串接 BigQuery 後,GA4 的標準報表還能正常使用嗎?
A:完全可以,兩者是平行的,互不影響。GA4 標準報表照樣使用,BigQuery 只是多了一個原始數據的備份和進階分析管道。實務上,日常監控用 GA4 標準報表,需要深度分析時才去 BigQuery 查詢,是最常見的工作模式。
Q:歷史資料可以補匯出到 BigQuery 嗎?
A:GA4 的 BigQuery 串接只從設定日期開始匯出,不能把過去的歷史數據補匯出。這就是為什麼建議越早設定越好。不過,如果你有在用其他分析工具(例如 Mixpanel、Amplitude),或是你的後端資料庫有存 GA4 的 Measurement Protocol 發送紀錄,有辦法用其他方式重建部分歷史數據,但這比較複雜,不在本文討論範圍。
BigQuery 串接是 GA4 進階使用的重要一步,更多 GA4 基礎知識可以先看 GA4 完整入門指南。在 BigQuery 裡分析自訂業務數據之前,記得先設好 GA4 自訂維度。複雜的探索分析也可以直接在 GA4 的 探索報表 進行。