The Blog

GTM without torching your LCP

Web performance

Marketing needs tracking tags. Performance needs discipline. We load Google Tag Manager through Next.js's own third-party helpers so analytics doesn't compete with the content visitors came to see.

The problem

Third-party scripts that compete with your content

Every marketing site needs analytics. Most need Google Tag Manager for event tracking, conversion pixels, and remarketing tags. The tension is that every third-party script competes with your own content for browser resources, network bandwidth, parse time, execution time.

The classic approach is pasting a script snippet in the <head>. It works, but the browser has to download, parse, and execute the script before it can finish rendering the page. On a fast connection, the impact is small. On a mobile device over 4G, which is how most visitors actually arrive, a render-blocking script in the head can measurably delay LCP.

The problem compounds. GTM loads its own container, which loads additional scripts based on the tags configured inside it. One snippet in the head becomes a cascade of requests, each adding latency before the visitor sees the content they came for.

The approach

@next/third-parties for controlled loading

Next.js provides @next/third-parties a package with components that load common third-party services using optimised strategies. Instead of a raw script tag, you render a <GoogleTagManager> component with your container ID. The component handles loading timing, script placement, and the data layer setup.

In our layout, we load GTM if a container ID is configured. If there's no GTM ID but there is a Google Analytics measurement ID, we fall back to the <GoogleAnalytics> component instead. This keeps the layout clean, one conditional, not two competing script blocks.

The key difference from a raw snippet is loading strategy. The @next/third-parties components defer script loading so they don't block initial render. The browser prioritises your content, HTML, CSS, above-the-fold images, and the analytics script loads after the critical path is clear.

Honest limits

Third-party scripts still have a cost

Loading GTM through `@next/third-parties` reduces the impact on initial render, but it doesn't eliminate the cost of third-party scripts entirely. GTM still downloads its container. The tags inside that container, analytics, remarketing pixels, conversion tracking, still execute and make their own network requests.

The real discipline is in what goes inside GTM, not just how GTM loads. Every tag added to the container has a performance cost. Consent management platforms, heat mapping tools, chat widgets, A/B testing scripts, each one adds JavaScript that the browser has to process.

We keep the GTM container lean. Essential analytics and conversion tracking go in. Anything that can be deferred or loaded conditionally based on user interaction stays out of the initial container load.

The framework-level loading strategy handles the "when." The container management handles the "what." Both matter for Core Web Vitals

The choice

Why we prefer GTM when both could exist

Google Tag Manager and Google Analytics can both be loaded independently. Running both creates redundant requests — GTM typically loads GA as one of its tags anyway.

We set the layout to check for a GTM container ID first. If it exists, we load GTM and let it manage GA internally. If there's no GTM container but there is a GA measurement ID, we load GA directly. This ensures exactly one analytics loading path per page, not two.

For most marketing sites, GTM is the better default. It gives the marketing team the ability to add and modify tags without code changes. GA alone requires developer involvement for every new tracking event or conversion pixel. The tradeoff is a slightly larger initial payload, GTM's container script plus its configuration, but the operational flexibility usually justifies it.

Little Dash

Wondering what's slowing your site down?

Run your URL through our free page speed checker to see where your Core Web Vitals stand against Google's ranking thresholds.