Get your free SEO audit today Call 91 060 30 90
</>Technical Guide · 18 min read

Third-party scripts and Core Web Vitals: the technical cost of tags, pixels and widgets

The Core Web Vitals guide in this section covers the three metrics and how they're measured. This guide focuses on one of the most common, and hardest to fix, causes of those metrics getting worse on sites that otherwise have reasonably optimized first-party code: third-party scripts. Tag managers, ad pixels, live chats, review widgets, embedded video players and personalization tools are, together, one of the largest sources of JavaScript running on a page that the team building it doesn't directly control the weight or behavior of.

The problem isn't that these tools are bad: almost all of them solve a real business need. The problem is that they get added one at a time, each one looks "lightweight" on its own, and the cumulative effect on the browser's main thread is rarely audited as a whole until the metrics are already bad.

Why a "small" script can have a big cost

A third-party script's weight in kilobytes is only part of its real cost. What most affects Interaction to Next Paint (INP) and, to a lesser degree, Largest Contentful Paint (LCP) isn't how heavy the file is, but how much main-thread execution time it consumes: parsing the JavaScript, executing it, and in many cases continuing to run code periodically after the initial load (trackers listening for scroll or click events across the whole page, for example). A script that's only a few kilobytes but runs an expensive loop on every scroll can have a worse INP impact than a much heavier script that runs once and then sits idle.

The real cost of tag managers

A tag manager (Google Tag Manager and equivalents) isn't heavy by itself, but it's a container that loads and executes other third-party scripts based on configured rules, often set up by marketing teams without direct visibility into the technical impact of each tag they add. The problem isn't the tool, it's the lack of governance: over time, a container accumulates tags nobody uses anymore, duplicates of the same pixel added twice by mistake, or tags configured to fire on every page when they're only needed on one specific section.

A periodic container audit (which tags are still active, which ones fire and how often, what's their individual weight and execution time measured with browser performance tools) is the only way to keep something that, by design, grows over time with no visible technical friction on each individual addition, under control.

Lazy loading: not everything needs to load before interaction

The most effective technique for reducing the impact of third-party scripts unrelated to the main content is deferring their load until after the page is interactive, instead of loading them in parallel with critical resources. A live chat, a reviews widget or a remarketing pixel almost never need to be ready in the first second; they can load after the page's load event, or even after the user's first real interaction (the first scroll or the first click), without that noticeably hurting their function.

// Load a third-party script after the page is interactive
window.addEventListener('load', () => {
    const script = document.createElement('script');
    script.src = 'https://example.com/reviews-widget.js';
    script.async = true;
    document.body.appendChild(script);
});

The "facade" pattern: simulate the widget until it's actually needed

For heavy widgets that do need to be visible from the start (an embedded video player, an interactive map), the facade technique shows a lightweight, static version that visually mimics the real widget (a cover image with an overlaid play button, in a video's case) and only loads the widget's heavy script when the user interacts with that facade, not before. YouTube and Vimeo offer variants of this technique natively; for first-party or third-party widgets that don't, it can be implemented manually by replacing the real widget with an image and a click event that loads the script only at that point.

Splitting long tasks: why the main thread blocks even if the script finishes quickly

When a third-party script runs a long uninterrupted task (a block of JavaScript that takes more than 50 milliseconds to execute in one go), the browser's main thread stays blocked for that duration and can't respond to any user interaction, which is exactly what Interaction to Next Paint measures (and penalizes). Many poorly optimized third-party scripts run exactly that pattern: heavy one-time initializations that block the main thread for hundreds of milliseconds at the worst possible moment, right when the page finishes loading and the user starts interacting.

When the script is first-party (or from a vendor that allows configuration), splitting that initialization into smaller chunks using requestIdleCallback or yielding control back to the main thread between chunks avoids the prolonged block, even if total execution time is similar. When the script is third-party with no control over its internal code, the only real lever is controlling when it loads and executes, not how it executes internally.

A pattern that needlessly worsens the problem: conditionally loading all analytics and marketing scripts' execution, but still downloading their JavaScript files before knowing whether the user will accept consent, only blocking their execution until the response. This consumes bandwidth and, depending on how it's implemented, can still block the main thread even if the script "does nothing" until consent. The correct alternative is to not even request the script file until explicit consent exists, dynamically injecting the <script> tag only at that point.

How to audit the real cost of third parties on an existing site

The browser's performance panel (the Performance tab in Chrome DevTools) lets you record a page load and see, script by script, how much execution time each one consumes on the main thread, grouped by origin. This reveals, with real data rather than estimates, what share of main-thread blocking time comes from first-party code versus third-party, and within third-party, which one concentrates the biggest cost, information that rarely matches the intuition of "which one looks heaviest" based purely on file weight.

Frequently asked questions

Does removing Google Tag Manager automatically improve performance?

Not by itself: the container itself is lightweight. The cost lies in the tags it loads, so auditing and trimming those tags has far more impact than removing the manager that organizes them.

Does lazy-loading a script hurt its function (a remarketing pixel, for example)?

In most cases not noticeably: deferring the load a few seconds after the page's load event still registers the visit for remarketing purposes without affecting the real experience, since these tools' attribution window is usually days, not milliseconds.

How many third-party scripts is "too many"?

There's no fixed number; the cumulative main-thread execution cost matters more than the script count. A site with ten well-deferred, lightweight scripts can perform better than one with three poorly optimized scripts blocking the main thread at the critical moment.

Do users' ad blockers "fix" this problem for me?

It shouldn't be assumed as a strategy: a significant share of users don't run blockers, and the goal is for the site to perform well for everyone, not just for those already mitigating the problem on their own.

Does a CDN serving third-party scripts faster solve the INP problem?

It helps with the file's download time, but not with main-thread execution time, which is the bigger factor in INP. A script served instantly but that still runs a long task still blocks the main thread just the same.

Want to talk about technical SEO for your site?

Tell us about your project and we'll tell you how we can help, no strings attached.

Call 91 060 30 90