Coolkid mascot CoolkidLab

SEO 菜鳥成長史 · #3 · 最後更新:2026-05-11

GA4 + GSC 終於裝完:CSP 把 Google Analytics 擋掉的踩雷全紀錄

從 v0.3 上架到今天剛好第 5 天。終於把 GA4 + GSC 都裝上去。

原本以為是「複製貼上 5 分鐘」的小事。實際做完才發現中間有個讓我笑出來的鍋——是我自己半個月前埋的。

這篇紀錄整套裝 GA4 + GSC 的步驟、踩到的 CSP 陷阱、以及這個陷阱怎麼讓 28 個頁面的 GA 一起啞掉。

1. 為什麼這篇值得寫

GA4 安裝教學一抓一大把,但 95% 的文章只講三件事:

對於用 WordPress + 外掛的人,這樣確實 5 分鐘就好。但靜態站、自己 build、又有資安潔癖鎖了 CSP 的人——你會發現貼進去之後 console 一片紅,GA 完全沒反應,然後查半天還以為是自己貼錯位置。

這篇的核心不是「怎麼貼 GA」,是「為什麼貼了 GA 卻沒反應」、以及「GA + GSC 的整套裝法」。

2. 第一刀:GA4 帳戶開到拿 G ID(10 分鐘)

GA4 後台流程乾淨,跟著走基本不會出錯:

  1. 進 analytics.google.com → 建立帳戶 → 帳戶名稱填品牌名
  2. 建立資源 → 屬性名稱填品牌名(不要塞 URL 或「GA4」字樣,這是給自己之後辨識用的標籤)
  3. 時區選台灣、貨幣選新台幣
  4. 業務目標問你想看什麼,按需求勾
  5. 資料串流選「網站」→ 填 URL 跟串流名稱

走完會拿到一組 G-XXXXXXXXXX 開頭的 Measurement ID,這個 ID 一輩子不會變,複製存好。

後台會跳一個 modal 給你 gtag.js 的安裝程式碼。這段才是真正的戰場。

3. 第二刀:CSP 把 GA 擋掉的鍋(這篇的主菜)

我這站的 head 不是手動寫每一頁,是有 build.py 一次注入所有頁面。所以「貼程式碼」實際上是改 page_shell() 函式裡 head 的 template。

把 GA4 的 ID 拉成常數放檔頂,head template 在 </head> 之前加兩段:

GA4_ID = "G-XXXXXXXXXX"

# 在 page_shell() 的 </head> 之前
<script async src="https://www.googletagmanager.com/gtag/js?id={GA4_ID}"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '{GA4_ID}');
</script>

跑 python build.py,28 個 html 全部重生,每頁都帶 G ID。git push,Vercel 自動部署。回 GA4 後台等資料。

等了 5 分鐘——還是 0。打開網站,按 F12 開 console,畫面一片紅:

Refused to load the script
'https://www.googletagmanager.com/gtag/js?id=G-XXXX'
because it violates the following Content Security Policy directive:
"script-src 'self' 'unsafe-inline'"

兇手就很明顯了。是我半個月前在 vercel.json 鎖的 CSP(資安潔癖的鍋)。當時的 script-src 只允許「來自自家站」跟「inline」兩種來源,googletagmanager.com 不在白名單裡,瀏覽器直接拒載。

(1)什麼是 CSP

Content-Security-Policy 是 HTTP header,告訴瀏覽器「這個網站只准載入哪些來源的 script / style / 圖 / 字體 / 連線」。鎖緊了能擋掉 XSS 攻擊跟惡意第三方腳本,但鎖太死自己想用的服務也會被鎖在門外。

vercel.json 裡的 CSP 大概長這樣(節選):

"Content-Security-Policy":
  "default-src 'self';
   script-src 'self' 'unsafe-inline';
   ... (其他 directives)"

GA 要載 gtag.js(外部 script)、又要把資料 POST 回 google-analytics.com(外部 connect),這兩個權限都要顯式開放。

(2)正確的 CSP 修法

丟給 agent 一次改完 vercel.json,把兩個 directive 加上 GA 相關的網域:

script-src 'self' 'unsafe-inline'
  https://www.googletagmanager.com;

connect-src 'self'
  https://*.supabase.co
  https://www.google-analytics.com
  https://*.analytics.google.com
  https://*.googletagmanager.com;

重點:

重新 commit、push。Vercel 部署完,回網站重整、F12 console 一片乾淨。GA4 後台「過去 30 分鐘活躍使用者」終於亮 1——那 1 個就是我自己。

4. 第三刀:GSC 串接 + sitemap 提交 + 資料保留

GA 跑起來只是第一塊。要看到「有人從 Google 搜尋什麼進站」要把 GSC 串進來。三件小事一次做:

(1)GA4 ↔ GSC 串接

GA4 後台 → 管理(左下齒輪)→ 產品連結 → Search Console 連結 → 選 GSC 資源 → 選網站串流 → 提交。

串完之後,GA 報表會多兩塊:「探索 → 範本庫 → Search Console 報表」可以看查詢字、CTR、平均排名;「獲客 → 流量獲取」會多一條 google / organic 細分到具體搜尋查詢。

為什麼一定要串:原本 GSC 只能看「誰找到我」,GA 只能看「進來之後幹嘛」,兩邊資料各看各的。串接後接在一起——找到我的查詢字,配上他進站後的停留 / 互動 / 轉換——這才是 SEO 真正能拿來判斷的數字。

(2)GSC 提交 sitemap

GSC 後台 → 索引 → Sitemap → 加新的 sitemap → 輸入「sitemap.xml」→ 提交。一次解掉「Google 知不知道我的站有哪些頁」這個問題。

提醒:sitemap 提交不等於「立刻被收錄」。GSC 會跟你說「成功讀取」就好,實際進索引還要等幾天到幾週。這個我之前 #1 那篇有寫過完整流程。

(3)資料保留改 14 個月

GA4 預設「事件層級資料」只保留 2 個月。對個人站等於每兩個月就洗掉一次歷史,看不到趨勢。

GA4 後台 → 管理 → 資源設定 → 資料保留 → 改 14 個月(免費上限)。這個沒成本沒副作用,所有人都該開到滿。

5. 最終戰績

項目做完前做完後
GA4 安裝未裝 ❌28 頁全帶 ✅
GSC 串接未串 ❌已串 ✅
Sitemap 提交未提交 ❌已提交 ✅
資料保留2 個月(預設)14 個月 ✅
CSP whitelist太緊 ❌正確開放 GA 端點 ✅

6. 我從這個過程學到什麼

三件事:

  1. 「複製貼上 5 分鐘」的教學文,前提是「跟教學文寫的環境一樣」。我有自己的 build 系統 + 自己鎖過的 CSP,原本的範本就會卡。
  2. 出問題第一步打開 F12 console。瀏覽器幾乎一定會把擋掉的請求印出來告訴你原因,不用猜。
  3. 同一次 commit 修兩個檔(build.py + vercel.json)才能上線。少改一個 push 上去 GA 就裝了等於沒裝,浪費一次部署。

這跟我做交易學到的東西一樣:訊號出現不代表能直接下單,要看跟你的部位 / 環境合不合。一個普世的 setup,遇到自己的特殊環境一樣會卡。

7. 給跟我一樣從 0 開始的人:6 步驟 checklist

如果你的站也準備裝 GA4 + GSC,按這個順序走:

  1. GA4 後台建立資源、拿到 G-XXXXXXXXXX
  2. 把 gtag.js script 加到網站 (靜態站找你的 head template / build script,不要每個 html 手貼)
  3. 如果有設 CSP,script-src 加 https://www.googletagmanager.com、connect-src 加三個 GA 端點
  4. Push 上線,回 GA4 後台「過去 30 分鐘」看自己有沒有亮起來;沒亮就 F12 看 console 找原因
  5. GA4 ↔ GSC 串接、GSC 提交 sitemap、資料保留改 14 個月,三件事一次做完
  6. 確認 robots.txt 沒擋 Googlebot、sitemap.xml URL 都是 200

整套順利做完大概 30 分鐘。我這次因為踩了 CSP 鍋,多花了大概 20 分鐘。但下一次任何站都不會再被同一個鍋打到。

8. 下一步

GA + GSC 裝完只是「裝好監視器」。預設只追 page_view,看得到「有沒有人來」,但看不到「他來了之後幹嘛」。

白老鼠實驗下一篇 #4 會做自訂事件 + 轉換追蹤:定義「滑到底」「點 CTA」「停留 60 秒以上」這些行為訊號,再標哪些算重要事件、哪些算轉換。等於把監視器升級成「能告訴你誰是真讀者、誰只是路過」的版本。

看完這篇之前先確認:

適合你
  • 剛裝 GA4 但 console 一片紅的人
  • 用 Vercel + 自己鎖 CSP 的靜態站
  • GA + GSC 想一次到位的人
不適合
  • 完全還沒裝 GA4 的人(先看 #0 gsc-basics)
  • 用 Plausible / Umami 等替代分析的人
  • WordPress + 外掛全自動的人
最常踩
  • 只開 google.com 忘了 googletagmanager.com
  • 改完 vercel.json 沒重新 deploy
  • 漏掉 fonts.googleapis.com / gstatic.com

相關閱讀

這篇背後的真實開發過程記錄在 Build Log搜尋標籤:ga4gsccspvercel

本篇為個人學習與實驗紀錄。GA4 / GSC 介面與 CSP 規範持續變動,本文步驟不保證在你的網站環境完全相同,請依自身狀況實驗驗證。本站不接 YMYL 高風險站、不做 PBN、不做品牌矩陣 SEO。

← 回 SEO 菜鳥成長史

⚠ 本站所有內容僅供教育與研究用途,不構成投資建議,不保證任何獲利。投資有風險,使用者須自行判斷並承擔結果。