> For the complete documentation index, see [llms.txt](https://docs.chord.co/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.chord.co/activate/event-streaming/destinations/tag-managers/google-tag-manager.md).

# Google Tag Manager

**Google Tag Manager (GTM)** is a tag management system. It lets you deploy and manage marketing and analytics tags without editing code. This destination loads your GTM container in the browser and pushes Chord event data to the GTM data layer. There, the tags and triggers you configured can use it. There is no server component.

## Getting started

This destination runs in the browser. Chord loads the GTM container for you, so you do not install the script yourself. You need a GTM container. Find its ID, for example `GTM-XXXXXX`, in the GTM dashboard.

## Settings

* **Destination Name** (required): a name to tell this destination apart.
* **Container ID** (required): your GTM container ID. It identifies the GTM container to load.
* **Data Layer Name** (required): the name of the data layer variable.
* **Consent Requirements** (optional): the consent categories a visitor must accept before Chord sends data to this destination. See [Consent](/activate/event-streaming/consent.md).

## Connect

Add **Google Tag Manager** from the destination catalog, using the settings above. See [Connect a destination](/activate/event-streaming/connect-a-destination.md) for the full steps.

{% hint style="info" %}
If your site already installs the GTM snippet directly, that container loads twice: once from your snippet and once from this destination. Remove the manual snippet.
{% endhint %}

## Events

All events push data to the GTM data layer with `dataLayer.push(eventData)`. Your GTM tags and triggers route events on to downstream tools.

Each push contains the event's data **twice**, in two shapes:

* **Flattened** to top-level keys (`order_id`, `total`, `currency` and so on). This is the conventional data layer shape, and the one most containers are built to read.
* **Nested** under `properties`, alongside `traits` and `context`.

Both are always present, so a Data Layer Variable can read either `order_id` or `properties.order_id`. Use whichever matches your existing container.

Values that are absent from the event are left out instead of sent as empty strings, so GTM's **Set Default Value** option works as expected.

## Event mapping

| Chord event type | GTM data layer `event` value                          | Notes                                         |
| ---------------- | ----------------------------------------------------- | --------------------------------------------- |
| `page`           | `"page"`                                              |                                               |
| `identify`       | `"identify"`                                          |                                               |
| `track`          | The Chord event name, for example `"Order Completed"` | All events are forwarded with no name mapping |

`group` and `alias` calls have no data layer representation. Chord skips them and logs a warning to the browser console.

## Keys on every event

| Data layer key | Chord source                                                                                                      |
| -------------- | ----------------------------------------------------------------------------------------------------------------- |
| `event`        | See the event mapping above                                                                                       |
| `userId`       | `userId`                                                                                                          |
| `anonymousId`  | `anonymousId`                                                                                                     |
| *(flattened)*  | Every key of `properties`, written as a top-level key. On identify, every trait too                               |
| `properties`   | The full `properties` object                                                                                      |
| `traits`       | `traits` merged with `context.traits`                                                                             |
| `context`      | `campaign` (UTMs), `clientIds` and `page` only. See [What lands in the data layer](#what-lands-in-the-data-layer) |

## Page events

In addition to the keys above:

| Data layer key | Chord source                                             | Notes                                                |
| -------------- | -------------------------------------------------------- | ---------------------------------------------------- |
| `title`        | `properties.title`, falling back to `context.page.title` |                                                      |
| `name`         | Same as `title`                                          | Kept for containers built against the previous shape |
| `url`          | `properties.url`, falling back to `context.page.url`     |                                                      |

## Identify events

Traits are flattened to top-level keys as well as nested. You can read `email` and `name` as `email` or as `traits.email`. Any `properties` on the identify call are flattened too, and a trait wins over a property with the same key.

## Track events

Event properties are flattened to top-level keys. For an `Order Completed`, that means `order_id`, `total`, `currency` and `products` are all readable directly. `products` stays an array.

## What lands in the data layer

Everything pushed to the data layer is readable by **every tag in your container**, including any third-party or custom HTML tag. Two consequences are worth knowing before you build tags against it:

* Only the `campaign`, `clientIds` and `page` slices of event context are pushed. `clientIds` carries advertising click identifiers from several vendors at once (`fbc` for Meta, `ttclid` for TikTok, `gcl_aw` for Google Ads, `irclickid` for Impact, and others), so a tag for one vendor can read another's. That is what makes campaign and click ID attribution possible from GTM at all. It is worth knowing when you add a tag you did not write.
* Visitor traits, including email, are pushed under `traits`, and flattened on identify. They are not pushed a second time inside `context`.

## Custom property mappings

Property mappings configured on the destination connection are forwarded to the data layer. A mapping written to a bare destination path, for example `properties.customer_type → customer_type`, arrives as a top-level key. A mapping written with a `properties.` prefix arrives both flattened and inside the nested `properties` object.

Mapped properties overwrite flattened properties with the same key. Mapped properties can never overwrite `event`, `userId`, `anonymousId`, `properties`, `traits` or `context`, which always win on a key collision. On page events, `title`, `name` and `url` also win over a mapped key.

Unlike ad pixel destinations, GTM does **not** strip personal information from mapped properties. It is a tag manager rather than an ad network endpoint, and it already forwards the complete `traits` object. Redaction is the responsibility of the individual tags you configure in your container.

## Reset data layer

After each event, Chord pushes a reset callback that clears GTM's merged data layer model. Chord has no setting to turn this off, so it is always on. It keeps events isolated from one another. It also means **nothing pushed by Chord persists into later events**. A variable read outside the triggering event's scope resolves to `undefined`.

## Initialization

Chord initializes the data layer array, then pushes the current user ID (as both `user_id` and `userId`) and a `gtm.start` timestamp event. It then loads the GTM container script from `https://www.googletagmanager.com/gtm.js?id=<your container ID>`. If you set a custom **Data Layer Name**, Chord passes it to GTM with the script.

Chord tracks whether the script is loading, loaded or failed, so it never loads the script twice. If the script fails to load, Chord still pushes events to the data layer, but no container reads them.

## Content Security Policy

If your site uses a Content Security Policy, allow these domains:

| Directive     | Domain                             |
| ------------- | ---------------------------------- |
| `script-src`  | `https://www.googletagmanager.com` |
| `connect-src` | `https://www.googletagmanager.com` |

Your policy must also allow `connect-src` to your Chord ingest host. Without it, the browser blocks event delivery to Chord entirely, and no data reaches your warehouse or any server destination.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.chord.co/activate/event-streaming/destinations/tag-managers/google-tag-manager.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
