Tag Verification: Proof a GTM Tag Fires, Not That It Exists
A container audit reads configuration. Tag Verification drives your pages in a real browser, reads what GTM reports through Tag Assistant, and returns a per-tag verdict with a screenshot.
Every GTM practitioner has signed off a container that looked right and was not. The tag was there, the trigger was attached, the variable resolved in Preview on your own laptop, and three weeks later the client asked why the lead form conversion had recorded zero events since the redesign. Nothing in the container changed. The page did. A container export cannot tell you that, because a container export describes intent, not what happened when the page loaded.
Tag Verification in AI Tag Manager exists to close that gap. It loads your pages in a real browser on a worker host, connects Google Tag Assistant to the container, clicks what a visitor would click, and reads what GTM says about itself: which events fired, which tags ran on each, and whether any tag threw. The output is one row per live tag with a status of Fired, Not fired or Not tested, a reason drawn from observed data, and a screenshot of the Tag Assistant panel for that tag. The page header says it plainly: prove a tag actually fires, rather than that it is configured to.
Why an audit cannot answer the question a verification answers
The Container Audit and Tag Verification look at the same container and answer different questions. An audit reads the GTM API. It can tell you a tag has no trigger, that a trigger references a missing variable, or that a Consent Mode setting is absent. Everything it knows comes from configuration. It never observes a page load, because nothing in the GTM API can.
Verification starts where the audit stops. A click trigger whose CSS selector matched the old button, a dataLayer push a developer renamed, a consent banner that now blocks the tag on first load: none of these are configuration errors, and all of them show up as a tag that simply does not fire. Run the audit first to clean up what is obviously wrong, then verification to find what is quietly wrong.
How verification observes a tag: the Tag Assistant debug stream
There are two ways to tell whether a tag fired from outside the page. Watching the network for the beacon works for GA4 and a handful of pixels, but it cannot distinguish a tag GTM evaluated and chose not to fire from one that fired and then threw, and it cannot see a custom HTML tag that sends nothing. The other way is asking GTM directly, and that is what this tool does.
When Tag Assistant connects to a page, GTM streams its debug feed to the Tag Assistant window as postMessage frames. The browser worker captures those frames verbatim with a message listener, with no scraping of the Tag Assistant UI. A parser turns them into per-event records: the dataLayer push that raised the event, the variables resolved at that moment, and each tag GTM ran with its execution status. One event looks like this after parsing:
{
"container": "GTM-ABC1234",
"epoch": 0,
"eventId": 7,
"eventName": "generate_lead",
"apiCall": { "event": "generate_lead", "form_id": "contact" },
"tags": [
{ "name": "GA4 - Lead", "status": "fired" },
{ "name": "Meta - Lead", "status": "failed" }
]
}Two details matter. The event name comes from the push itself, not the frame's label, which has been seen mislabelled in real captures. And the epoch field exists because gtm.uniqueEventId restarts at zero on every navigation; one debug session drives several pages, so without it page two's event 5 would overwrite page one's. That is what lets one session still attribute every verdict to the page it was decided on.
What a pass, a fail and a not-tested verdict actually mean
The verdict engine joins the parsed events against the container's list of unpaused tags. The rules are short, and they are what stop the report from lying in either direction.
| Status in report | What Tag Assistant saw | Reason text you will see |
|---|---|---|
| Fired | GTM started the tag on at least one event, and it either completed or was still running when the frame closed | The event it fired on, for example gtm.linkClick or generate_lead |
| Not fired | GTM ran the tag and it reported an error status | GTM ran this tag and it reported an error. |
| Not tested | The tag never appeared in any event during the run | Nothing in this run exercised what this tag fires on, so whether it works is unknown. This is not a pass. |
The third row is the one people argue about. A tag that never appears in the stream could be broken, or it could be a purchase tag on a site where the run never bought anything. The engine has a stricter mode that marks unseen tags as Fail when the run is known to have exercised the trigger, but the calls the UI makes today run with that mode off, so the report never turns an untouched tag into a failure. The success rate is computed over tested tags only, and a line under the KPI tiles says how many were excluded and that not tested is not a pass.
Across pages, worst wins. A tag that failed on /contact is Not fired in the merged report even if it fired cleanly on the home page, and the failing page is the one attached to the row.
What the tool loads and drives
A run has two working phases, and the stepper at the top of the page names every step: Container, URLs, Test Actions, Scan Pages, Verify Tags, Results.
The scan phase renders each page in the worker's headless browser, five at a time, and extracts click targets, forms, and same-origin links from the real DOM. Whole-site discovery follows those links breadth-first from the main URL up to 20 pages, skipping login, cart and checkout paths, and the activity log says how many pages were found but not scanned if the cap is hit.
The verify phase is where Tag Assistant gets involved. The container is read once from the GTM API for its public ID, its unpaused tag inventory, and a debug link built from a GTM environment. Pages are then driven four to a Tag Assistant session, one session at a time. In each, the worker loads the page and clicks up to 15 page-specific targets, plus up to 10 header and footer targets on the first page only, behind a navigation guard so a click that would leave the page is not followed. Each tag that fires gets its own screenshot of the Tag Assistant panel with that tag's card opened to its values; that is what the Evidence column shows, with the page-level shot as a fallback.
Why the run is chunked, and what the progress bar counts
Driving a page takes seven to ten seconds in the worker, and a Supabase edge function is killed at 150 seconds, so the first version, which sent every page in one request, died above the worker and left the UI on Verifying forever. Verification now calls the edge function once per chunk of four pages, and the bar under Verifying through Tag Assistant advances only when a chunk comes back: progress is completed pages, not an animation. Chunking also isolates failure. If a session dies, only those four pages fail, each with the error text on its own row, and an amber banner on Results offers Retry failed pages, which re-drives only those while keeping every proven verdict.
How to use it
- Open Tag Verification. On the Container step, pick an Account, a Container and a Workspace. Verification reads the tag list from that workspace.
- On the URLs step, enter a Main website URL so discovery finds pages for you, or paste Specific pages one per line (commas and spaces also separate). The panel tells you how many were entered, how many were invalid and why, and how many duplicates were folded, so the scanned count always reconciles to what you typed.
- On the Test Actions step, choose Click tracking, Form tracking or Clicks + forms. Click tracking is the default and submits nothing. The two form modes carry the warning Submits real forms on the card.
- Press Start page scan. The Activity feed and the Scanned pages table fill in with Status, Tags, Clickable and Forms per page. Click a failed row to read its error.
- Press Continue to verification. The button disables while the run is in flight.
- Read the Results: five KPI tiles (Pages scanned, Tags checked, Fired, Not fired, Success rate), an overall verdict card, filter chips per status, a search box, and a sort dropdown that defaults to problems first.
- Press Download CSV to export Tag Name, Status, Reason, Page URL, Actual Event and an Evidence column that says captured or none.
When the run cannot look, and how it tells you
The rule that shapes this tool is that an inability to observe is never shown as a finding about your container. Failures in that class render in a grey box, not a red one, with the line: Nothing was measured, so no result is shown. This is not a finding about your container.
- The worker is not configured. The browser host is a separate service; if the deployment has none, the edge function returns 503 before it spends any of your GTM API quota.
- The container has no usable environment. Tag Assistant needs a way in that requires no Google sign-in, so the tool builds a debug link from a GTM environment's authorization code, preferring the built-in latest environment. If none exists, the failure panel offers two exits: Create verification environment and retry, which adds an environment named AI Tag Manager Verification (a one-time, reversible container write that happens only on that click), or paste a Preview and Share link and press Retry with this link. The pasted link is used once and never stored, because share links expire in minutes.
- Tag Assistant saw a different container. The parser refuses to score if the expected public ID never entered debug mode, and the message names what it did see (It saw GTM-XYZ9876.), so a wrong link is a two-second fix rather than a report full of Not fired.
Per-page errors are different. A page that timed out gets a red row in the verification list with the actual error text underneath it, and shows up in the amber coverage banner on Results. The Pages scanned tile counts failed pages too, so the denominator stays honest. The silent tag failures post makes the same argument: the worst outcome is a report that looks complete and is not.
Reading a real failure
Suppose GA4 - Lead fired on /contact and Meta - Lead is Not fired on the same page with the reason GTM ran this tag and it reported an error. Expand the row: Actual event shows generate_lead. Press View image and the screenshot shows the Meta tag's card opened to its values, where the cause is usually visible: a pixel ID variable resolved to undefined, or a consent check returned denied because the run never accepted the banner. The audit would have called this tag correctly configured, because it was.
If instead the Meta tag shows Not tested, the run never pushed generate_lead, most likely because Click tracking mode does not submit forms. Switch to Clicks + forms, review the forms the scan found, and run again. The Page health list at the bottom of the report shows which pages tested nothing.
Limits, and when to use something else
Verification is client-side only. The footer of the page says so: server-to-server hits, meaning Meta Conversions API, server-side GTM and Measurement Protocol, cannot be seen from a browser and nothing here will ever claim to have checked them. If your setup routes through a server container, this proves the client half fired and says nothing about what the server did with it. The server-side GTM setup guide covers that half.
A run is a snapshot of the pages you listed on the day you ran it. It does not tell you a tag will keep firing after tomorrow's deploy, or that event volume in GA4 is normal. For that, GA4 Monitoring compares each property's daily event counts against the previous day and posts to Slack when a metric drops or spikes.
Other limits worth knowing. Discovery stops at 20 pages. Form modes submit real forms, so use staging or reviewed values. A container whose tags all sit behind a purchase or a login will mostly come back Not tested, and the report says so rather than inventing a pass. And nothing here signs a server-side browser into your Google account; the run needs an environment or a preview link.
Where it sits in a measurement workflow
Think of the three tools as three tenses. The Container Audit answers what the container is, from the API. Tag Verification answers what it did when a browser loaded the site: which tags fired, on which events, with what values. GA4 Monitoring answers whether it is still doing that, every morning, in Slack. Run the audit when you inherit a container, verification before and after every release, and monitoring always.
If you generated tags with the AI Generator, verification is the last gate before you publish, and the ninety-minute audit playbook slots a run into its final twenty minutes for that reason.
To try it, open Tag Verification, pick the container you are least sure about, paste the three pages that matter most, leave the mode on Click tracking, and read the Not tested count before the success rate. That number is how much of your container a browser can reach without a purchase or a form, and it is usually the first thing worth fixing.