Google Tag Manager:追蹤碼的部署層、資料層約定與發布治理
這篇整理 Google Tag Manager(GTM)在網站追蹤架構裡的位置:它在頁面上做什麼、前端工程與行銷人員之間靠什麼約定交接事件、發布前怎麼驗證,以及它帶進來的治理成本。範圍是網頁容器(web container)與伺服器端代碼管理(server-side tagging)的資料路徑;GTM 後台每個選單怎麼操作不在這篇,介面以 Google 的說明文件為準。
GTM 承擔的責任:追蹤碼的部署
GTM 是一個在頁面上執行的追蹤碼載入器,分析資料由它載入的各家代碼收集:網站放一段容器片段(container snippet),頁面載入時從 googletagmanager.com 下載這個容器目前發布的設定,再依設定決定在什麼時機載入哪些追蹤碼。設定由三種元件組成:
- 代碼(tag):要執行的追蹤碼,例如 GA4 的設定、Meta Pixel、一段自訂的 JavaScript。
- 觸發條件(trigger):代碼在什麼時候執行,例如每一頁載入時、某個按鈕被點擊時、資料層 出現某個事件時。
- 變數(variable):代碼執行時要讀的值,例如目前頁面的網址、資料層 裡的訂單金額。
GTM 存在的理由是部署權的轉移。沒有 GTM 時,行銷要加一個廣告平台的像素,得請前端改程式、走一次發版;有了 GTM,行銷在後台加代碼、按發布,網站程式不用動。這個轉移同時是 GTM 所有成本的來源:GTM 容器裡的代碼從此也在網站上執行,而它們不經過工程團隊的程式碼審查與版本控制。
資料層:頁面與容器之間的事件約定
GTM 讀取網站狀態有兩種方式:從頁面的 DOM 抓(某個 CSS class 的按鈕被點擊、某個元素的文字),或讀網站主動推進來的資料。網站主動推送資料的載體是資料層(資料層)——頁面上的一個全域陣列 window.dataLayer,網站在事件發生時往裡面推一個物件:
1// 訂單建立成功之後由前端程式推入;event 是 GTM 觸發條件比對的事件名稱
2window.dataLayer = window.dataLayer || [];
3window.dataLayer.push({
4 event: 'purchase',
5 order_id: 'order-20261022-0042', // 送往各家時當去重 ID 用
6 value: 1280,
7 currency: 'TWD'
8});event 這個鍵的值會被 GTM 的自訂事件觸發條件(Custom Event trigger)比對,名稱對上的代碼就執行,沒有任何觸發條件對上的事件只留在陣列裡、不產生請求(擷取紀錄見 用 Playwright 擷取追蹤碼請求 的 GTM 那一則);其餘的鍵可以在 GTM 裡建成 資料層 變數,讓代碼讀取。purchase、order_id 這些名稱由網站自己決定,GTM 不規定,所以它們要被當成一份 schema 管理:誰新增了哪個事件、欄位的型別與意義、改名時哪些代碼會受影響。事件命名規範 與 Schema 版本演進策略 的做法同樣適用在這份約定上。
兩種讀法的差別在前端改版的時候浮現。靠 DOM 抓的觸發條件綁在 CSS selector 上,前端重構把按鈕的 class 改名,觸發條件就不再命中,GTM 不報錯、事件安靜地消失,通常要等行銷發現報表的數字掉下來才會有人查。資料層 的推送寫在前端程式裡,改版時跟著程式碼一起被審查,所以分工會落成:前端工程負責在對的時機推對的事件,行銷負責把事件接到哪幾家代碼。
order_id 在這裡同時服務 Meta Pixel 與 Conversions API 的去重:GTM 裡的 Meta Pixel 代碼把它填進 eventID,伺服器端用同一個值送 Conversions API。
預覽模式與版本發布的驗證
GTM 的變更要先驗證再發布,驗證工具是預覽模式(Preview,在 Tag Assistant 裡開啟)。開啟後,這個瀏覽器載入網站時會用工作區裡還沒發布的設定,並在旁邊列出這次瀏覽依序發生的 資料層 事件;點選任一個事件,可以看到那個時間點哪些代碼執行了、哪些沒執行,以及每個變數當時的值。預覽模式靠 cookie 運作,只影響開啟它的那個瀏覽器,其他讀者看到的仍是已發布的版本。
驗證一個購買事件時,操作一次測試購買,在預覽模式裡確認 purchase 事件出現、該執行的代碼都在「已觸發」那一欄、資料層 變數讀到的金額與訂單相符。代碼送出的內容再到各家自己的驗證工具確認(GA4 的 DebugView、Meta 的 Test Events),因為預覽模式只看得到代碼有沒有執行,看不到對方的後台有沒有收到。
GTM 有自己的版本紀錄:每次發布產生一個版本,可以比對兩個版本的差異、退回前一版。這份紀錄在 GTM 的後台裡,不在網站的 git 裡,所以網站程式的變更與追蹤設定的變更分住兩處。出事時要對時間軸的人得兩邊都查:某天轉換數掉了,可能是前端那天發版改了 資料層,也可能是有人那天在 GTM 發布了一個新版本。
自訂 HTML 代碼的安全與效能成本
GTM 的代碼類型裡有一種自訂 HTML(Custom HTML),內容是任意的 HTML 與 JavaScript,發布後會在每一個符合觸發條件的頁面上執行。這代表 GTM 容器的發布權限等同於在網站上執行任意程式碼的權限:一個帳號被盜、或一段從廣告商複製來的程式碼帶有錯誤或惡意行為,影響的是所有讀者,而這段程式碼從來沒有進過程式碼審查。治理上要控制的因此是權限:誰能發布(GTM 把編輯與發布分成不同的權限等級)、發布前誰審過、自訂 HTML 的內容有沒有人讀過。
網站有設內容安全政策(Content Security Policy,CSP)時,GTM 要求的放行範圍也是這個成本的一部分:容器本身要放行 googletagmanager.com,自訂 HTML 注入的 inline script 要靠 nonce 或放寬 script-src 才能執行,每多接一家代碼還要再放行那一家的網域。放寬 CSP 讓 GTM 正常運作,同時也放寬了它原本要擋的那一類注入。
效能面的成本來自每一個代碼都是一段第三方 script。GTM 讓加代碼變得很便宜,所以容器裡的代碼數量只增不減,停用的廣告活動留下的像素很少有人回頭刪。定期盤點的做法是在預覽模式裡走一次主要頁面,列出實際執行的代碼與它們載入的網域,對照目前還在使用的服務。
伺服器端代碼管理改變的資料路徑
網頁容器的每個代碼都從讀者的瀏覽器直接送資料給各家 vendor。伺服器端代碼管理在中間多放一個伺服器容器(server container),通常架在網站自己的子網域上:瀏覽器只把事件送到這個子網域一次,伺服器容器再轉送給 GA4、Meta Conversions API 等目的地。
這條路徑帶來三個變化。事件送往網站自己的網域,避開以已知追蹤網域為對象的攔截清單;資料送出去之前會先經過自己控制的伺服器,可以在那裡拿掉不該送給第三方的欄位(作法同 SDK redaction helper 在 SDK 送出前做的遮蔽);cookie 由自己的伺服器以 HTTP header 寫入,比 JavaScript 寫入的 cookie 受瀏覽器追蹤防護的限制少;這一項有前提:伺服器所在的子網域,它的 CNAME 或 IP 位址與網站主站不同、而指向第三方時(例如子網域以 CNAME 指到雲端服務的網域,而主站不在那裡),Safari 會把它寫的 cookie 期限壓到 7 天;與主站解析到同一個 CNAME 或 IP 範圍時不受這條限制(規則見 First-party Cookie(第一方 cookie))。代價是那台伺服器要自己跑:GTM 的伺服器容器部署在 Cloud Run 或自己的主機上,流量、費用與可用性都回到自架 collector 要面對的那些事,見 Ingestion Scaling。
伺服器容器的預覽模式驗證的是另一段:它列出伺服器收到的請求、解析出的事件資料,以及轉送給各家的請求。網頁容器的預覽模式確認瀏覽器有送,伺服器容器的預覽模式確認轉送的內容對,兩段要分別驗。
容器載入、資料層事件與代碼送出的請求,可以在 Google Tag Manager 實測頁 填入測試容器的 ID 實際觸發一次。容器屬於哪一個帳戶、帳戶與容器的權限分級,以及把容器移到另一個帳戶時要匯出匯入、網站上的容器 ID 跟著換的處理,見 追蹤資產的歸屬。
#monitoring #vendor #google-tag-manager #gtm #data-layer #tracking