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:
| Column | What it means |
|---|---|
| Domain | The origin serving the script (e.g. googletagmanager.com). |
| Total transfer size | Sum of compressed bytes shipped across every page. |
| Average blocking time | How long this script kept the main thread busy, averaged per page. |
| Pages affected | How many pages load this script. |
| Impact score | Composite 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.
| Script | Typical impact | Mitigation |
|---|---|---|
| Google Analytics / GTM | Medium, loads on every page | Swap GA4 for a lightweight proxy or server-side GTM |
| Intercom | Heavy (~200KB+), main-thread-blocking | Lazy-load after user interaction, or swap for a lighter widget |
| Drift | Similar to Intercom | Same playbook |
| HubSpot forms | Heavy when embedded globally | Load per-page only where needed |
| YouTube embeds | Huge — full player JS + iframe | Use a facade (lite-youtube-embed) |
| Hotjar / Fullstory | Records every session | Sample traffic, skip on high-bounce pages |
| Custom embeds | Varies | Add 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>
defer for anything that touches the DOMasync 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.