A container grows by adding and rarely by removing. This check reads a Google Tag Manager export in the browser and lists what is no longer connected to anything: tags without a working trigger, triggers and variables that nothing references, leftover templates and folders, and elements kept alive only by paused tags. Broken references (a trigger ID or a {{variable}} that does not exist) and duplicate IDs are listed as well, because they are the faults that make a tag silently send nothing.
In Tag Manager: Admin → Export Container, for a version or the workspace. The API format of a container version works too.
Everything below can go, grouped as in Tag Manager. Delete in this order: tags, triggers, variables, templates, folders, so that nothing still refers to an element when it is removed. Built-in variables are not deleted but unticked under Variables → Configure. Entries marked “only used by …” become free once the elements named there are gone.
These are not deletions but faults to fix: references that point nowhere, duplicate IDs and similar.
Overview
| Element | In the container | Cleanup candidates |
|---|
Structure: the export format (containerVersion with lists of tags, triggers, variables, folders, built-in variables, templates, zones, clients and transformations), duplicate IDs and duplicate names.
References: firing and blocking triggers, members of trigger groups, setup and cleanup tags by name, every {{variable}} in parameters, filters and consent fields, custom template types (cvt_…) and folder IDs. Names are compared exactly, including case and spaces.
Orphans: a tag is live when it is not paused and has an existing firing trigger or is started by a live tag. Triggers, variables and templates are followed from live tags, zones, clients and transformations. What is not reached is either unused (nothing refers to it) or used only by dead elements (only paused or never-firing elements refer to it).
Order: broken references first, then unused elements, then points worth a look.
The check works on names and IDs inside the export. It cannot see a name that a script assembles as plain text, an element that another workspace still uses, or a tag that is kept on purpose. A listed element is a candidate, not a verdict: compare with the version history and the preview before deleting. Server containers are read the same way, and references from clients and transformations count as live.
The container JSON is read and analysed in the browser and is sent nowhere. Exports contain tag IDs, measurement IDs and sometimes pixel codes or keys inside custom HTML; for that reason nothing is stored or transmitted here, and the result areas are excluded from session recording.
More tools for GTM containers:
- GTM Duplicates Analyser – finds tags, triggers and variables that do the same thing twice.
- GTM Naming Convention Auditer – checks element names against an agreed convention.
- GTM Container History & Deep Search Engine – finds the version in which an element was added, changed or removed.
- GTM DataLayer Variable Path Flattener – turns a nested dataLayer object into the variable paths to create.
- Text & Code Diff – compares two exports, for example before and after a cleanup.
Articles on keeping a container in order:
- Tutorial: Agreeing a GTM Naming Convention and Enforcing It on an Existing Container – names make orphans easy to spot.
- Comparing Two GTM Container Exports – how to confirm that a cleanup removed only what it should.
- Tutorial: Finding the Container Version in Which a Tag Changed – for the moment a removed element turns out to be needed.
- Tutorial: Using Claude Code to Prepare and Review Google Tag Manager Changes – review a cleanup before it is published.