Skip to content
← Back to Blog

The Tag You Forgot to Remove

Universal Analytics was sunset in July 2023. Three years later, UA tags are still executing in containers across the web, pushing events to endpoints that no longer process data.

The Tag You Forgot to Remove

Universal Analytics stopped processing data in July 2023. Google gave years of warning, ran migration wizards, sent emails, and eventually turned the lights off. The GA4 migration is done.

The UA tags are still running.

Dead code that fires on every page load

A Universal Analytics tag in a GTM container does the same thing today that it did in 2022. It initializes a tracking library, constructs a hit payload, and sends a network request to Google's collection endpoint. The browser executes the JavaScript, resolves the DNS, opens the connection, and transmits the data. The only difference is that Google discards the hit when it arrives. The data goes nowhere, but the work happens on every page load for every visitor.

This isn't a theoretical concern about tidy containers. Each UA tag adds a network request, JavaScript execution time, and a DNS resolution to the page. On a site with 500,000 monthly visitors, that's 500,000 requests per UA tag per month to an endpoint that returns nothing useful. Multiply by the average number of UA tags still present in a container (often 3-5 between pageview, event, and transaction tags), and the dead weight becomes meaningful for page performance even though no data is collected.

The tags persist because removing them feels risky. Someone configured them, they might still be needed, and nobody is certain which UA property they pointed to or whether the data was feeding a report someone relies on. Three years after sunset, the answer is definitive: no UA property is processing data. Every UA tag is dead code.

The archaeological layers

UA tags are the most recent layer of dead code, but containers accumulate tracking artifacts from every generation of Google Analytics.

The oldest layer is _gaq.push(). This is the API for ga.js, Google's JavaScript tracking library that predated analytics.js (which itself predated GA4). A container with _gaq.push() calls has code from before 2014. The ga.js library stopped being updated years before that, and Google has long since stopped serving it in any meaningful capacity. These calls exist because someone added them to a Custom HTML tag a decade ago and nobody has looked inside that tag since.

The next layer is __utmz cookie reads. The __utmz cookie tracked campaign attribution in Universal Analytics. It stored the traffic source, medium, campaign name, and keyword for each session. When UA was sunset, the __utmz cookie stopped being set. But Custom HTML tags that read __utmz to pass campaign data to other systems are still executing. They read a cookie that no longer exists, get an empty value, and pass that emptiness downstream. If the receiving system treats empty values differently from missing values, this can produce subtle data quality issues in whatever platform is consuming the data.

These are archaeological layers. Each generation of Google Analytics left code behind in containers, and containers don't clean themselves up. Tags get paused rather than deleted. Custom HTML gets disabled by commenting out the code rather than removing the tag. The container grows a sediment of dead implementations that make every audit harder because the reviewer has to determine which tags are active, which are paused, which are dead, and which are dead but still executing.

Paused tags are not the same as dead tags

A paused tag is explicitly disabled through GTM's interface. It won't fire regardless of its triggers. It's inert, takes up no runtime resources, and has no effect on the page or the data. The only cost is clutter: a paused tag makes the container harder to navigate and audit.

A dead tag is active, firing, and executing code that produces no useful result. UA tags fall into this category. They're not paused. They fire on their configured triggers, execute their JavaScript, and send network requests. They consume browser resources on every page load. They just don't produce data anymore because the receiving endpoint stopped processing it.

The distinction matters for prioritization. Paused tags are cleanup work that can wait. Dead tags are active waste that should be addressed sooner because they affect page performance with zero return. Removing a dead UA tag reduces page load work immediately. Removing a paused tag reduces clutter but changes nothing about how the page performs.

How dead code accumulates

The pattern is consistent across containers of every size. A tag gets added for a specific purpose: a vendor integration, a campaign tracking requirement, a testing setup. The tag works, the project moves forward, and the tag stays. When the vendor relationship ends or the campaign concludes, nobody removes the tag because nobody is sure it's safe to remove, nobody remembers adding it, or the person who added it no longer works there.

Pausing is the path of least resistance. It's reversible, it's low-risk, and it takes one click. Deleting requires confidence that the tag isn't needed, which requires understanding what the tag does, which requires reading the configuration or the Custom HTML code, which takes time nobody has allocated. So the tag gets paused, and the container gains another entry in its inventory of disabled-but-present components.

Over time, this produces containers with 13 paused tags on average. The worst cases reach into the hundreds. These containers function correctly because paused tags don't fire, but they're harder to audit, harder to hand off to a new team, and harder to understand for anyone encountering them for the first time.

The cleanup process

Removing dead code from a GTM container is mechanical work, not strategic work. The steps are specific.

Start with UA tags. Any tag with a type of Universal Analytics (ua) is dead. Check whether it's active or paused. If active, it's consuming resources and should be removed or paused immediately. If paused, it can be removed during a cleanup pass. Before deleting, note the UA property ID and the event configuration in case the organization needs a historical record of what was being tracked.

Then check Custom HTML for legacy patterns. Search the code in Custom HTML tags for _gaq.push, ga('send', and __utmz. Any tag containing these patterns is either dead code or contains dead code alongside other functionality. Tags that only contain legacy code can be removed. Tags that mix legacy code with active functionality need the legacy portions stripped out.

Finally, review paused tags. For each paused tag, determine when it was last active (the container version history shows this) and what it does. Tags paused for more than six months with no documentation are candidates for removal. If uncertain, the safest approach is to leave them paused and document the decision rather than deleting something that might need to be referenced later.

The cleanup produces an immediate benefit in container legibility. A container with 80 active tags and 13 paused tags feels different from a container with 80 active tags, no paused tags, and a version note explaining what was removed and why. The second container is the one the next person can understand.

The ongoing problem

Dead code accumulation is not a one-time cleanup problem. It's a lifecycle issue. Every tag added to a container will eventually become dead code unless someone actively manages its lifecycle: reviewing whether it's still needed, updating it when the vendor changes their implementation, and removing it when the purpose has been fulfilled.

Containers without this lifecycle management grow continuously. They gain 5-10 tags per year from new vendor integrations, campaign tracking, A/B testing tools, and analytics experiments. They lose zero tags because nothing triggers removal. After 4-5 years, the container has 40-60 tags of accumulated history alongside its 20-30 active tags. The active tags are the container's job. The historical tags are its debt.

A quarterly review of the tag inventory (which tags are active, which are paused, which are still needed) prevents the accumulation from reaching the point where a full archaeological dig is required. The review doesn't need to be comprehensive. It needs to catch the obvious: vendor relationships that ended, campaigns that concluded, testing tags that should have been temporary. Fifteen minutes per quarter is enough to prevent fifteen hours of cleanup later.

See what's in your setup

Enter your URL for a health score, consent check, and prioritized findings.

Scan Now — Free