---
name: "tag_manager_audit"
description: "Audit a tag manager container before it costs data: export and inventory every tag, trigger and variable, prove duplicate fires in Preview, check Consent Mode v2 built-in and additional checks on denied and granted runs, review server-side routing, and run a pause-then-delete cleanup that removes dead tags without breaking live measurement. Use when a container has grown unchecked, counts do not match the source system, a site or consent change is planned, or nobody can say what is firing and why."
---

# Tag Manager Audit

## Purpose
Produce a complete inventory of a tag manager container, a set of findings backed by live firing evidence, and a cleanup plan that removes dead and duplicate tags in stages. The audit covers Google Tag Manager web containers first, and the same inventory and evidence rules apply to other tag managers. A settings screenshot is not evidence. A tag is only called duplicate, dead or consent-safe after the live checks in the workflow.

## Workflow

1. **Export before you touch anything.** In Tag Manager, go to Admin, then Export Container, and export the current published version. Google exports containers as JSON that can be compared, stored in version control and reimported, so file that export as the backup and the rollback. Record the container ID, the version number, the export date and who has publish rights. If two containers for the same site exist in the account list, stop and resolve which one the site actually loads first. Two live containers is a finding by itself.

2. **Build the inventory from the export, not by scrolling the interface.** Run `bin/audit_container.py <container.json> --out-dir <audit-folder>`. It writes `inventory.csv` and `findings.md` and prints counts for tags, triggers and variables plus static flags: paused tags, duplicate candidates that share a type and a firing trigger set, tags with no firing trigger, unused triggers, unreferenced variables and Custom HTML or Custom Image tags. Then extend the CSV from `assets/container-inventory.csv` with three columns the export cannot give you: destination ID (the GA4 measurement ID, ad account or pixel ID the tag sends to), owner, and last verified date. A tag with no owner and no destination anyone recognises goes to the top of the cleanup list.

3. **Check installation outside the container.** View the page source or use Tag Assistant on the home page, a product or article page, and the conversion page. Count how many times the container snippet appears and whether any analytics or ad tag is also hardcoded in the page or loaded by a platform app or plugin. The classic duplicate is a hardcoded GA4 or gtag snippet left in place after the same tag was added in the container, or a shop platform app and a container tag both sending the same purchase. The container export will never show a hardcoded tag, so this check is manual and mandatory.

4. **Prove firing in Preview, one journey at a time.** Connect Preview through Tag Assistant and walk the journeys that matter: landing, key browse, signup or add to cart, and the completed conversion. For each journey, record per tag whether it fired, on which event, and how many times for one real action. Expected is once per intended action. Use GA4 DebugView or the destination test tool to confirm the event landed, because a tag firing in Preview only proves the browser half. Any tag that fires twice for one action, fires on the wrong event, or fires in Preview but never lands is a defect with the journey and the count written in the inventory notes.

5. **Run the consent audit on both paths.** Follow `references/consent-checks.md`. First list the consent design in writing: Basic or Advanced mode, the consent platform, and the default state for each of the four Consent Mode v2 signals: ad_storage, analytics_storage, ad_user_data and ad_personalization. Then check settings: Google tag, Google Analytics, Google Ads, Floodlight and Conversion Linker tags carry built-in consent checks per Google, so they should have no additional consent checks layered on in Tag Manager. Every non-Google tag and Custom HTML tag needs an explicit additional consent decision, Require additional consent for tag to fire with the types named, or a written reason it needs none. Then run live: one fresh profile rejecting all, one accepting all, reading the Consent tab in Tag Assistant and watching which tags fire in each run. Settings alone do not pass this step.

6. **Audit triggers and variables for rot.** Work the static flags, but verify each one before calling it dead. Consolidate triggers that differ only by a page path value into one trigger with a condition list, where the tags using them agree. Check that click and form triggers use stable identifiers, not visible text that marketing can rename. For variables, check data layer variables against the data layer pushes seen in Preview: a variable reading a key no push provides returns undefined on every event, and that often explains a conversion value of zero. Custom JavaScript variables must return a value synchronously. Anything that needs a network call belongs in site code pushing to the data layer, not in a variable.

7. **Review Custom HTML tags as code, because they are code.** Read each one line by line. Record what it loads, what data it reads from the page or data layer, where it sends data, and who owns it. Flag any that read form fields, email addresses or full URLs with query strings, any that load a script from a vendor nobody can name, and any with no owner. These tags bypass most template review, so they carry the highest privacy and breakage risk in the container.

8. **Note the server-side state.** Follow `references/server-side-basics.md`. Record whether a server container exists, which tags route through it, which still fire direct from the browser, and whether the same conversion is sent both ways without the same event name and event ID to deduplicate it. Ask for the list of parameters the server container strips before forwarding. If there is no server container, write that down as the current state. Do not turn an audit into a server migration pitch unless duplication, page weight or data control findings in this container justify it.

9. **Write the cleanup plan before changing the live container.** Use `assets/cleanup-plan-template.md`. Every removal gets one row: the evidence it is dead or duplicate, the destination checked, and the staged plan. The staging is fixed: pause the tag in one publish, watch one full business cycle for the destination it fed, then delete in a second publish and re-run step 4 on the affected journeys. Triggers and variables are deleted only after every tag that referenced them is gone or rewired, and the auditor script shows no remaining reference.

10. **Publish, verify and compare counts.** Publish cleanup changes as their own container version with a version name that says audit cleanup and the date. Re-run the core journeys in Preview on the published version by browsing the live site with Tag Assistant, confirm each kept conversion lands once, and compare destination counts for a like-for-like period before and after. State the numbers: conversions per day before, conversions per day after, and the difference explained by the duplicates and dead tags removed. If a kept conversion drops to zero, restore the backup export or the previous version first and investigate second.

## Output Contract
An audit folder containing: the container export used, `inventory.csv` covering every tag, trigger and variable with type, paused state, firing triggers, destination ID, owner and verdict of keep, fix, pause or remove, `findings.md` from the auditor plus the live Preview and consent findings the static checks cannot produce, and a filled cleanup plan from `assets/cleanup-plan-template.md` with pause and delete versions and post-cleanup count comparison. A clean container is a valid result: say so, list what was checked, and give the next audit trigger (site redesign, consent change, new ad platform, or a set quarterly date).

## Operating Rules
1. **Export first, always.** No audit and no cleanup starts without a filed export of the published version. It is the inventory source and the rollback in one file.
2. **Static flags are candidates, not verdicts.** The auditor groups, counts and flags. Only Preview firing counts, destination landing checks and consent runs turn a flag into a finding.
3. **One action, one fire.** A conversion or pageview tag that fires twice for one real action is a defect, whether the second copy comes from a duplicate container tag, a hardcoded snippet, a platform app or a server route with a different event ID.
4. **Pause before delete.** Removing a tag in the same publish that first disables it destroys the easy rollback. One business cycle paused, then delete, then verify.
5. **Built-in consent tags get no extra checks.** Google tags that carry built-in consent checks must not have additional consent checks layered on in Tag Manager. Non-Google tags must have an explicit additional check or a written exemption. Both halves are audited.
6. **Denied and granted are separate tests.** A consent setup tested only with cookies accepted has not been tested. Record both runs, per tag family.
7. **No owner, no stay of execution.** A tag nobody owns, sending to a destination nobody recognises, is removed on the staged plan after the pause watch shows no destination impact anyone can name. Sentiment about an old campaign is not ownership.
8. **Do not fix measurement by deleting the evidence.** If counts in the destination do not match orders or leads in the source system, keep the mismatched tags in place until the duplicate or gap is located. Deleting first makes the cause unfindable.
9. **Version names carry the audit.** Every publish from an audit names the audit and the step, so the version history alone can reconstruct what changed and when.
10. **Report counts, not adjectives.** Tags before and after, duplicates found with their firing counts, consent runs passed and failed, conversions before and after. A reader should be able to redo the arithmetic from the inventory and findings files alone.
