Skip to content

What a GTM audit should actually cover

Most containers are messy but functional. The question isn't "how many problems are there" — it's whether your tracking works, your consent is compliant, and you know what to fix first. Here's what we check and why.

Ten areas of container health

A GTM audit that only checks one thing misses the picture. Consent, analytics, advertising, performance, and organization are all connected. Here's how we break it down.

Every check, explained

Search or filter to find specific checks. Each one maps to a real issue we've seen in production containers, with a description and a fix.

85 rules
Error Dead Code

Dead __utmz cookie reference

Tags reference __utmz cookies from Universal Analytics, which was sunset in July 2023. These cookies are no longer set by any active system.

Fix: Remove or replace the UTM cookie system. Build attribution from URL parameters directly.
Error Dead Code

Dead _gat._getTrackers() call

Tags use the _gat._getTrackers() method from the legacy ga.js library, deprecated since 2014.

Fix: Remove the legacy ga.js tracker code entirely.
Error Dead Code

Dead _gaq.push() call

Tags push events to _gaq, the legacy ga.js async queue. ga.js has been deprecated since 2014.

Fix: Remove _gaq.push calls and migrate to GA4 events.
Error Dead Code

Dead ga('send') Universal Analytics call

Tags use ga('send', ...) from analytics.js (Universal Analytics). UA was sunset July 2023.

Fix: Remove analytics.js calls and use native GA4 event tags.
Optimization Dead Code

Paused tags older than 6 months

Tags have been paused for over 6 months. Paused tags still add to container size and create maintenance confusion.

Fix: Delete paused tags or document why they must stay. Don't leave them indefinitely.
Info Dead Code

Potentially stale domain references

Tags reference domains that may no longer be active, such as previous brand names or old store URLs.

Fix: Verify the domains are still valid and update or remove stale references.
Info Ads

Hardcoded conversion values

Conversion tags use hardcoded dollar amounts instead of dynamic values from the data layer, leading to inaccurate revenue reporting.

Fix: Replace hardcoded values with a data layer variable that captures the actual transaction amount.
Optimization Data Quality

Multiple googtag configs with same ID prefix

Multiple Google Tag configurations for the same platform can cause double-counting of pageviews and events.

Fix: Consolidate into a single Google Tag config per measurement ID.
Optimization Data Quality

Duplicate external script loaded

The same external script is loaded by multiple tags, creating redundant network requests and potential race conditions.

Fix: Load the script once with a dedicated tag and reference it from others.
Optimization Data Quality

Custom HTML replaceable by native GTM template

Custom HTML implementations exist for platforms that have native GTM tag templates available.

Fix: Replace with the official GTM template for better consent integration and maintenance.
Optimization Data Quality

Duplicate event listeners across tags

Multiple custom HTML tags add listeners for the same DOM events, which can cause race conditions and double-firing.

Fix: Consolidate event listeners into a single tag or use GTM's built-in trigger types.
Optimization Data Quality

Custom event trigger with no filter conditions

Custom event triggers fire for every instance of the event regardless of context, catching unintended events.

Fix: Add filter conditions to narrow the trigger to specific events.
Optimization Data Quality

Lookup table missing default value

Lookup table variable has no default value configured, returning undefined for unmatched inputs.

Fix: Set a sensible default value for the lookup table.
Optimization Data Quality

Tag setup dependency chain

Tags depend on setup tags to fire first, creating fragile firing sequences that break if timing changes.

Fix: Use GTM's tag sequencing or move shared logic into a variable.
Optimization Data Quality

Overloaded trigger firing 10+ tags

A single trigger fires 10 or more tags simultaneously, creating a burst of network requests that can impact page performance.

Fix: Review whether all tags genuinely need the same trigger or can be staggered.
Optimization Data Quality

Tags with 10+ blocking triggers

Tags have 10 or more blocking (exception) triggers, creating fragile configurations that are hard to debug.

Fix: Simplify by inverting the logic: use a single inclusive trigger with filter conditions.
Optimization Data Quality

Trigger with overly broad regex pattern

Regex filters use patterns like ".*" or ".+" that match everything, providing no actual filtering.

Fix: Replace with a specific regex pattern or remove the filter entirely.
Optimization Data Quality

Tag fires on both page-load and custom event

Tag fires once on page load and again when a custom event occurs, potentially double-counting conversions.

Fix: Choose one trigger type or add conditions to prevent duplicate fires.
Optimization Data Quality

dataLayer.push race condition

Multiple Custom HTML tags push to dataLayer on the same trigger without priority ordering, creating timing-dependent behavior.

Fix: Set tag firing priorities or consolidate dataLayer pushes into a single tag.
Optimization Data Quality

Variable referencing 5+ other variables

A variable references 5 or more other variables, creating a single point of failure in the variable chain.

Fix: Simplify the variable chain or use a Custom JavaScript variable to consolidate logic.
Info Data Quality

Direct document.cookie access

Custom JavaScript variable accesses document.cookie directly instead of using GTM's built-in Cookie variable type.

Fix: Use GTM's 1st Party Cookie variable for cleaner and more maintainable cookie access.
Error PII

Base64 encoding used for PII

Tags use btoa() to encode data. Base64 is trivially reversible and is not encryption — PII sent this way is still exposed.

Fix: Remove PII from tags entirely, or hash with SHA-256 before sending.
Optimization Performance

jQuery dependency in custom HTML

Custom HTML tags use jQuery ($() or jQuery()) without guaranteed loading, causing errors if jQuery isn't present.

Fix: Replace with vanilla JavaScript or ensure jQuery loads before the tag fires.
Optimization Performance

document.write() usage

Tags use document.write(), which blocks page rendering and can cause blank pages when fired asynchronously.

Fix: Replace document.write with DOM manipulation methods (createElement, appendChild).
Optimization Performance

innerHTML assignment detected

Tags assign to innerHTML, which can execute embedded scripts and poses XSS risk if content includes user data.

Fix: Use textContent for text or createElement for DOM manipulation.
Optimization Performance

All Pages trigger with URL-specific code

Tags fire on every page but contain URL-checking logic, wasting execution time on irrelevant pages.

Fix: Move URL conditions into the trigger filter instead of the tag code.
Error Security

eval() usage detected

Tags use eval(), which executes arbitrary strings as code. This is a critical XSS vector.

Fix: Replace eval() with JSON.parse() for data parsing or refactor the logic to avoid dynamic code execution.
Error Security

HTTP (non-secure) resource loading

Tags reference HTTP URLs instead of HTTPS, creating mixed content warnings and enabling man-in-the-middle attacks.

Fix: Change all resource URLs to use HTTPS.
Info Organization

Empty folders found

Folders contain no tags, triggers, or variables — artifacts from previous configurations that add clutter.

Fix: Delete empty folders to keep the container organized.
Info Organization

Orphaned triggers (not used by any tag)

Triggers not referenced by any tag, likely leftover from deleted tags.

Fix: Delete orphaned triggers or attach them to the correct tags.
Info Organization

Orphaned variables (not referenced anywhere)

Variables not referenced by any tag, trigger, or other variable in the container.

Fix: Delete orphaned variables to reduce container size and maintenance overhead.
Info Organization

Tags with no folder assignment

Tags are not assigned to any folder, making the container difficult to navigate at scale.

Fix: Organize all tags into folders by function or team.
Info Organization

Default or placeholder names

Items still have default names like "Untitled Tag", "Copy of…", or auto-generated names.

Fix: Rename to follow a consistent naming convention (e.g., "GA4 – purchase – All Pages").
Info Organization

Tags without structured naming convention

Tags lack structured naming separators (-, –, |, :), making it hard to identify purpose at a glance.

Fix: Adopt a naming convention like "Platform – Action – Trigger" across all tags.
Info Organization

Mixed naming separators

Container uses multiple different separator styles inconsistently (dashes, pipes, colons).

Fix: Standardize on a single separator style across all names.
Info Organization

Variables without type prefixes

Variables lack standard type prefixes (DLV, CJS, LUT, CONST, etc.) making it hard to identify variable types.

Fix: Add type prefixes to variable names (e.g., "DLV – page_type", "CJS – getUserId").
Info Organization

Duplicate custom event triggers

Multiple triggers listen for the same custom event, creating redundancy and confusion about which trigger to use.

Fix: Consolidate into a single trigger per custom event name.
Info Organization

Excessive global variable declarations

Tags declare multiple global variables (window.x) which can conflict with site code and other tags.

Fix: Wrap code in IIFEs or use dataLayer instead of global variables.
Optimization GA4

Event names with uppercase letters

GA4 event names use uppercase letters. GA4 treats "Add_To_Cart" and "add_to_cart" as separate events, fragmenting data.

Fix: Use lowercase snake_case for all event names to match GA4 conventions.
Optimization GA4

Event names exceed 40-character limit

Event names longer than 40 characters are silently truncated by GA4, potentially merging distinct events.

Fix: Shorten event names to under 40 characters.
Error GA4

Event names with invalid characters

Event names contain spaces, hyphens, or start with a number. GA4 will reject or silently rename these events.

Fix: Use only letters, numbers, and underscores. Must start with a letter.
Optimization GA4

Reserved event names used

Event names conflict with GA4 reserved names for automatic tracking (e.g., first_visit, session_start).

Fix: Rename to a custom event name that doesn't collide with reserved names.
Error GA4

Events exceed 25-parameter limit

Event tags send more than 25 custom parameters. GA4 drops parameters beyond this limit silently.

Fix: Reduce to 25 or fewer parameters per event. Move low-priority data to user properties.
Optimization GA4

Parameter names exceed 40 characters

GA4 parameter names longer than 40 characters are silently truncated.

Fix: Shorten parameter names to under 40 characters.
Optimization GA4

debug_mode hardcoded to true

debug_mode is set to literal "true" instead of a GTM variable, so it stays on in production.

Fix: Use a GTM variable (e.g., Lookup Table) to toggle debug_mode per environment.
Optimization GA4

Duplicate event names across tags

Multiple active tags send the same event name, causing double-counting of events in reports.

Fix: Consolidate duplicate events into a single tag or differentiate the event names.
Optimization GA4

GTM tags duplicating Enhanced Measurement

GTM tags send events that GA4 Enhanced Measurement also tracks automatically (scroll, click, video, etc.).

Fix: Disable Enhanced Measurement for events you track via GTM, or remove the GTM tags.
Error GA4

Purchase event missing required parameters

Purchase event missing transaction_id, value, or currency — required for revenue reporting in GA4.

Fix: Add all three required fields: transaction_id, value, and currency.
Optimization GA4

Ecommerce events in too many separate tags

Many separate GA4 tags handle individual ecommerce events instead of consolidating with the ecommerce data layer.

Fix: Use GA4's built-in ecommerce support with a single tag per measurement ID.
Optimization GA4

Purchase event on page-load trigger

Purchase event triggered by page-load instead of a custom event trigger, which may fire before ecommerce data is ready.

Fix: Fire purchase on a custom event trigger (e.g., dataLayer push with transaction data).
Info GA4

Measurement ID hardcoded

GA4 measurement ID hardcoded as a literal value instead of using a GTM variable for reuse and easy updates.

Fix: Store the measurement ID in a Constant or Lookup Table variable.
Info GA4

Similar event name proliferation

Similar events that differ only by suffix could be consolidated (e.g., button_click_header, button_click_footer).

Fix: Use a single event name with a parameter to distinguish context.
Error GA4

Parameters with PII-suggesting names

Parameters with names like "email", "phone", or "user_name" — GA4 prohibits sending PII.

Fix: Remove PII parameters or hash values with SHA-256 before sending.
Optimization GA4

Custom HTML using gtag() instead of native

Custom HTML contains gtag() calls instead of using native GA4 event tags, losing consent integration and debugging.

Fix: Replace with native GA4 Event tags in GTM.
Error GA4

Event parameters with PII-risk names

Parameters with names that strongly suggest personally identifiable information is being collected.

Fix: Remove PII from event parameters. Use user properties with hashed identifiers instead.
Error GA4

Parameters using reserved prefixes

Parameters use reserved prefixes (ga_, google_, firebase_, gtag., or leading underscore) that GA4 silently drops.

Fix: Rename parameters to avoid reserved prefixes.
Info GA4

Parameter names with inconsistent casing

The same parameter name appears with different casing across GA4 tags, fragmenting data in reports.

Fix: Standardize parameter names to consistent lowercase snake_case.
Info GA4

Parameters with inconsistent hardcoded vs dynamic values

The same parameter is used with both hardcoded strings and GTM variables across different tags.

Fix: Standardize on variables for consistency and easier updates.
Optimization GA4

Event tags with Once Per Page firing

GA4 event tags set to fire Once Per Page, which silently drops repeat events on single-page applications.

Fix: Change to "Unlimited" or "Once Per Event" firing for SPA-compatible tracking.
Error Ads

No Conversion Linker tag found

Google Ads tags are present but no Conversion Linker tag exists for proper cross-domain attribution.

Fix: Add a Conversion Linker tag firing on All Pages.
Optimization Ads

Conversion tags on page-load trigger

Ad conversion tags triggered by page-load instead of a custom event, which may misattribute conversions.

Fix: Fire conversion tags on specific custom event triggers (e.g., purchase, signup).
Optimization Ads

Conversion Linker not on All Pages

Conversion Linker is not configured to fire on All Pages, breaking cross-domain tracking on some pages.

Fix: Change the Conversion Linker trigger to All Pages.
Optimization Ads

Ad tag proliferation

An ad platform has excessive tag counts (10+ native or 5+ Custom HTML), indicating consolidation opportunity.

Fix: Consolidate ad tags and use a single tag per platform action where possible.
Info Ads

Ad platform IDs hardcoded in 3+ tags

Ad account IDs are hardcoded in 3 or more tags instead of using a reusable GTM variable.

Fix: Store ad IDs in a Constant variable and reference it from all tags.
Optimization Ads

Custom HTML ad pixels without consent

Custom HTML ad pixels are configured with consent NOT_NEEDED or NOT_SET. Custom HTML tags have no Built-In consent protection — they fire unconditionally unless you set consent requirements in GTM.

Fix: Add proper ad_storage consent requirement to all Custom HTML ad pixels.
Optimization Ads

Same platform as native tag and Custom HTML

An ad platform is deployed via both native GTM tags and Custom HTML, creating duplicate tracking.

Fix: Remove the Custom HTML version and use the native GTM tag exclusively.
Optimization Ads

Google Ads conversion without remarketing tag

Google Ads Conversion Tracking tags present but no remarketing tag for audience building.

Fix: Add a Google Ads Remarketing tag to enable audience lists.
Error E-commerce

Ecommerce events without Send Ecommerce data

GA4 ecommerce event tags don't have "Send Ecommerce data" enabled, so transaction data is silently lost.

Fix: Enable "Send Ecommerce data" in the tag's ecommerce settings.
Optimization E-commerce

Ecommerce events on page-load triggers

Ecommerce action events triggered by page-load instead of custom event, firing before data layer is ready.

Fix: Fire ecommerce events on dataLayer push triggers.
Optimization E-commerce

Incomplete ecommerce funnel

Container tracks purchase but is missing key funnel steps (view_item, add_to_cart, begin_checkout).

Fix: Implement the full ecommerce funnel for meaningful drop-off analysis.
Optimization E-commerce

Ecommerce tools via Custom HTML

Custom HTML implements ecommerce marketing platforms (Hotjar, Klaviyo, etc.) instead of native integrations.

Fix: Check if a native GTM template exists for the platform.
Optimization E-commerce

Ecommerce tools without consent

Custom HTML ecommerce tools are configured without any consent requirement.

Fix: Add appropriate consent requirements based on the tool's data usage.
Optimization Consent

Ad tags firing without consent

Advertising and conversion tags have no Additional consent configured. For native Google tags (Ads Conversion, Remarketing, GA4), Built-In consent automatically enforces the correct consent signals — NOT_NEEDED is Google's recommended setup. For Custom HTML and non-Google templates, this is a real gap.

Fix: Custom HTML ad tags: add ad_storage consent. Native Google tags with Built-In consent: no action required unless your CMP setup needs explicit Additional consent.
Error Consent

No CMP detected

Tags require consent but no Consent Management Platform is detected in the container.

Fix: Install a CMP (CookieBot, OneTrust, etc.) and configure it to fire on Consent Initialization.
Error Consent

CMP detected but consent mode not wired

A CMP is installed but 80%+ of tags have no consent configuration, making the CMP effectively decorative.

Fix: Configure consent types on all tags that collect or process user data.
Optimization Consent

CMP not on Consent Initialization trigger

CMP tag is not configured to fire on the Consent Initialization trigger, causing a timing gap.

Fix: Move the CMP tag to fire on Consent Initialization (not All Pages or DOM Ready).
Optimization Consent

Ad tags using analytics_storage instead of ad_storage

Advertising tags have Additional consent set to analytics_storage instead of ad_storage. For native Google tags, Built-In consent already includes ad_storage — the Additional analytics_storage creates an unnecessary second gate. For non-native tags, this is the wrong consent type.

Fix: Native tags: remove the unnecessary Additional analytics_storage check. Non-native tags: change to ad_storage.
Optimization Consent

Ad tags missing ad_user_data consent

Ad tags have ad_storage but are missing the ad_user_data consent type required by the EU Digital Markets Act. Tags with Built-In ad_user_data coverage (Google Ads Conversion, Remarketing) are excluded from this check.

Fix: Add ad_user_data as an additional required consent type for tags without Built-In coverage.
Optimization Consent

Remarketing tag missing ad_personalization

Remarketing tag is missing the ad_personalization consent type. Google Ads Remarketing tags have Built-In ad_personalization coverage and are excluded from this check.

Fix: Add ad_personalization as a required consent type on remarketing tags without Built-In coverage.
Optimization Consent

GA4 events with consent NOT_NEEDED

GA4 event tags have Additional consent set to NOT_NEEDED. Native GA4 tags have Built-In analytics_storage that automatically respects Consent Mode v2 — this is Google's recommended setup. Non-native GA4 implementations need explicit consent.

Fix: Native GA4: no action required (Built-In handles it). Non-native: add analytics_storage consent.
Optimization Consent

GA4 tags missing analytics_storage consent

GA4 tags have Additional consent configured without analytics_storage. For native GA4 tags, Built-In analytics_storage is active regardless — the Additional types create an extra gate.

Fix: Review whether the Additional consent types are intentional. Built-In analytics_storage handles analytics consent automatically.
Optimization Consent

Conversion Linker missing ad_storage

Conversion Linker has consent configured without ad_storage. Native Conversion Linker tags have Built-In ad_storage coverage and are excluded from this check.

Fix: Add ad_storage as a required consent type on Conversion Linker tags without Built-In coverage.
Optimization Consent

CMP waitForUpdate is 0 or missing

CMP has waitForUpdate set to 0 or not configured, so tags may fire before the user responds to the consent banner.

Fix: Set waitForUpdate to at least 500ms to give the CMP time to load.
Optimization Consent

Non-standard consent types used

Tags use consent types not in the Consent Mode v2 specification (ad_storage, analytics_storage, etc.).

Fix: Use standard Consent Mode v2 types for cross-platform compatibility.
Optimization Consent

Ad tags missing ad_personalization

Ad tags require ad_storage but are missing ad_personalization. Tags with Built-In ad_personalization coverage (Google Ads Conversion, Remarketing) are excluded from this check.

Fix: Add ad_personalization consent type to advertising tags without Built-In coverage.

How findings are prioritized

Not everything needs fixing today. Findings are grouped by what matters to the business, so you focus on real problems before cleanup tasks.

Error
Investigate first

Patterns involving data loss, PII exposure, security concerns, GA4 data rejection, and consent gaps. Worth understanding before making other changes.

Highest impact on health score
Optimization
Worth reviewing

Things that work but could work better: data quality patterns, consent configuration, redundant tags, naming inconsistency, and performance considerations.

Moderate impact on health score
Info
Good to know

Naming patterns, folder organization, cleanup opportunities, and maintenance suggestions. Context for understanding the container, not urgent work.

No impact on health score

See what's in your container

Upload your GTM export and get results in seconds. No account needed.

Scan Now