> ## Documentation Index
> Fetch the complete documentation index at: https://docs.abtestly.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Google Tag Manager

> How ABTestly coexists with GTM. Short version: do not install ABTestly through GTM; do install your GTM tags after ABTestly.

Two rules:

1. **Do not install ABTestly through GTM.**
2. **Do fire GTM tags that depend on variant changes after ABTestly.**

## Why not through GTM

GTM defers script execution until after DOM parsing. By the time GTM
fires, the page has painted. Loading ABTestly through GTM produces
consistent flicker, 200 to 800 ms of original content visible
before the variant swaps in.

Install the ABTestly snippet directly in `<head>`, above your GTM
snippet or below it (either order works, but ABTestly has to be a
direct `<script>` tag, not a GTM tag). See
[Install the snippet](/install/snippet).

## Firing GTM tags that read variant changes

If a GTM tag depends on the variant that ABTestly applied, say, a
custom dimension for the variant key, it needs to fire *after* the
variant applies.

**Recommended pattern:** listen for the `experience_impression`
dataLayer event (see [GA4 dataLayer](/integrations/ga4-datalayer))
and fire your tag from a trigger scoped to that event.

* GTM → Triggers → New → Custom Event.
* Event name: `experience_impression`.
* Any tag using that trigger fires once per exposure, with the
  variant fields available as `{{ variant_key }}`, `{{ experiment_id }}`, etc.

## Order in `<head>`

```html theme={null}
<head>
  <!-- ABTestly first -->
  <script>!function(){/* ABTestly snippet */}();</script>

  <!-- GTM after -->
  <script>(function(w,d,s,l,i){/* GTM */})(window,document,'script','dataLayer','GTM-XXXX');</script>
</head>
```

ABTestly first because it needs to run before the browser paints.
GTM after because it does its own async loading and does not need to
be first.

## Consent

If your GTM setup uses Google Consent Mode, the two systems compose.
ABTestly's own consent gate ([Consent](/install/consent)) waits for
`window[consentKey] === 'granted'`. Google Consent Mode manages
GTM's own tags. Both can be gated on the same consent flag.

## Common questions

**Can I have GTM install my consent-gated ABTestly snippet?** No.
same reason as "do not install through GTM". Install the snippet
directly and let its built-in deferred mode wait for consent.

**Can I push my own dataLayer events from variant code?** Yes.
Variant JS can call `window.dataLayer.push({...})` freely. Just make
sure the event is not something GTM will misinterpret as an
ABTestly-internal event.

**Do I need a separate GTM container for ABTestly?** No. Use your
existing container and add tags that depend on ABTestly's
dataLayer events.
