All posts
MeasurementStep-by-step

GTM Audit Checklist: Turn Review Notes Into Checks

A GTM audit in 9 checks: duplicate conversion tags, Custom HTML on all pages, hard-coded IDs, click triggers, consent, unused tags, versions and access.

October 3, 2026·8 min read·by Olexander Cheberko
Table of contentstap to expand

A GTM audit checks that each tag in your Google Tag Manager container fires once, on the right event, with a deliberate consent setting, and that you know who can publish. The nine checks below cover duplicate conversion tags, Custom HTML on all pages, hard-coded IDs, click triggers, consent, unused tags and variables, version notes and user access, and four of them end in a rule a script can enforce.

Start here

What Google already flags

Check 1: Does Tag Diagnostics flag a missing tag?

WhereTag ManagerGoogle tagsyour Google tag
Do: Open the Google tag settings and, under Your Google tag, in the Tag quality section, select View diagnostics (Google: Tag Diagnostics).
You should see: Neither Missing conversion linker, raised when a Google Ads or Floodlight tag has no conversion linker tag in the container, nor Missing Google tags, raised when event tags have no matching Google tag.
If not: Add what is missing: a Google tag with your ID in Tag ID on Initialization - All Pages (setup), and a Conversion Linker on All Pages, which Google recommends so the linker is active on any potential landing page.
Careful: Some of your pages are not tagged means pages that never loaded the Google tag: the container itself, not a tag inside it. The list is in the Google tag under Admin > Tools > Tag coverage (tag coverage).

Conversion tags

Check 2: Does each conversion action have one tag?

WhereTag ManagerTags
Do: Open every Google Ads Conversion Tracking tag and note its Conversion ID and Conversion label (Google: conversion tags in GTM).
You should see: Each label in one tag only; two tags with one label report a lead twice.
If not: Pause or delete the copy. If the action's event snippet also runs in the site code or a CMS plugin, keep one install: Google warns that double-tagging can cause duplicate conversion reporting.
Careful: A GA4 key event for the same form, imported into Google Ads and set to primary, counts the lead again in the Conversions column, where Google Ads reports primary actions, and no tag in GTM shows it. The GA4 audit starts with that question.

Check 3: Does the conversion fire only on a confirmed submit?

WhereTag ManagerTagsconversion tagTriggering
You should see: A Page View trigger limited to the thank-you page, a Form Submission trigger with Check Validation on, which fires only if the form is successfully sent, or a Custom Event trigger on what the form pushes to the data layer, which Google suggests when the form's submit event is overridden.
If not: Replace any click trigger, All Elements or Just Links, on the submit button. A click trigger fires when an element is clicked, so a submit that fails validation still counts as a lead. See which trigger fits which form.

Check 4: Are IDs variables, not typed values?

WhereTag ManagerTagsTag Configuration
You should see: A variable in the Conversion ID field and in the Google tag's Tag ID. Google's conversion help says to use Tag Manager variables for the conversion tag's fields whenever applicable.
If not: Click Variables, then New under User-Defined Variables, and choose Constant, the type Google says is commonly used when multiple tags use the same account number. Select it in each tag.

Everything else that runs

Check 5: Does any Custom HTML run on every page?

WhereTag ManagerTagsCustom HTML
Do: Open each Custom HTML tag and read its Triggering.
You should see: For each tag, someone who can say why it is there, and a trigger limited to the pages that use it, as Google's tag best practices advise.
If not: Swap vendor code for a built-in template where one exists; Google calls templates the best way to avoid performance and malware issues. Otherwise give it a page view trigger limited to those pages (page view triggers).
Careful: An administrator can require 2-step verification before anyone edits Custom HTML tags or Custom JavaScript variables: Admin > Account Settings > Require 2-step login verification for certain operations (Google).

Check 6: Does every tag have a consent decision?

WhereTag ManagerAdminContainer Settings
Do: Under Additional Settings, select Enable consent overview, then click Tags and the Consent Overview icon (Google: consent in Tag Manager).
You should see: No tags under Consent Not Configured.
If not: In each tag, open Advanced Settings > Consent Settings and pick No additional consent required, which marks a tag as needing nothing beyond its built-in consent checks, or Require additional consent for tag to fire, which fires only when every listed consent type is granted.
Careful: Consent defaults can differ by region, so test from where your visitors are. My agents once reported consent denied with no banner on a site; it held only because they ran from Bulgaria, and I withdrew the finding.

Check 7: Is anything left that nobody uses?

WhereTag ManagerTags and Variables
Do: For variables, export the container under Admin > Export Container and search the file for each name in double braces, the form tags use to reference it.
You should see: Every tag has a firing trigger, which every tag needs to fire, no tag is kept off with a trigger exception, and every user-defined variable is referenced.
If not: Pause a tag you will need again (pause) and delete the rest with bulk actions. Google advises pausing or removing over blocking, since only those take the code out of the container, and removing old variables, which add size and processing time.

Who changes the container

Check 8: Does each version say what changed?

WhereTag ManagerVersions
You should see: A Version Name and Version Description on each version that say what changed, and a date in the Published column, the publish history that shows when versions were live and who published them.
If not: Fill both in at Submit. Under Admin > Container Notifications, set notifications for a published version to Always so Tag Manager emails you each one.

Check 9: Do the right people hold Administrator and Publish?

WhereTag ManagerAdminUser Management
Do: Open User Management in the Account column, then in the Container column.
You should see: At least two account administrators from inside the business; Google says the account should be managed by someone in your organization, not an external agency. Publish on the container only for people who publish.
If not: Add a second Administrator, lower anyone who does not publish to Read, Edit or Approve, and Remove people who have left. Tag Diagnostics shows Only one administrator detected until you do.
Careful: Tag Manager cannot stop an account being left without an admin when the sole admin's Google account is deleted elsewhere, and an account or container with no admin is deleted automatically.

Turn each review note into a rule

Lauren Tan, an engineer at Cursor, said in a recorded talk on trusting coding agents that the worst place to be is enforcing a codebase's rules by hand in code review. Instead of writing such a comment, she says to ask "how do I turn this into a hard rule": a lint or a CI failure. She layers rules and skills on top but does not rely on them alone, since agents can forget them. A container review note such as "this tag has no consent setting" returns next quarter unless something fails when it does.

An exported container is JSON that Google says can be compared and stored in a version control system to review changes before publishing. The script below reads one and exits with an error on four of the notes above. It uses only fields from Google's Tag and Parameter references, and the tag ID shapes follow Google's tag ID examples.

import json, re, sys
from collections import defaultdict
 
data = json.load(open(sys.argv[1], encoding="utf-8"))
version = data.get("containerVersion", data)
errors, same, ids = [], defaultdict(list), defaultdict(set)
 
def values(params):
    for p in params or []:
        if isinstance(p.get("value"), str):
            yield p["value"]
        yield from values(p.get("list"))
        yield from values(p.get("map"))
 
for tag in version.get("tag", []):
    name = tag["name"]
    if tag.get("paused"):
        continue
    if not tag.get("firingTriggerId"):
        errors.append(f"{name}: no firing trigger, it never fires")
    status = tag.get("consentSettings", {}).get("consentStatus", "notSet")
    if status.replace("_", "").lower() == "notset":
        errors.append(f"{name}: consent not configured")
    params = tag.get("parameter", [])
    same[(tag["type"], json.dumps(params, sort_keys=True))].append(name)
    for v in values(params):
        if re.fullmatch(r"(AW|G|GT)-[A-Z0-9]+|\d{6,}", v):
            ids[v].add(name)
 
for names in same.values():
    if len(names) > 1:
        errors.append("same type and settings: " + ", ".join(names))
for value, names in ids.items():
    if len(names) > 1:
        errors.append(f"{value} typed into {len(names)} tags: use a Constant variable")
 
print("\n".join(errors) or "0 errors")
sys.exit(1 if errors else 0)

Save it as gtm_rules.py and run it on each export before you publish. It catches exact copies (check 2), an ID typed into more than one tag (check 4), unset consent (check 6) and the trigger half of check 7. Click triggers, Custom HTML scope and version notes still need a person until each gets a line of its own.

I run this blog the same way. Rules for my writing agents, such as no em dashes, no links to removed pages and no invented frequency claims, now fail a lint script. I approve every commit myself, and no agent pushes on its own.

After the audit

A clean container sends each lead to Google Ads once, on a real submit, with consent decided. Which leads became a booked appointment or a sale is in your CRM or phone system, and getting that back into Google Ads bidding is the closed-loop measurement I set up.

Tags

gtm-auditgoogle-tag-manager-auditgtm-audit-checklisttag-diagnosticsgoogle-tag-managerconversion-tracking

Frequently asked questions

Does Google have a free GTM audit tool?

Partly. Tag Diagnostics, built into your Google tag settings, flags a missing conversion linker, missing Google tags, pages that never loaded the tag and an account with only one administrator. It does not review triggers, Custom HTML or consent settings tag by tag, so checks 2 to 8 still need a person or a script.

Can I audit a Google Tag Manager container with Read access?

For the review, yes. Read lets a user browse the tags, triggers and variables in a container without the ability to change anything. Fixing what you find needs Edit, creating a version needs Approve, and publishing it needs Publish.

Should I pause or delete unused tags in Google Tag Manager?

Pause a tag you will need again, such as one for a timed campaign, and delete the rest. Do not keep a tag off with a trigger exception: Google's tag best practices note that pausing or removing a tag takes its code out of the container, while blocking does not. Either change takes effect only after you save and publish.

How do I find unused variables in GTM?

Export the container under Admin > Export Container and search the file for each user-defined variable's name in double braces, the form tags, triggers and other variables use to reference it. A name that never appears that way is unused, and you can delete it with the bulk actions on the Variables table.

Related posts