On many websites, the code written by the developers is only part of what the browser executes. The rest comes from external vendors: analytics platforms, advertising pixels, heatmap tools, chat widgets, review systems, consent managers. Each seems harmless on its own, but together they can occupy the main thread for seconds, open connections to dozens of domains and worsen every Core Web Vital.
The problem is organizational too: these scripts are often added by different departments, through a tag manager, without anyone assessing their overall cost.
Why they weigh so much
An external script costs in several ways:
- connections: every new domain requires DNS resolution, connection and TLS negotiation before the first byte;
- download: many scripts are large and in turn load other scripts, in chains you cannot see from the page's code;
- execution: the JavaScript must be parsed, compiled and run on the main thread, creating long tasks that worsen INP;
- layout effects: banners, widgets and ads that appear after load push content around and increase CLS;
- unpredictability: the vendor can change the script at any time, and a page that is fast today can become slow tomorrow without anything on your side changing.
Finally there is the dependency risk: a script loaded synchronously in the head that does not respond can block the page from displaying until the request times out.
Taking inventory
The first step is knowing what is really there. A practical method:
- open the DevTools Network panel, load the page and sort by domain: anything that does not belong to the site is third party;
- in the Performance panel, record a load and look at the summary by entity, which attributes execution time to individual vendors;
- in Lighthouse, the third-party audit lists vendors with transferred size and main-thread blocking time;
- export the tag list from the tag manager and compare it with what you see on the network: forgotten tags from finished campaigns often turn up.
For each entry note what it is for, who asked for it and who actually uses the data it collects. It is common to discover two analytics tools measuring the same thing, or a pixel from an advertising platform no longer in use.
Measuring impact by subtraction
The most convincing way to show the cost of a script is to remove it and measure. In DevTools, in the Network panel, you can block a domain or a single URL with the request blocking command, then reload the page and compare timings. Synthetic testing tools such as WebPageTest let you do the same repeatably, running several tests with and without the listed domains.
Presenting a comparison like "with the widget LCP is X, without it is Y" makes the discussion concrete and moves the decision from personal taste to numbers.
Loading techniques
Once you have decided what to keep, how you load it matters.
| Situation | Technique |
|---|---|
| Script not needed for the first render | async or defer, never synchronous in the head |
| Widget used only by some users | load on first click or interaction |
| Script useful only after load | inject after the load event or during idle time |
| Critical external domain | preconnect to set up the connection early |
| Stable, versioned library | host it on your own domain |
Hosting a copy on your own domain removes a connection and puts the script under your own caching rules, but it only makes sense for files that do not need to update themselves: many analytics and advertising scripts must instead be loaded from the vendor's origin.
There are also libraries, such as Partytown, that move the execution of some third-party scripts into a web worker to free the main thread. They work well with certain kinds of scripts and less well with others, so they must be tested case by case.
The role of consent
Where user consent is required, tracking scripts must not start before the choice is made. Besides being correct, this is also a performance benefit: the first load is lighter. Watch the banner itself, though: it needs reserved space or should appear as an overlay, otherwise it becomes a source of CLS, and its script must not block rendering.
A rule for the future
A one-off audit is not enough, because new tags keep arriving. A small procedure works better: every new third party needs a written justification, an owner and a measurement of its impact; every quarter the list is reviewed and whatever is not needed is removed. In my work, this periodic review almost always ends with something being removed.
In short
- Third parties cost in connections, download, execution and layout stability.
- Take inventory with DevTools, Lighthouse and the tag manager's list.
- Prove the cost by blocking the script and measuring the difference.
- Load asynchronously, defer what is not needed right away and consider self-hosting.
- Set up an approval procedure and a periodic review of tags.