Skip to main content

Third-Party Scripts

Third-party JavaScript is the single biggest cause of slow Webflow sites. Chat widgets, analytics, A/B testers, and marketing pixels all load code on every page — and most of it blocks the main thread.

Site Health's third-party dashboard at /sites/[siteId]/scripts aggregates the impact across your whole site so you can see exactly which domains to prune, defer, or replace.

What the dashboard shows

For every third-party domain seen across your latest scan, you get:

ColumnWhat it means
DomainThe origin serving the script (e.g. googletagmanager.com).
Total transfer sizeSum of compressed bytes shipped across every page.
Average blocking timeHow long this script kept the main thread busy, averaged per page.
Pages affectedHow many pages load this script.
Impact scoreComposite of blocking time × pages affected. Sort by this first.

Sort by Impact score to find the worst offenders fast.

Common Webflow culprits

If you've been building Webflow sites for a while, these names will be familiar.

ScriptTypical impactMitigation
Google Analytics / GTMMedium, loads on every pageSwap GA4 for a lightweight proxy or server-side GTM
IntercomHeavy (~200KB+), main-thread-blockingLazy-load after user interaction, or swap for a lighter widget
DriftSimilar to IntercomSame playbook
HubSpot formsHeavy when embedded globallyLoad per-page only where needed
YouTube embedsHuge — full player JS + iframeUse a facade (lite-youtube-embed)
Hotjar / FullstoryRecords every sessionSample traffic, skip on high-bounce pages
Custom embedsVariesAdd defer / async or move into per-page custom code

Deferring scripts in Webflow

Webflow's Project Settings → Custom Code editor lets you wrap scripts any way you want. Two patterns cover 90% of cases.

Defer (run after HTML parses, before DOMContentLoaded):

<script defer src="https://example.com/widget.js"></script>

Async (run whenever it finishes downloading — not ordered):

<script async src="https://example.com/pixel.js"></script>
Use defer for anything that touches the DOM

async scripts can execute before the DOM exists. defer scripts wait for parsing. If the script queries elements, defer is safer.

For anything user-triggered (chat widgets, video players), load it on interaction:

<script>
const load = () => {
const s = document.createElement('script');
s.src = 'https://widget.example.com/bundle.js';
s.async = true;
document.head.appendChild(s);
window.removeEventListener('scroll', load);
window.removeEventListener('click', load);
};
window.addEventListener('scroll', load, { once: true });
window.addEventListener('click', load, { once: true });
</script>

What's next

  • See the downstream impact in Core Web Vitals — especially TBT and INP.
  • After cutting scripts, trigger a new scan and watch page trends to confirm the win.