---
title: "導入 Google Tag Manager (GTM) 取代內嵌 GA"
description: "介紹 Google Tag Manager 的運作方式、環境與版本管理，並整理從內嵌 Google Analytics 遷移到 GTM 的實作步驟。"
lang: "zh-Hant-TW"
tags: ["GTM", "Measurement"]
pubDate: 2021-01-26T00:00:00.000Z
---

## Google Tag Manager 簡介

### 產品理念

RD 只要嵌一次 code，後面要修改，都只要行銷或 PM 或任何想新增監測的人在 Web GUI 上面操作就可以了，不需要改 code

### 運作方式

在 HTML 中嵌入一段 snippet，裡面會去載入並執行位於 `https://www.googletagmanager.com/gtm.js?id=GTM-XXXXXXXX` 的 js file。

```jsx
// The Google Tag Manager snippet
(function (w, d, s, l, i) {
  w[l] = w[l] || [];
  w[l].push({
    "gtm.start": new Date().getTime(),
    event: "gtm.js",
  });
  var f = d.getElementsByTagName(s)[0],
    j = d.createElement(s),
    dl = l != "dataLayer" ? "&l=" + l : "";
  j.async = true;
  j.src = "https://www.googletagmanager.com/gtm.js?id=" + i + dl;
  f.parentNode.insertBefore(j, f);
})(window, document, "script", "dataLayer", "GTM-XXXXXXXX");
```

透過 [`https://tagmanager.google.com`](https://tagmanager.google.com/) Web GUI publish to `Live` environment，就會動態改變上面那個 js file 的內容

### Glossary

#### Container

- GTM 的管理單位，一個 container 會有一個 id，以及會產生一組對應的 code snippet，要放在 html 網頁中。
- 在 container 中透過設定各種 tags, variables, triggers 達到想要的功能
  ![screenshot/_2021-01-27_7.12.13.png](https://tech.mincontent.com/_astro/_2021-01-27_7.12.13.DGALLjDG_Z9ne96.webp)
- 一個 account 可以開多個 containers。一個頁面也可以嵌多個 containers。

#### Tags

- 一個 tag 可以想成是一個 action。例如讓頁面載入指定 id 的 GA 的設定檔，或是發出帶某些參數的 GA event 到某個 tracking property。
- 這些行為需要使用的參數，可以用下面的 Variables 設定。
- Tag 會綁定 Triggers 來指定發動的時機。

#### Variables

- 可以取用包括 GTM 的環境變數、網頁載入時的 metadata（例如 url）、或是可以自訂變數常數。

#### Triggers

- 用來設定觸發 tags 執行的條件或事件，有內建的 trigger 可選，例如 `DOM ready`

### 實際使用

#### 版本管理

- workspaces: 共享的 staging area（有點像 git 的 staging area）。 workspaces 編輯內容儲存後是會即時同步的。
- versions: 在 staging area 的 changes 可以存成 version，可以加 title 和 description（有點像 git commit）。
- environments → version 可以被 published 到某個 environment。Publish 後就會變成 GTM serve 的 code snippet js file 的內容。Code snippet 裡面 js file 的位址預設是指向 `Live` 這個 environment 所部署的 version 內容。可以改變 code snippet 裡 url 的路徑去拿其它 environment，例如： `https://www.googletagmanager.com/gtm.js?id=GTM-XXXXXXXX&gtm_auth=XXXXXXXXXXX&gtm_preview=env-4&gtm_cookies_win=x` （可以[透過 GTM 裡面網頁介面取得這個網址](https://support.google.com/tagmanager/answer/6311518?hl=en#sharePreviews#installContainerSnippets)）

#### Dev tool: [Tag Assistant](https://tagassistant.google.com/)

- ![screenshot/multiple-gtm-containers.gif](https://tech.mincontent.com/_astro/multiple-gtm-containers.kbBwJ_Lz_F3Dz8.webp)
- 注意：頁面中一定要至少有一個 container 被 publish 過一次才能成功 connected。應該是因為一定要拿到 GTM 的 js file，有些 connecting 需要的功能寫在裡面。
- 可以 preview workspace 的設定內容，或任何指定的 version 的設定內容，不需要 publish 就能 preview。也可以 preview local 的頁面（ex: `http://0.0.0.0:8026`）

---

## Q＆A

### 遷移後各個頁面是否都可以透過 GTM 收集到跟頁面相關的流量資料？

是，且 GA4 透過 event 蒐集使用者數據，有些數據內建固定會蒐集，不用設定 custom event，例如 page view、站外連結點擊等。

Ref：[https://support.google.com/analytics/answer/9964640?hl=en#mapping-events](https://support.google.com/analytics/answer/9964640?hl=en#mapping-events)

### 如果不同部門已經有各自的帳號，不想更動帳號設定，是否可以在同一個頁面上可以有 multiple GTM containers？

文件上目前看起來，只要確保維持一個頁面只有一個 `dataLayer` object 就可以這樣做。

> For the best performance of a page, keep the number of Google Tag Manager containers on the page minimal.
> [https://developers.google.com/tag-manager/devguide#multiple-containers](https://developers.google.com/tag-manager/devguide#multiple-containers)

實際測試：

1.  Google Tag Manager snippet 做了什麼？

    - 會 push 一個 GTM event 到 global `dataLayer` array
    - 會非同步載入 [`https://www.googletagmanager.com/gtm.js?id=GTM-XXXXXXXX`](https://www.googletagmanager.com/gtm.js?id=GTM-XXXXXXXX) 這種 script
    - 檔案大小 70kb↑ （30kb gzipped one actually transferred，會隨著 tag 設定內容增加大小）
    - `cache-control: private, max-age=900` 沒有更動內容的話可以拿瀏覽器快取

    ```jsx
    // The Google Tag Manager snippet
    (function (w, d, s, l, i) {
      w[l] = w[l] || [];
      w[l].push({
        "gtm.start": new Date().getTime(),
        event: "gtm.js",
      });
      var f = d.getElementsByTagName(s)[0],
        j = d.createElement(s),
        dl = l != "dataLayer" ? "&l=" + l : "";
      j.async = true;
      j.src = "https://www.googletagmanager.com/gtm.js?id=" + i + dl;
      f.parentNode.insertBefore(j, f);
    })(window, document, "script", "dataLayer", "GTM-XXXXXXXX");
    ```

2.  可以在 GTM 的 Tag Assistant 中偵測到兩個 containers，並可以同時進行 debug

### 怎麼在分析報表時，不會把測試的資料也收集進去？

看似可用來過濾，但實際上無法的設定：

- 根據實際測試，雖然 GA4 裡面的 `Measurement ID` 設定時需要填對應網址，但這個設定並不會過濾掉不是從這個網址送過去的資料。例如，只要頁面嵌入的程式碼是某個 ID，就算該 ID 後台設定的對應網址並非目前的網址，該次拜訪資料仍然可以進到這個 ID 的資料集。

可以用來過濾的設定：

- GA 中可以標記過濾掉特定 ip 來源的資料（例如 filter 掉透過公司網路的 ip，可以用來防止從公司連上 production 網址的流量被計入）[https://support.google.com/analytics/answer/10104470?hl=zh-Hant&ref_topic=9303319](https://support.google.com/analytics/answer/10104470?hl=zh-Hant&ref_topic=9303319)
- 在 GA 報表中可以 filter 出特定 `hostname` 的資料。根據實際測試，page view event 會送 hostname 資料（in `Page Location`），GA4 介面中也可以根據 hostname 做 filter
  ![screenshot/_2021-01-26_4.27.54.png](https://tech.mincontent.com/_astro/_2021-01-26_4.27.54.BPcA0BIN_TJVSv.webp)
  ![screenshot/ga-filter.gif](https://tech.mincontent.com/_astro/ga-filter.BZLmSQUt_Z2szPln.webp)

### 怎麼讓 PM 或 GTM 管理者方便測試 tags，在實際部署 GTM 設定之前可以先測試？

- 方案 1：開很多個 GTM container，不同環境載入不同的 GTM container
  - 缺點：container 間設定不好轉移，測試完還要從測試 container export setting，再到正式 container import setting。
- 方案 2：使用 GTM 的 **environment** 功能 （推薦 ✅）
  > The environments feature in Google Tag Manager is ideal for organizations that want to preview their container changes in a test environment before those changes are published.
  > [https://support.google.com/tagmanager/answer/6311518?hl=en](https://support.google.com/tagmanager/answer/6311518?hl=en)
  > 有兩種套用方式：
  - 方案 2-1（推薦 ✅）：使用 GTM 提供的 [Tag Assistant](https://tagassistant.google.com/)，可以在自己本機端的 Chrome 上面測試，不需要修改到 server 上的資料。例如我想在 `https://test-machine-a.example-host` 的網站套用目前正在測試的 GTM setting，只要用 web preview debug tool 打開 `https://test-machine-a.example-host` 即可測試，不會影響到 `test-machine-a` 機器上的內容。 [https://support.google.com/tagmanager/answer/6311518?hl=en#sharePreviews](https://support.google.com/tagmanager/answer/6311518?hl=en#sharePreviews)
  - 方案 2-2：在 server 的 container snippet 上加參數。這種方式會綁定例如 test-machine-a 的機器，就載入 GTM 上 test-machine-a 的 GTM setting。[https://support.google.com/tagmanager/answer/6311518?hl=en#sharePreviews#installContainerSnippets](https://support.google.com/tagmanager/answer/6311518?hl=en#sharePreviews#installContainerSnippets)

參考資料

- [https://support.google.com/tagmanager/answer/6103576#multiple](https://support.google.com/tagmanager/answer/6103576#multiple)
- [https://developers.google.com/tag-manager/devguide#multidomain](https://developers.google.com/tag-manager/devguide#multidomain)

### PM 是否可以透過 GTM dashboard 設定蒐集某個按鈕（或任何 HTML element）被點擊的次數，和點擊該按鈕的不重複用戶數？要達到這件事，前端是否有需要改動到 code？

- 只要指定好 Tag 和 Trigger 就可以針對特定 element 的點擊事件發 GA event。如果有方式可以識別出該 element，前端部分就不用另外改 code。在識別 element 上，或許可以直接使用 QE 的 test id attributes，或參考其架構作規劃。
- Tags
  GA4 （新版）的 Event：
  ![screenshot/_2021-01-28_6.10.41.png](https://tech.mincontent.com/_astro/_2021-01-28_6.10.41.COfkblpS_Z2w9PvQ.webp)
  Universal Analytics（舊版）的 event：
  ![screenshot/_2021-01-28_6.06.28.png](https://tech.mincontent.com/_astro/_2021-01-28_6.06.28.7cv5ArHj_1FWita.webp)
- Trigger
  Click elements filter：
  ![screenshot/_2021-01-28_6.08.15.png](https://tech.mincontent.com/_astro/_2021-01-28_6.08.15.DdXcCWJZ_Z2kpP2I.webp)

### 讓 GTM 可以動態 inject tags 進我們的網頁會有什麼安全性的點需要考慮？

GTM 可以載入 HTML 會有 XSS 風險的疑慮。如果要降低安全性風險，必須確保都tags 都嵌較安全的服務，不可以嵌來路不明的程式碼或未受信賴的第三方服務。GTM 似乎也可以設定限制 GTM tags 可以使用的類型，但即使設定了，只要有管理員權限的話可能就不會受到限制。

參考資料：

- [https://developers.google.com/tag-manager/devguide#security](https://developers.google.com/tag-manager/devguide#security)
- [https://support.google.com/tagmanager/answer/9323295?hl=en&ref_topic=3441532](https://support.google.com/tagmanager/answer/9323295?hl=en&ref_topic=3441532)
- GTM 被用來作 XSS 攻擊繞過 CSP 的例子：
  [k1tten/writeups](https://github.com/k1tten/writeups/blob/master/bugbounty_writeup/HackMD_XSS_%26_Bypass_CSP.md)

---

## 其它

### 透過 GTM variables 分流不同 GA id

用 GTM 裡面的 variables 功能，可以設定不同 `hostname` 會載入不同 GA4 data stream id。未來如果要設定可以用。
![screenshot/_2021-01-26_4.13.18.png](https://tech.mincontent.com/_astro/_2021-01-26_4.13.18.B_UbITVU_Z304DA.webp)
![screenshot/_2021-01-26_4.11.55.png](https://tech.mincontent.com/_astro/_2021-01-26_4.11.55.CknYpp1o_Z1lwH74.webp)

### GTM 和 GA 的使用者權限管理

- GA
  [Google Analytics user permissions](https://support.google.com/analytics/answer/2884495?hl=en)

- GTM
  [Users and permissions](https://support.google.com/tagmanager/answer/6107011?hl=en)

---

## 相關資源

[Tag Manager Help](https://support.google.com/tagmanager?utm_source=marketingplatform.google.com&utm_medium=et&utm_campaign=marketingplatform.google.com%2Fabout%2Fsupport%2F&hl=en#topic=3441530)

[Developer Guide | Google Tag Manager for Web Tracking](https://developers.google.com/tag-manager/devguide#multidomain)
