Google Tag Manager on its own rarely slows a website down. Google's web.dev guide on tags and tag managers puts the GTM library at around 33 KB compressed. What slows sites down is everything that piles up inside the container over the years: Custom HTML tags, heatmaps, chat widgets, A/B testing snippets and duplicate pixels. They fight your page for bandwidth and the main thread, and that's what drags down INP and LCP. The fix is to find the expensive tags, then remove them, delay them or move them server-side.
Here's how I find the tags that hurt Interaction to Next Paint (INP) and Largest Contentful Paint (LCP), what I delete and what I delay, when server-side tagging is worth paying for, and how I load scripts on Next.js and WordPress.
How do you know if Google Tag Manager is slowing your site?
Google Tag Manager is slowing your site if blocking googletagmanager.com in Chrome DevTools noticeably improves LCP, INP or main-thread time. If those numbers barely move, GTM isn't the problem.
Start with the targets. Google's Web Vitals thresholds count an LCP of 2.5 seconds or less and an INP of 200 milliseconds or less as good. Tags hit each metric in a different way:
- LCP suffers when tags download and run during page load, taking bandwidth and main-thread time away from your hero image and text.
- INP suffers when tag JavaScript keeps the main thread busy, so taps and clicks are slow to respond. web.dev says Google has seen a correlation between larger tag managers and worse INP scores.
- CLS suffers when a tag injects a banner, popup or widget after the page has already rendered.
There's a catch when you read the reports. Most tools pin the cost of a Custom HTML tag on the tag manager that injected it, not on the tag itself. So when PageSpeed Insights shows a lot of time on gtm.js, it often means one tag inside the container is slow. GTM is just the messenger.
Because GTM is on so many sites, it's always the first suspect. The 2024 Web Almanac found that 92% of pages use at least one third party, and googletagmanager.com is among the ten most common third-party domains. It also showed GTM pulling in other domains in a chain, from google-analytics.com to facebook.net. One container can mean a dozen requests.
How do you find which tags hurt INP and LCP?
Check field data, block GTM in Chrome DevTools, record real interactions in the Performance panel, then test the suspect tags one at a time. That's the order I work in on an audit, and it's the same on WordPress and Next.js.
- 1
Check field data first
Open PageSpeed Insights or the Core Web Vitals report in Search Console. Note which metric fails, on mobile or desktop, and on which page types.
- 2
Run the blocking test
In Chrome DevTools, use Network request blocking to block googletagmanager.com and run a Lighthouse or Performance trace again. If LCP and main-thread time barely change, GTM isn't your bottleneck.
- 3
Record a real interaction
In the Performance panel, record yourself opening the menu, adding to cart or submitting a form. Look for long tasks and which third-party script ran them.
- 4
List every tag
Write down each tag's type, trigger, owner and the business decision it supports. Tags nobody can explain go on the removal list.
- 5
Test suspects one at a time
Measure a page with only the suspect tag, or publish a version without it to a test environment. Don't compare Web Vitals in GTM Preview mode, because Preview runs slower.
That last point comes straight from Google: web.dev warns that Preview mode adds overhead, so its timings won't match production.
If you'd rather not read a Lighthouse report line by line, paste it into my free Page Speed Fix Planner. It tells you which Core Web Vitals pass or fail, what's causing each problem and which fixes to do first, third-party script cost included.
Which tags should you delay, and which should you remove?
Remove tags nobody owns or uses. Delay tags that are useful but heavy, like chat widgets and heatmaps. Leave GA4 loading normally.
My rule is simple: if nobody can tell me who owns a tag and what decision it feeds, it goes. web.dev recommends labelling every tag with an owner for exactly this reason, because people are scared to delete tags they don't understand. These are the usual offenders:
| Tag type | Why it hurts | What I'd do |
|---|---|---|
| Duplicate GA4 (hard-coded plus GTM, or a plugin plus GTM) | Two scripts and double-counted data | Remove one install |
| Tags from old campaigns or past agencies | Code still ships in the container | Delete them. Don't block with a trigger exception |
| Heatmaps and session recording | Heavy JavaScript that watches every interaction | Limit to key pages, sample traffic or run for set periods |
| Live chat widgets | Large bundles loaded on every page | Load on click or after the page is idle, outside GTM |
| A/B testing with an anti-flicker snippet | Hides the page until the script loads, delaying LCP | Remove it or move testing server-side |
| Ad pixels (Meta, Google Ads, LinkedIn) | Fire on every page load | Fire on conversion events only, or move them server-side |
| Cookie banner loaded through GTM | A visible element arrives late, hurting LCP and CLS | Load it directly in the page |
| Custom HTML with a pasted vendor library | Bloats the container and can't be cached separately | Use a template or an external script src |
Two details from web.dev's guidance matter here. Pausing or removing a tag takes its code out of the container, but blocking it with a trigger exception doesn't. And Google caps containers at 300 KB, while the median site's container sits around 50 KB. If yours is near the cap, nobody's been cleaning it.
Triggers matter as much as the tags. Fire anything non-essential on Window Loaded or a custom event, not on page view, and only on the pages that need it. Watch out for "All Elements" click triggers attached to heavy tags. That work runs on every tap, which is exactly what INP measures. Delete unused variables too, since Custom JavaScript variables get evaluated over and over.
Does server-side tagging make your site faster?
Yes, when several ad pixels run in the browser, because each vendor's JavaScript moves off the visitor's device and onto your own tagging server. No, when the slowdown comes from chat widgets or heatmaps.
With server-side tagging, the browser sends one stream of events to your tagging server, and that server passes the data on to GA4, Meta, Google Ads and the rest. The vendors' scripts stop running in the visitor's browser. web.dev lists it as an option for larger sites that want more control over their data, with one caveat: only some vendors support it.
It has limits. You still need a lightweight web container or Google tag in the browser to send the events. And if a chat widget or heatmap is what's slowing you down, server-side tagging does nothing, because those tools have to run in the browser.
The hosting isn't free, so compare costs before you commit:
| Hosting option | Typical monthly cost | Source |
|---|---|---|
| Stape free tier | $0 up to 10,000 requests a month | Upstack Data |
| Stape paid plans | From $20 a month | Stape |
| Google Cloud Run | About $45 per server, at least two recommended, so roughly $90 | Scandiweb, citing Google |
| Google Cloud production setup | $120 minimum, up to $250–$300 | Stape (a competing host, so read it as their estimate) |
Then someone has to set it up, maintain it and keep the consent settings right. If your site only runs GA4, I'd clean up the container first. Server-side tagging starts to pay off when you're running three or four ad platforms and their pixels are clearly costing you speed.
How should you load GTM and third-party scripts in Next.js?
Use the GoogleTagManager component from the official @next/third-parties package for GTM, and next/script with afterInteractive or lazyOnload for other third-party scripts. You get far more control than with a pasted snippet.
The GoogleTagManager component fetches the container after hydration, so it doesn't compete with your first render:
// app/layout.tsx
import { GoogleTagManager } from '@next/third-parties/google'
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<GoogleTagManager gtmId="GTM-XXXXXXX" />
<body>{children}</body>
</html>
)
}
The same package has a sendGTMEvent helper that pushes events to the dataLayer, so you don't end up with hand-written listeners scattered through your components. For scripts outside GTM, use next/script with afterInteractive (the default), or lazyOnload for anything that can wait. Don't use beforeInteractive for marketing tags. For chat widgets, I render a lightweight button and only load the real widget when someone clicks it. The Partytown-based worker strategy is still experimental in Next.js, so I don't trust it with production tracking.
If your Next.js site fails INP for reasons beyond tags, my guide to fixing Core Web Vitals on Next.js covers the rest.
What are the WordPress-specific fixes?
Keep a single Google Tag Manager install, get rid of duplicate pixels added by plugins, and delay heavy widgets rather than analytics. WordPress sites tend to pick up tracking from several places at once, so these are the checks I run first:
- One install only. Pick one of Site Kit, GTM4WP, the theme's header field or custom code in Elementor or Bricks. View the page source and search for
gtm.jsand your GA4 measurement ID. If either appears twice, you're paying for it twice. - Check plugin pixels. WooCommerce marketing plugins often add their own Meta or Google pixels while the same pixels fire from GTM as well. Keep one source.
- Delay the right things. WP Rocket, Perfmatters and LiteSpeed Cache can hold JavaScript back until the visitor interacts. Use that for chat widgets, heatmaps and social embeds, not your analytics.
- Don't expect caching to fix it. Page caching speeds up how HTML is delivered. Tag scripts still run in the browser.
- Update your CSP. If you send security headers, your Content-Security-Policy has to allow Google's tag domains. Add them to the right directives and test in report-only mode before you enforce it. Check what your site currently sends with my free Security Headers Checker, and if a policy has already blocked your tags, see how to fix a Content Security Policy that broke WordPress. I maintain the HTTP Security Header plugin, which sets CSP from a settings screen.
Delaying GTM can hide the problem
Holding the whole container until the first interaction makes Lighthouse scores look great, but it skews your data and shifts the cost onto real visitors. Delay individual heavy tags instead.
On WordPress builds where I set up GA4 and Tag Manager myself, like the Aura Clips agency site on Bricks Builder, the tracking goes in as part of the build. Starting lean like that is far easier than untangling a five-year-old container later. For the wider WordPress picture, see how to fix Core Web Vitals on WordPress.
What should you ask a developer before they touch your tags?
Ask how they'll measure field data before and after, and how they'll confirm GA4 and ad conversions still fire once they're done. Tag cleanups go wrong when tracking breaks quietly and nobody spots it for a month. Get answers to these first:
- Will you measure field data before and after, not just a Lighthouse score?
- How will you check that GA4 conversions, ad conversions and form events still fire after the cleanup?
- Which tags do you plan to remove, and who approves the list?
- Will you export a container backup and name each version you publish?
- Does server-side tagging actually fit our vendor list, and what will hosting cost each month?
- If you delay scripts in WordPress, which ones will be excluded, and why?
If you're setting up tracking from scratch, keep it lean from day one: one GTM container, a named owner for every tag, and ad pixels that fire on conversions only.
What's the next step?
Run your slowest page through PageSpeed Insights and paste the report into the Page Speed Fix Planner. If Google domains or Custom HTML tags are at the top of the list, start there. If you want me to audit the container and fix INP and LCP without breaking your conversion tracking, have a look at my technical SEO and Core Web Vitals service, or book a 20-minute call and tell me what PageSpeed is flagging.



