> Part of the walkerOS documentation. Project overview and full index: <https://www.walkeros.io/llms.txt>

# Google Tag Manager (GTM)

<!-- -->

[Web](#)[ ](https://github.com/elbwalker/walkerOS/tree/main/packages/web/destinations/gtag)

<!-- -->

[Source code](https://github.com/elbwalker/walkerOS/tree/main/packages/web/destinations/gtag)[ ](https://www.npmjs.com/package/@walkeros/web-destination-gtag)

<!-- -->

[Package](https://www.npmjs.com/package/@walkeros/web-destination-gtag)

[Google Tag Manager (GTM)](https://tagmanager.google.com/) is a tool to manage and add third-party integrations to your website, configured within the unified gtag destination.

## Installation[​](#installation "Direct link to Installation")

```
npm install @walkeros/web-destination-gtag
```

```
import { startFlow } from '@walkeros/collector';
import { destinationGtag } from '@walkeros/web-destination-gtag';

await startFlow({
  destinations: {
    gtag: {
      code: destinationGtag,
      config: {
        loadScript: true, // walkerOS installs the container; omit it when GTM is already on the page
        settings: {
          gtm: {
            containerId: 'GTM-XXXXXXX',
            dataLayer: 'dataLayer',
          },
        },
      },
    },
  },
});
```

Set `loadScript: true` when walkerOS should install the container for you. It loads `gtm.js` and pushes the `gtm.js` start event into the dataLayer, which is what Google's own snippet does.

Leave `loadScript` unset when the container is already on the page, for example when you are feeding an existing GTM setup while you migrate. walkerOS then neither loads the container nor pushes the `gtm.js` bootstrap event: it adopts the configured dataLayer (creating it if it does not exist yet) and pushes your mapped events into it, so your existing triggers keep firing exactly as often as before.

`loadScript` is set once per destination and applies to every flavor configured on it. On a destination that also configures `ga4` or `ads`, the same flag governs whether those scripts are loaded too.

## Configuration[​](#configuration "Direct link to Configuration")

This <!-- -->destination<!-- --> uses the standard <!-- -->destination<!-- --> config wrapper (consent, data, env, id, ...). For the shared fields see [destination<!-- --> configuration](https://www.walkeros.io/docs/destinations.md#configuration). Package-specific fields live under `config.settings` and are listed below.

## Settings[​](#settings "Direct link to Settings")

| Property               | Type                  | Description                                                                                                                            | More |
| ---------------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | ---- |
| `como`                 | `boolean \| object`   | Consent mode configuration: false (disabled), true (use defaults), or custom mapping                                                   |      |
| `como_advanced`        | `boolean \| number`   | Advanced consent mode (non-EU): emit denied default at page load with wait\_for\_update (true=500ms, or a number of ms)                |      |
| `ga4`                  | `ga4`                 | GA4-specific configuration settings                                                                                                    |      |
| `measurementId*`       | `string`              | GA4 Measurement ID from Google Analytics                                                                                               |      |
| `debug`                | `boolean`             | Enable debug mode for GA4                                                                                                              |      |
| `pageview`             | `boolean`             | Enable automatic pageview tracking                                                                                                     |      |
| `server_container_url` | `string`              | Server-side GTM container URL                                                                                                          |      |
| `snakeCase`            | `boolean`             | Lowercase the event name and replace its spaces with underscores (like true). Applies to the event name only, never to parameter names |      |
| `transport_url`        | `string`              | Custom transport URL for GA4                                                                                                           |      |
| `data`                 | `any`                 | Custom data mapping configuration                                                                                                      |      |
| `ads`                  | `ads`                 | Google Ads specific configuration settings                                                                                             |      |
| `conversionId*`        | `string`              | Google Ads Conversion ID (required)                                                                                                    |      |
| `currency`             | `string`              | Currency code (ISO 4217, e.g., USD, EUR)                                                                                               |      |
| `data`                 | `any`                 | Custom data mapping (WalkerOS.Mapping.Value \| Values)                                                                                 |      |
| `enhancedConversions`  | `enhancedConversions` | Enhanced conversions: maps event fields to Google user\_data for improved measurement accuracy                                         |      |
| `email`                | `any`                 | Mapping value for user email                                                                                                           |      |
| `phone_number`         | `any`                 | Mapping value for user phone number                                                                                                    |      |
| `address`              | `address`             | Address mapping for enhanced conversions                                                                                               |      |
| `first_name`           | `any`                 | Mapping value for first name                                                                                                           |      |
| `last_name`            | `any`                 | Mapping value for last name                                                                                                            |      |
| `street`               | `any`                 | Mapping value for street address                                                                                                       |      |
| `city`                 | `any`                 | Mapping value for city                                                                                                                 |      |
| `region`               | `any`                 | Mapping value for region/state                                                                                                         |      |
| `postal_code`          | `any`                 | Mapping value for postal/zip code                                                                                                      |      |
| `country`              | `any`                 | Mapping value for country                                                                                                              |      |
| `gtm`                  | `gtm`                 | Google Tag Manager specific configuration settings                                                                                     |      |
| `containerId*`         | `string`              | GTM Container ID (required)                                                                                                            |      |
| `dataLayer`            | `string`              | Custom dataLayer variable name (default: dataLayer)                                                                                    |      |
| `domain`               | `string`              | Custom GTM domain for script loading                                                                                                   |      |
| `data`                 | `any`                 | Custom data mapping (WalkerOS.Mapping.Value \| Values)                                                                                 |      |

\* Required fields

## Mapping[​](#mapping "Direct link to Mapping")

Per-event rules under `config.mapping`. For the standard rule fields (consent, condition, data, batch, name, policy) see [mapping](https://www.walkeros.io/docs/mapping.md).

| Property | Type     | Description                              | More |
| -------- | -------- | ---------------------------------------- | ---- |
| `ga4`    | `ga4`    | GA4-specific event mapping               |      |
| `ads`    | `ads`    | Google Ads-specific event mapping        |      |
| `label`  | `string` | Conversion label for this specific event |      |
| `gtm`    | `gtm`    | GTM-specific event mapping               |      |

## Examples

### Add to cart

A product add event is mapped to the GA4 add\_to\_cart event with item details and value.

Event

```
{
  "name": "product add",
  "data": {
    "id": "ers",
    "name": "Everyday Ruck Snack",
    "color": "black",
    "size": "l",
    "price": 420
  },
  "context": {
    "shopping": [
      "intent",
      0
    ]
  },
  "globals": {
    "pagegroup": "shop"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "us3r",
    "device": "c00k13",
    "session": "s3ss10n"
  },
  "nested": [],
  "consent": {
    "functional": true
  },
  "id": "f5aebb26790ff263",
  "trigger": "click",
  "entity": "product",
  "action": "add",
  "timestamp": 1700000101,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
```

Mapping

```
{
  "name": "add_to_cart",
  "include": [
    "data"
  ],
  "data": {
    "map": {
      "currency": {
        "value": "EUR",
        "key": "data.currency"
      },
      "value": "data.price",
      "items": {
        "loop": [
          "this",
          {
            "map": {
              "item_id": "data.id",
              "item_variant": "data.color",
              "quantity": {
                "value": 1,
                "key": "data.quantity"
              }
            }
          }
        ]
      }
    }
  }
}
```

Out

```
gtag("event", "add_to_cart", {
  "currency": "EUR",
  "value": 420,
  "items": [
    {
      "item_id": "ers",
      "item_variant": "black",
      "quantity": 1
    }
  ],
  "data_id": "ers",
  "data_name": "Everyday Ruck Snack",
  "data_color": "black",
  "data_size": "l",
  "data_price": 420,
  "send_to": "G-XXXXXX-1"
})
```

### Enhanced conversions

enhancedConversions maps event fields into a gtag set user\_data call sent immediately before the conversion event.

Event

```
{
  "name": "order complete",
  "data": {
    "id": "0rd3r1d",
    "currency": "EUR",
    "shipping": 5.22,
    "taxes": 73.76,
    "total": 555,
    "customerEmail": "buyer@shop.com",
    "customerPhone": "+1234567890"
  },
  "context": {
    "shopping": [
      "complete",
      0
    ]
  },
  "globals": {
    "pagegroup": "shop"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "us3r",
    "device": "c00k13",
    "session": "s3ss10n"
  },
  "nested": [
    {
      "entity": "product",
      "data": {
        "id": "ers",
        "name": "Everyday Ruck Snack",
        "color": "black",
        "size": "l",
        "price": 420
      },
      "context": {
        "shopping": [
          "complete",
          0
        ]
      },
      "nested": []
    },
    {
      "entity": "product",
      "data": {
        "id": "cc",
        "name": "Cool Cap",
        "size": "one size",
        "price": 42
      },
      "context": {
        "shopping": [
          "complete",
          0
        ]
      },
      "nested": []
    },
    {
      "entity": "gift",
      "data": {
        "name": "Surprise"
      },
      "context": {
        "shopping": [
          "complete",
          0
        ]
      },
      "nested": []
    }
  ],
  "consent": {
    "functional": true
  },
  "id": "864b2b26489a786d",
  "trigger": "load",
  "entity": "order",
  "action": "complete",
  "timestamp": 1700000109,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
```

Mapping

```
{
  "name": "PURCHASE_EC2",
  "settings": {
    "ads": {
      "label": "PURCHASE_EC2"
    }
  },
  "data": {
    "map": {
      "value": "data.total"
    }
  }
}
```

Out

```
gtag("set", "user_data", {
  "email": "buyer@shop.com",
  "phone_number": "+1234567890"
});

gtag("event", "conversion", {
  "send_to": "AW-123456789/PURCHASE_EC2",
  "currency": "EUR",
  "value": 555
})
```

### Google Ads init

Configures a Google Ads account via its conversionId. gtag already exists here, so no \`js\` is sent.

Event

```
{
  "settings": {
    "ads": {
      "conversionId": "AW-123456789",
      "currency": "EUR"
    }
  }
}
```

Out

```
gtag("config", "AW-123456789")
```

### Consent Mode v2

A walker consent command with marketing and functional granted updates gtag Consent Mode v2 parameters.

Event

```
{
  "marketing": true,
  "functional": true
}
```

Out

```
gtag("consent", "default", {
  "ad_storage": "denied",
  "ad_user_data": "denied",
  "ad_personalization": "denied",
  "analytics_storage": "denied"
});

gtag("consent", "update", {
  "ad_storage": "granted",
  "ad_user_data": "granted",
  "ad_personalization": "granted",
  "analytics_storage": "granted"
})
```

### GA4 init

Configures a GA4 property via its measurementId. gtag already exists here, so no \`js\` is sent: that would be a second, false initialisation signal.

Event

```
{
  "settings": {
    "ga4": {
      "measurementId": "G-XXXXXX-1"
    }
  }
}
```

Out

```
gtag("config", "G-XXXXXX-1", {})
```

### GA4 include all

Include flattens every event section into prefixed GA4 params, exposing data, context, user, source, and event fields.

Event

```
{
  "name": "page view",
  "data": {
    "domain": "www.example.com",
    "title": "walkerOS documentation",
    "referrer": "https://www.walkeros.io/",
    "search": "?foo=bar",
    "hash": "#hash",
    "id": "/docs/"
  },
  "context": {
    "dev": [
      "test",
      1
    ]
  },
  "globals": {
    "pagegroup": "docs"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "us3r",
    "device": "c00k13",
    "session": "s3ss10n"
  },
  "nested": [
    {
      "entity": "child",
      "data": {
        "is": "subordinated"
      }
    }
  ],
  "consent": {
    "functional": true
  },
  "id": "ev-1700000106",
  "trigger": "load",
  "entity": "page",
  "action": "view",
  "timestamp": 1700000106,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "1700000106abcdef1700000106abcdef",
    "type": "collector",
    "schema": "4"
  }
}
```

Mapping

```
{
  "include": [
    "data",
    "context",
    "globals",
    "user",
    "source",
    "event"
  ]
}
```

Out

```
gtag("event", "page_view", {
  "data_domain": "www.example.com",
  "data_title": "walkerOS documentation",
  "data_referrer": "https://www.walkeros.io/",
  "data_search": "?foo=bar",
  "data_hash": "#hash",
  "data_id": "/docs/",
  "context_dev": "test",
  "globals_pagegroup": "docs",
  "user_device": "c00k13",
  "user_session": "s3ss10n",
  "source_type": "collector",
  "source_schema": "4",
  "source_count": 1,
  "source_trace": "1700000106abcdef1700000106abcdef",
  "source_release_default": "4.5.0",
  "event_entity": "page",
  "event_action": "view",
  "event_trigger": "load",
  "event_id": "ev-1700000106",
  "event_name": "page view",
  "event_timestamp": 1700000106,
  "event_timing": 3.14,
  "send_to": "G-XXXXXX-1"
})
```

### Ads conversion

An order complete event is sent as a Google Ads conversion with a configured label and transaction value.

Event

```
{
  "name": "order complete",
  "data": {
    "id": "0rd3r1d",
    "currency": "EUR",
    "shipping": 5.22,
    "taxes": 73.76,
    "total": 555
  },
  "context": {
    "shopping": [
      "complete",
      0
    ]
  },
  "globals": {
    "pagegroup": "shop"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "us3r",
    "device": "c00k13",
    "session": "s3ss10n"
  },
  "nested": [
    {
      "entity": "product",
      "data": {
        "id": "ers",
        "name": "Everyday Ruck Snack",
        "color": "black",
        "size": "l",
        "price": 420
      },
      "context": {
        "shopping": [
          "complete",
          0
        ]
      },
      "nested": []
    },
    {
      "entity": "product",
      "data": {
        "id": "cc",
        "name": "Cool Cap",
        "size": "one size",
        "price": 42
      },
      "context": {
        "shopping": [
          "complete",
          0
        ]
      },
      "nested": []
    },
    {
      "entity": "gift",
      "data": {
        "name": "Surprise"
      },
      "context": {
        "shopping": [
          "complete",
          0
        ]
      },
      "nested": []
    }
  ],
  "consent": {
    "functional": true
  },
  "id": "66b93c938cf1b3cd",
  "trigger": "load",
  "entity": "order",
  "action": "complete",
  "timestamp": 1700000103,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
```

Mapping

```
{
  "name": "PURCHASE_CONV",
  "settings": {
    "ads": {
      "label": "PURCHASE_CONV"
    }
  },
  "data": {
    "map": {
      "value": "data.total"
    }
  }
}
```

Out

```
gtag("event", "conversion", {
  "send_to": "AW-123456789/PURCHASE_CONV",
  "currency": "EUR",
  "value": 555
})
```

### GTM dataLayer push

A page view event is pushed to window\.dataLayer for GTM with the mapped event name and parameters.

Event

```
{
  "name": "page view",
  "data": {
    "domain": "www.example.com",
    "title": "walkerOS documentation",
    "referrer": "https://www.walkeros.io/",
    "search": "?foo=bar",
    "hash": "#hash",
    "id": "/docs/"
  },
  "context": {
    "dev": [
      "test",
      1
    ]
  },
  "globals": {
    "pagegroup": "docs"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "us3r",
    "device": "c00k13",
    "session": "s3ss10n"
  },
  "nested": [
    {
      "entity": "child",
      "data": {
        "is": "subordinated"
      }
    }
  ],
  "consent": {
    "functional": true
  },
  "id": "30d191241e1f6d3d",
  "trigger": "load",
  "entity": "page",
  "action": "view",
  "timestamp": 1700000104,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
```

Mapping

```
{
  "name": "page_view",
  "settings": {
    "gtm": {}
  },
  "data": {
    "map": {
      "page_title": "data.title",
      "page_location": "data.domain"
    }
  }
}
```

Out

```
dataLayer.push({
  "event": "page_view",
  "page_title": "walkerOS documentation",
  "page_location": "www.example.com"
})
```

### GTM init

With script loading enabled the destination initializes the dataLayer, pushes the gtm.js start event, and loads the GTM container.

Event

```
{
  "loadScript": true,
  "settings": {
    "gtm": {
      "containerId": "GTM-XXXXXXX"
    }
  }
}
```

Out

```
dataLayer.push({
  "gtm.start": 1700000000000,
  "event": "gtm.js"
})
```

### Multi-tool push

A single order event fans out to GA4, Google Ads, and GTM from one mapping rule with per-tool settings.

Event

```
{
  "name": "order complete",
  "data": {
    "id": "0rd3r1d",
    "currency": "EUR",
    "shipping": 5.22,
    "taxes": 73.76,
    "total": 555
  },
  "context": {
    "shopping": [
      "complete",
      0
    ]
  },
  "globals": {
    "pagegroup": "shop"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "us3r",
    "device": "c00k13",
    "session": "s3ss10n"
  },
  "nested": [
    {
      "entity": "product",
      "data": {
        "id": "ers",
        "name": "Everyday Ruck Snack",
        "color": "black",
        "size": "l",
        "price": 420
      },
      "context": {
        "shopping": [
          "complete",
          0
        ]
      },
      "nested": []
    },
    {
      "entity": "product",
      "data": {
        "id": "cc",
        "name": "Cool Cap",
        "size": "one size",
        "price": 42
      },
      "context": {
        "shopping": [
          "complete",
          0
        ]
      },
      "nested": []
    },
    {
      "entity": "gift",
      "data": {
        "name": "Surprise"
      },
      "context": {
        "shopping": [
          "complete",
          0
        ]
      },
      "nested": []
    }
  ],
  "consent": {
    "functional": true
  },
  "id": "77918b95c513d885",
  "trigger": "load",
  "entity": "order",
  "action": "complete",
  "timestamp": 1700000107,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
```

Mapping

```
{
  "name": "purchase",
  "include": [
    "data"
  ],
  "settings": {
    "ga4": {},
    "ads": {
      "label": "PURCHASE_CONV"
    },
    "gtm": {}
  },
  "data": {
    "map": {
      "value": "data.total",
      "currency": {
        "key": "data.currency",
        "value": "EUR"
      }
    }
  }
}
```

Out

```
gtag("event", "purchase", {
  "value": 555,
  "currency": "EUR",
  "data_id": "0rd3r1d",
  "data_currency": "EUR",
  "data_shipping": 5.22,
  "data_taxes": 73.76,
  "data_total": 555,
  "send_to": "G-XXXXXX-1"
});

gtag("event", "conversion", {
  "send_to": "AW-123456789/PURCHASE_CONV",
  "currency": "EUR",
  "value": 555,
  "data_id": "0rd3r1d",
  "data_currency": "EUR",
  "data_shipping": 5.22,
  "data_taxes": 73.76,
  "data_total": 555
});

dataLayer.push({
  "event": "purchase",
  "value": 555,
  "currency": "EUR",
  "data_id": "0rd3r1d",
  "data_currency": "EUR",
  "data_shipping": 5.22,
  "data_taxes": 73.76,
  "data_total": 555
})
```

### Page view

A page view event is forwarded as a GA4 page\_view event with no additional mapping.

Event

```
{
  "name": "page view",
  "data": {
    "domain": "www.example.com",
    "title": "walkerOS documentation",
    "referrer": "https://www.walkeros.io/",
    "search": "?foo=bar",
    "hash": "#hash",
    "id": "/docs/"
  },
  "context": {
    "dev": [
      "test",
      1
    ]
  },
  "globals": {
    "pagegroup": "docs"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "us3r",
    "device": "c00k13",
    "session": "s3ss10n"
  },
  "nested": [
    {
      "entity": "child",
      "data": {
        "is": "subordinated"
      }
    }
  ],
  "consent": {
    "functional": true
  },
  "id": "d75d28698a71428a",
  "trigger": "load",
  "entity": "page",
  "action": "view",
  "timestamp": 1700000102,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
```

Out

```
gtag("event", "page_view", {
  "send_to": "G-XXXXXX-1"
})
```

### Purchase

An order complete event is mapped to the GA4 purchase event with transaction details and nested product items.

Event

```
{
  "name": "order complete",
  "data": {
    "id": "0rd3r1d",
    "currency": "EUR",
    "shipping": 5.22,
    "taxes": 73.76,
    "total": 555
  },
  "context": {
    "shopping": [
      "complete",
      0
    ]
  },
  "globals": {
    "pagegroup": "shop"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "us3r",
    "device": "c00k13",
    "session": "s3ss10n"
  },
  "nested": [
    {
      "entity": "product",
      "data": {
        "id": "ers",
        "name": "Everyday Ruck Snack",
        "color": "black",
        "size": "l",
        "price": 420
      },
      "context": {
        "shopping": [
          "complete",
          0
        ]
      },
      "nested": []
    },
    {
      "entity": "product",
      "data": {
        "id": "cc",
        "name": "Cool Cap",
        "size": "one size",
        "price": 42
      },
      "context": {
        "shopping": [
          "complete",
          0
        ]
      },
      "nested": []
    },
    {
      "entity": "gift",
      "data": {
        "name": "Surprise"
      },
      "context": {
        "shopping": [
          "complete",
          0
        ]
      },
      "nested": []
    }
  ],
  "consent": {
    "functional": true
  },
  "id": "544404246e968e43",
  "trigger": "load",
  "entity": "order",
  "action": "complete",
  "timestamp": 1700000100,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
```

Mapping

```
{
  "name": "purchase",
  "include": [
    "data",
    "context"
  ],
  "data": {
    "map": {
      "transaction_id": "data.id",
      "value": "data.total",
      "tax": "data.taxes",
      "shipping": "data.shipping",
      "currency": {
        "key": "data.currency",
        "value": "EUR"
      },
      "items": {
        "loop": [
          "nested",
          {
            "condition": {
              "$code": "e=>S(e)&&\"product\"===e.entity"
            },
            "map": {
              "item_id": "data.id",
              "item_name": "data.name",
              "quantity": {
                "key": "data.quantity",
                "value": 1
              }
            }
          }
        ]
      }
    }
  }
}
```

Out

```
gtag("event", "purchase", {
  "transaction_id": "0rd3r1d",
  "value": 555,
  "tax": 73.76,
  "shipping": 5.22,
  "currency": "EUR",
  "items": [
    {
      "item_id": "ers",
      "item_name": "Everyday Ruck Snack",
      "quantity": 1
    },
    {
      "item_id": "cc",
      "item_name": "Cool Cap",
      "quantity": 1
    }
  ],
  "data_id": "0rd3r1d",
  "data_currency": "EUR",
  "data_shipping": 5.22,
  "data_taxes": 73.76,
  "data_total": 555,
  "context_shopping": "complete",
  "send_to": "G-XXXXXX-1"
})
```
