- Do not install ABTestly through GTM.
- 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.
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 theexperience_impression
dataLayer event (see 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>
Consent
If your GTM setup uses Google Consent Mode, the two systems compose. ABTestly’s own consent gate (Consent) waits forwindow[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 callwindow.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.