Skip to main content

Google Tag Manager

If you use GTM, your dataLayer is usually already populated to some degree, so setting up GTM answers two questions at once: how to load the tag, and which tracking mode to use.

Decision Matrix​

dataLayer empty / unreliabledataLayer completedataLayer present but incomplete
Can write Custom HTML4.1 native4.2 datalayer mode4.3 hybrid mode
Sandboxed template only4.4, no mode line4.4 + trackingMode: 'datalayer'4.4 + trackingMode: 'hybrid'

If you also need custom events, window.b2mConfig is required regardless of mode — see Custom Events.

4.1 Custom HTML — Native​

Your dataLayer isn't used for analytics (GTM is only for tag management here). Let the SDK collect everything itself:

<script
src="https://edge.b2metric.com/b2m-web-sdk.js"
data-api-key="YOUR_API_KEY"></script>

4.2 Custom HTML — dataLayer Only​

<script
src="https://edge.b2metric.com/b2m-web-sdk.js"
data-api-key="YOUR_API_KEY"
data-tracking-mode="datalayer"
data-event-groups="core,ecommerce"></script>

4.3 Custom HTML — Hybrid​

<script
src="https://edge.b2metric.com/b2m-web-sdk.js"
data-api-key="YOUR_API_KEY"
data-tracking-mode="hybrid"
data-event-groups="core,ecommerce,search"></script>

4.4 Sandboxed Custom Template​

GTM's sandboxed custom template can't render a script tag with data-* attributes. Use a config object instead — including the mode:

<script>
window.b2mConfig = {
apiKey: 'API_KEY',
trackingMode: 'hybrid',
// 'datalayer' | 'hybrid' — omit this line entirely for native
eventGroups: {
core: { enabled: true },
ecommerce: { enabled: true },
search: { enabled: true }
}
};
</script>
<script src="https://edge.b2metric.com/b2m-web-sdk.js"></script>

Attribute-to-config mapping​

If you need to translate an existing script-tag setup to a b2mConfig object:

Script-tag attributeb2mConfig key
data-api-keyapiKey
data-tracking-modetrackingMode
data-event-groups="core,ecommerce"eventGroups: { core: {enabled:true}, ecommerce: {enabled:true} }
data-require-consent="true"requireConsent: true
data-ab-mode="true"abMode: true
data-cookie-domaincookieDomain
data-app-identifierappIdentifier
data-chat-integration-idchatIntegrationId
data-session-replay="true"enableSessionReplay: true

4.5 GTM + Custom Events (+ Mode + Chat) — Full Example​

<script>
window.b2mConfig = {
apiKey: 'API_KEY',
trackingMode: 'hybrid',
requireConsent: true,
eventGroups: {
core: { enabled: true },
ecommerce: { enabled: true },
my_events: {
enabled: true,
events: ['quote_started', 'quote_completed', 'demo_requested'],
autoTrack: []
}
},
chatIntegrationId: 'INTEGRATION_ID',
chatApiKey: 'CHAT_API_KEY',
chatTenant: 'TENANT'
};
</script>
<script src="https://edge.b2metric.com/b2m-web-sdk.js"></script>

4.6 Trigger Selection​

TriggerWhen to use it
All Pages (Page View)Default choice — correct for most setups.
Initialization — All PagesWhen the SDK needs to run as early as possible (e.g. A/B testing anti-flicker — see A/B Testing).
Consent InitializationIn a CMP-based setup where the SDK must load only after consent is resolved (see Consent Management).

Attach the trigger to a single tag firing once per page — attaching the same SDK tag to more than one trigger loads it twice.

4.7 Ordering Rule​

window.b2mConfig must be defined before the SDK script runs. Keeping the config block above the SDK tag inside the same Custom HTML tag (as in every example above) guarantees this. Don't split them across two separate GTM tags and rely on tag priority — the SDK reads config immediately, so a config tag that fires later is simply ignored.

4.8 Common Conflicts to Check For​

  • If the page already has a hardcoded tag with data-api-key, a window.b2mConfig block from GTM is never read. Pick one integration path, not both.
  • If two tags on the page both carry data-api-key, only the first one found is used — remove the duplicate rather than relying on load order.
  • data-apiKey (wrong case) never starts the SDK — the attribute selector only looks for data-api-key.

4.9 Verifying in GTM Preview​

await window.b2mReady; // true
window.b2mWebSDK.config.trackingMode;
// 'native' | 'datalayer' | 'hybrid' — is this what you expected?
window.b2m.getEnabledEvents(); // are your event names listed?

Then trigger a dataLayer push and check the Network tab: the resulting event should reach the collector exactly once. If it appears twice, the mode is probably still set to native.