Performance May 19, 2026 5 min read Updated July 29, 2026

Audit every third-party script on your Webflow site in 30 minutes

Most sites carry scripts nobody can account for. A repeatable inventory that turns 'we probably need that' into a decision, with the cost of each one measured.

On this page

Why this is worth half an hour

Third-party scripts accumulate. A campaign adds a pixel, a trial adds a heatmap, an experiment adds a testing tool, marketing switches analytics vendors and the old snippet stays. Nobody removes anything, because nobody is certain what's safe to remove.

The result is a site carrying six to twelve third-party scripts, of which perhaps four earn their place. They are usually the largest contributor to poor INP, because third-party JavaScript competes with your page for the main thread.

The blocker is rarely technical. It's that no one has an inventory, so every conversation ends at "better leave it, someone might be using it". This gets you the inventory.

Step 1: list what loads (5 minutes)

DevTools → Network → hard reload → sort by Domain. Or run this in the console:

const own = location.hostname;
const third = performance.getEntriesByType('resource')
  .filter(r => {
    try { return new URL(r.name).hostname !== own; } catch { return false; }
  })
  .map(r => ({
    host: new URL(r.name).hostname,
    kb: Math.round(r.transferSize / 1024),
    ms: Math.round(r.duration),
    type: r.initiatorType,
  }))
  .sort((a, b) => b.kb - a.kb);

console.table(third);
console.log('total third-party KB:', third.reduce((s, r) => s + r.kb, 0));

That's your inventory with sizes. Run it on the homepage and on one deep page — some scripts load only on certain templates.

Step 2: find where each is injected (10 minutes)

For each domain, find who added it. Four places to look on a Webflow site:

  1. Site Settings → Custom Code — head and footer, applies site-wide
  2. Page Settings → Custom Code — per page
  3. Embed elements in the Designer — easy to miss, so search your pages
  4. Google Tag Manager — if GTM is present, it's probably injecting several of the entries above

GTM deserves specific attention. In the Network panel it's one modest request; in reality it's a container that can inject a dozen tags. Open the container, list every tag, and note which fire on all pages.

Write down, for each script: what it is, who asked for it, which team looks at its data, and when it was added. The last column is the useful one — anything over two years old with no identifiable owner is almost certainly dead weight.

Step 3: measure the main-thread cost (10 minutes)

Size is the wrong metric for INP; execution time is what matters. A 40KB script that runs for 300ms is worse than a 200KB one that runs for 20ms.

DevTools → Performance → record a reload → open the Bottom-Up tab and group by URL. That gives you scripting time per domain.

Or, quicker, use long task attribution:

new PerformanceObserver(list => {
  list.getEntries().forEach(task => {
    if (task.duration > 50) {
      console.warn(`Long task: ${Math.round(task.duration)}ms`,
        task.attribution.map(a => a.containerSrc || a.name));
    }
  });
}).observe({ type: 'longtask', buffered: true });

Anything over 50ms blocks interaction. A cluster of long tasks attributed to one third-party domain is your headline finding.

Step 4: decide, one script at a time (5 minutes)

For each entry, exactly one of four outcomes. Don't allow a fifth.

Every third-party script gets exactly one of four outcomes: remove, defer, lazy-load or keep

Remove. No owner, no consumer, or duplicate of something else. Most audits find at least one analytics tool nobody has opened in a year.

Defer. Needed, but not before first paint. Add defer, or load on idle.

Lazy-load. Only relevant once a visitor reaches a section — maps, review widgets, embeds. Load on scroll.

Keep as is. Genuinely needed immediately. Consent management is the honest example: it has to run before the things it gates.

Write the outcome next to each script. A decision recorded is what stops this list regrowing next quarter.

The removal conversation

The reason dead scripts survive is social, not technical, so it's worth having the argument ready.

"Marketing might need it." Ask when they last opened it. If nobody can name a report, it isn't in use. Removing it is reversible in five minutes; the cost of keeping it is paid by every visitor on every page load.

"It's only 30KB." Size isn't the cost. Show the long-task measurement — 30KB that executes for 200ms on a mid-range phone is a real delay on every interaction.

"We'll need it again next quarter." Then add it next quarter. Snippets are one paste.

A useful framing: every script is a small ongoing tax on every visitor, paid in exchange for something. If nobody can name the something, stop paying.

After the audit

Re-measure. Run the step 1 snippet again and compare totals. A typical first audit removes 30–50% of third-party bytes, which is worth reporting to whoever approved the work.

Write it down. A short page listing each script, its owner, and why it's there. This is what makes the next audit ten minutes instead of thirty.

Put a gate on additions. Not bureaucracy — one question: what does this do, who reads its output, and does it need to run before the page paints? Scripts that can't answer all three go through the deferral pattern by default.

Re-run quarterly. Fifteen minutes. Sites regrow scripts the way drawers regrow cables.

The one that surprises people

Check whether your consent banner is loading tags before consent is given.

It's common to find analytics firing on page load with the banner appearing afterwards. That's both a compliance problem and a performance one — you're paying the main-thread cost of scripts that shouldn't have run yet. Fixing it improves both at once, which makes it the easiest thing on this list to get approved.

Share

Our Products

We don’t just build apps; we create solutions that transform how you use Webflow. Whether you’re looking to streamline workflows, add advanced functionality, or scale your business, we’ve got you covered.

All apps