Your GA4 purchase event fires before the data layer has the transaction value. Your conversion tag loads before the consent check completes. Your Facebook Pixel tries to read a variable that another tag hasn’t set yet. All of these are tag sequencing problems.
By default, GTM doesn’t guarantee the order tags fire. If two tags share the same trigger, they might fire in any order. Tag sequencing lets you enforce dependencies — “fire tag A first, then tag B, and only if tag A succeeds.”
How Tag Sequencing Works
Every tag in GTM has an Advanced Settings → Tag Sequencing section. It gives you two options:
- Setup Tag — a tag that fires BEFORE the current tag
- Cleanup Tag — a tag that fires AFTER the current tag
Setup Tag (fires first)
↓
Main Tag (fires second)
↓
Cleanup Tag (fires third)
You can also check the box: “Don’t fire [Main Tag] if [Setup Tag] fails.” This creates a hard dependency — if the setup tag errors out, the main tag is skipped entirely.
Where to Find It
- Open any tag in GTM
- Scroll to Advanced Settings
- Expand Tag Sequencing
- Select a setup tag and/or cleanup tag
When You Need Tag Sequencing
Use Case 1: Data Layer Push Before Conversion Tag
Problem: Your conversion tag reads {{transactionTotal}} from the data layer, but sometimes the data layer push hasn’t happened yet when the tag fires.
Solution: Create a Custom HTML tag that pushes the data to the data layer (setup tag), then sequence it before your conversion tag.
Setup Tag: "Push Transaction Data" (Custom HTML)
↓
Main Tag: "Google Ads Conversion" (reads {{transactionTotal}})
Setup tag (Custom HTML):
<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
'transactionTotal': document.getElementById('order-total').textContent,
'transactionId': document.getElementById('order-id').textContent
});
</script>
Main tag: Google Ads Conversion Tracking tag that references {{transactionTotal}} and {{transactionId}}.
Check “Don’t fire Main Tag if Setup Tag fails” to prevent the conversion tag from sending $0 values.
Use Case 2: Consent Check Before Any Tracking
Problem: You need to verify consent status before firing tracking tags, but your consent management platform loads asynchronously.
Solution: Create a consent verification tag as a setup tag for your tracking tags.
Setup Tag: "Verify Consent" (Custom HTML)
↓
Main Tag: "GA4 Page View"
Note: For most consent scenarios, Consent Mode v2 handles this natively within GTM. Tag sequencing is useful when you have custom consent logic that Consent Mode doesn’t cover.
Use Case 3: Initialize SDK Before Firing Events
Problem: A third-party SDK (like a chat widget or analytics tool) needs to initialize before you can call its tracking methods.
Solution:
Setup Tag: "Initialize Chat SDK" (Custom HTML - loads the SDK)
↓
Main Tag: "Track Chat Open Event" (Custom HTML - calls SDK method)
Setup tag:
<script>
(function() {
window.ChatSDK = window.ChatSDK || {};
// SDK initialization code
var script = document.createElement('script');
script.src = 'https://chat-sdk.example.com/v2/init.js';
script.onload = function() {
window.ChatSDK.init({ apiKey: 'abc123' });
};
document.head.appendChild(script);
})();
</script>
Important caveat: Tag sequencing waits for the setup tag to execute, but not necessarily for asynchronous operations within it to complete. If the setup tag loads an external script asynchronously, the main tag might fire before that script finishes loading.
For truly asynchronous dependencies, use a Custom Event trigger instead:
<script>
var script = document.createElement('script');
script.src = 'https://chat-sdk.example.com/v2/init.js';
script.onload = function() {
window.ChatSDK.init({ apiKey: 'abc123' });
// Push event when SDK is actually ready
window.dataLayer.push({ event: 'chat_sdk_ready' });
};
document.head.appendChild(script);
</script>
Then trigger the main tag on the chat_sdk_ready custom event instead of using tag sequencing.
Use Case 4: Cleanup After Conversion
Problem: After a conversion fires, you want to clear the data layer to prevent duplicate events if the page is refreshed.
Solution:
Main Tag: "Google Ads Conversion"
↓
Cleanup Tag: "Clear Transaction Data" (Custom HTML)
Cleanup tag:
<script>
window.dataLayer.push({
'transactionTotal': undefined,
'transactionId': undefined,
'event': 'transaction_cleared'
});
</script>
Use Case 5: Tag A’s Output Feeds Tag B
Problem: Tag A generates a value (like a session ID or experiment variant) that Tag B needs to read.
Example: An A/B testing tool assigns a variant, then your analytics tag needs to include that variant as a parameter.
Setup Tag: "Assign Experiment Variant" (Custom HTML)
↓
Main Tag: "GA4 Page View" (includes experiment_variant parameter)
Setup tag:
<script>
var variant = Math.random() > 0.5 ? 'control' : 'treatment';
window.dataLayer.push({
'experiment_variant': variant,
'experiment_id': 'homepage_cta_test'
});
</script>
Main tag: GA4 Event tag with custom parameters experiment_variant = {{DL - experiment_variant}} and experiment_id = {{DL - experiment_id}}.
Tag Sequencing vs. Trigger Priority
GTM offers two ways to control execution order:
Tag Sequencing (Per Tag)
- Controls order between specific tags
- Creates hard dependencies
- Can prevent main tag from firing if setup fails
- Scoped to individual tags
Tag Firing Priority (Per Trigger)
- Controls which tags fire first within a shared trigger
- Higher number = fires first
- No dependency enforcement (a tag with priority 10 fires before priority 5, but priority 5 fires regardless of whether priority 10 succeeds)
- Useful for ordering within a batch
When to use which:
| Scenario | Use |
|---|---|
| Tag B depends on Tag A’s output | Tag Sequencing |
| Tag A must succeed for Tag B to run | Tag Sequencing (with failure check) |
| Multiple tags on same trigger, order matters but no dependency | Tag Firing Priority |
| Consent check before all tracking | Consent Mode (or Tag Sequencing) |
| Loading SDK before calling its API | Custom Event trigger (not sequencing) |
Tag Firing Priority Deep Dive
Found in Advanced Settings → Tag Firing Priority (not Tag Sequencing — they’re separate settings).
Set a numeric value. Higher numbers fire first:
| Tag | Priority | Fires |
|---|---|---|
| Data Layer Enrichment | 100 | First |
| GA4 Page View | 50 | Second |
| Meta Pixel | 50 | Tied with GA4 (order not guaranteed) |
| Cleanup Script | 0 | Last |
Tags with the same priority fire in undefined order. If two tags MUST fire in a specific order relative to each other, use tag sequencing instead of priority.
Limitations
Setup Tags Can Only Be Non-Firing Tags
The setup tag must use the “Once per event” tag firing option. It can’t be a tag that also fires independently on other triggers (well, technically it can, but it creates confusing behavior where the tag fires both as a setup tag and independently).
Best practice: Create dedicated setup tags that exist solely to support sequencing. Don’t repurpose tags that also fire on their own.
No Chains Beyond Three
Tag sequencing is limited to one level:
Setup → Main → Cleanup ← This works
Setup → Middle → Main → Cleanup ← This does NOT work
You can’t chain setup tags. If you need a multi-step sequence, use Custom Event triggers to create the chain:
Tag 1 fires → pushes dataLayer event → Tag 2 fires → pushes dataLayer event → Tag 3 fires
Asynchronous Operations Aren’t Waited On
As mentioned earlier, tag sequencing waits for the setup tag’s JavaScript to execute, not for its asynchronous operations (script loads, API calls, timeouts) to complete.
If your setup tag does something asynchronous, use the Custom Event pattern instead.
Debugging Tag Sequences
GTM Preview Mode
- Enable Preview Mode
- Navigate to the page where your sequenced tags fire
- Click on the event (e.g., “Page View”) in the left panel
- Check the Tags panel — it shows execution order
- Verify setup tags fired before main tags
- Check for “Tag Not Fired” entries and hover for the reason
Tag Assistant (Companion)
The Tag Assistant shows detailed timing for each tag, including:
- When the trigger condition was met
- When the setup tag started and finished
- When the main tag started
- Any errors in the setup tag
If you need to debug broader GTM container issues, start with a full container audit before diving into sequencing problems.
Common Patterns
The Safe Conversion Pattern
Setup: Push order data to dataLayer (Custom HTML)
↓ (Don't fire Main if Setup fails)
Main: Google Ads Conversion Tag
↓
Cleanup: Clear order data from dataLayer
The Pixel Loading Pattern
Setup: Check if pixel is loaded (Custom HTML)
↓ (Don't fire Main if Setup fails)
Main: Custom event to pixel (Custom HTML)
The Variable Resolution Pattern
Setup: Resolve [GTM variables](/blog/gtm-variables-explained) from async source (Custom HTML)
↓ (Don't fire Main if Setup fails)
Main: Analytics tag using resolved variables
Checklist
- Identified tags with execution order dependencies
- Setup tags created as dedicated tags (not dual-purpose)
- “Don’t fire if setup fails” checked where appropriate
- Async operations use Custom Event pattern instead of sequencing
- Tag firing priorities set for non-dependent ordering
- Sequences verified in GTM Preview Mode
- Published and tested in production
Tag sequencing prevents race conditions that silently break your tracking. A conversion tag that fires before the data layer is ready sends $0 values. An analytics tag that fires before the SDK loads throws errors. Five minutes of setup now saves hours of debugging later.
Want to check if your GTM tags are firing in the right order? Run a free scan — we audit your tag configuration, trigger setup, and sequencing automatically.