Skip to main content

Google Tag Manager (GTM)

Web Source code Package

Google Tag Manager (GTM) is a tool to manage and add third-party integrations to your website, configured within the unified gtag destination.

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: {
      settings: {
        gtm: {
          containerId: 'GTM-XXXXXXX',
          dataLayer: 'dataLayer',
        },
      },
    },
  },
},
});

Configuration

This destination uses the standard destination config wrapper (consent, data, env, id, ...). For the shared fields see destination configuration. Package-specific fields live under config.settings and are listed below.

Settings

PropertyTypeDescriptionMore
comoboolean | objectConsent mode configuration: false (disabled), true (use defaults), or custom mapping
como_advancedboolean | numberAdvanced consent mode (non-EU): emit denied default at page load with wait_for_update (true=500ms, or a number of ms)
ga4ga4GA4-specific configuration settings
measurementId*stringGA4 Measurement ID from Google Analytics
debugbooleanEnable debug mode for GA4
pageviewbooleanEnable automatic pageview tracking
server_container_urlstringServer-side GTM container URL
snakeCasebooleanConvert parameter names to snake_case
transport_urlstringCustom transport URL for GA4
dataanyCustom data mapping configuration
adsadsGoogle Ads specific configuration settings
conversionId*stringGoogle Ads Conversion ID (required)
currencystringCurrency code (ISO 4217, e.g., USD, EUR)
dataanyCustom data mapping (WalkerOS.Mapping.Value | Values)
enhancedConversionsenhancedConversionsEnhanced conversions: maps event fields to Google user_data for improved measurement accuracy
emailanyMapping value for user email
phone_numberanyMapping value for user phone number
addressaddressAddress mapping for enhanced conversions
first_nameanyMapping value for first name
last_nameanyMapping value for last name
streetanyMapping value for street address
cityanyMapping value for city
regionanyMapping value for region/state
postal_codeanyMapping value for postal/zip code
countryanyMapping value for country
gtmgtmGoogle Tag Manager specific configuration settings
containerId*stringGTM Container ID (required)
dataLayerstringCustom dataLayer variable name (default: dataLayer)
domainstringCustom GTM domain for script loading
dataanyCustom data mapping (WalkerOS.Mapping.Value | Values)
* Required fields

Mapping

Per-event rules under config.mapping. For the standard rule fields (consent, condition, data, batch, name, policy) see mapping.

PropertyTypeDescriptionMore
ga4ga4GA4-specific event mapping
adsadsGoogle Ads-specific event mapping
labelstringConversion label for this specific event
gtmgtmGTM-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": "9433bed2cc537782",
  "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": "14dfb640f7eed832",
  "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

The destination bootstraps gtag and configures a Google Ads account via its conversionId.

Event
{
  "settings": {
    "ads": {
      "conversionId": "AW-123456789",
      "currency": "EUR"
    }
  }
}
Out
gtag("js", {});

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

The destination bootstraps gtag and configures a GA4 property via its measurementId.

Event
{
  "settings": {
    "ga4": {
      "measurementId": "G-XXXXXX-1"
    }
  }
}
Out
gtag("js", {});

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_id": "us3r",
  "user_device": "c00k13",
  "user_session": "s3ss10n",
  "source_type": "collector",
  "source_schema": "4",
  "source_count": 1,
  "source_trace": "1700000106abcdef1700000106abcdef",
  "source_release_default": "4.2.1",
  "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": "7f57f8c6fba9b725",
  "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": "90b169aded2b6239",
  "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

The destination initializes the dataLayer and pushes the gtm.js start event for a GTM container.

Event
{
  "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": "fa1aea4ccf03e63a",
  "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": "8b162560dcd73d76",
  "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": "51d0422ccb666f30",
  "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=>U(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"
})
💡 Need implementation support?
elbwalker offers hands-on support: setup review, measurement planning, destination mapping, and live troubleshooting. Book a 2-hour session (€399)