At a glance
JavaScript bytes downloaded but not executed during the page load, ranked per script. Lighthouse’s Coverage analysis identifies which lines of JS code never ran during the audit; the bytes occupied by those lines are “unused JS”. Brands routinely ship 50-70 percent of their JavaScript bundle on every page, with only 30-50 percent actually executing. The unused bytes still cost: download time, parse time, and memory. Removing them via code-splitting and tree-shaking is a structural performance improvement that compounds across every page-view.
Calculation
Calculated automatically from your Website Performance (PageSpeed + CrUX) data. See the At a glance summary above for what the metric tracks and the worked example below for a typical reading.Worked example
A UK-based BigCommerce fashion store homepage audit, mobile, Wednesday 15 May 26.
What the ranked list is telling us:
- 66 percent of all JavaScript shipped to the homepage is unused. That’s 624KB of bytes the user downloads, the browser parses, and the device’s memory holds, for code that never runs. For a typical mid-tier mobile device on slow 4G, those 624KB cost roughly 3 seconds of total processing (download + parse + execute-skipped) over the page lifecycle.
- GTM at 142KB unused (rank 1) is the most addressable single item. The GTM container ships every tag’s setup code regardless of whether the tag fires on the current page. Quarterly tag audit + page-scoped triggers typically reduces GTM bundle size by 40-60 percent. Time investment: 3-5 hours of GTM workspace cleanup.
- Klaviyo SDK at 114KB unused (rank 2) is partly structural (Klaviyo ships unified SDK with popup + behaviour + product feed components), partly addressable. Lazy-loading the popup component until the trigger fires saves 60-80KB; behaviour tracking still runs at page-load.
- Tidio chat at 110KB unused (rank 3) can be deferred entirely to post-load. The chat widget doesn’t need to load before first paint; users who don’t engage with chat (90 percent of sessions) never need the JS at all.
-
jQuery at 62KB unused (rank 4) is structural to Stencil themes. Short-term: defer (covered in
psi_render_blocking). Long-term: write new theme code in vanilla JS or modern alternatives; eventually remove jQuery dependency entirely. Multi-month project, not a quick win. - Stencil theme bundle at 54KB unused (rank 5) is the cleanest code-split target. Modern bundlers can produce per-template chunks: homepage-only JS, PDP-only JS, collection-only JS. Each template loads only its own bundle plus shared core. Code-splitting effort: 2-4 weeks for a developer familiar with Webpack/esbuild + theme architecture; ongoing benefit compounds.
- Optimizely (rank 6) ships the full A/B test variant fetcher even on pages without active tests. Configure to lazy-load only when an active test targets the current page. Saves 60-70KB on most pages.
- Cumulative impact estimation: removing or deferring the top 7 entries cuts JS bytes by 400-500KB and parse time by 800-1,500ms. Mobile p75 INP drops by 100-300ms; mobile p75 LCP drops by 200-500ms (less direct, but JS competes with image rendering for main-thread time).
- Read top 5 entries. Concentrate effort on the largest unused-byte items.
- Categorise per item: third-party (defer or remove), first-party theme (code-split), framework (long-term replacement).
- Verify in DevTools Coverage tab: confirms the unused-byte estimates and shows exactly which lines never ran.
- Ship in priority order: third-party deferral first (fastest wins), then code-splitting (medium effort, large benefit), then library replacements (longest, structural).
Sibling cards merchants should reference together
Reconciling against the vendor’s own dashboard
Where to look:- PageSpeed Insights, “Reduce unused JavaScript” opportunity in the Diagnostics section.
- Chrome DevTools → Coverage tab, line-level visibility of which JS lines executed; the most useful diagnostic tool.
- WebPack Bundle Analyzer (or equivalent for esbuild/Vite), shows what’s in your bundle and where the bytes go.
Cross-connector reconciliation: mostly internal cross-references with
psi_third_party_cost, crux_inp_p75, and psi_total_weight.
Quick rule for support tickets: if a merchant says “Lighthouse says I have 624KB of unused JS but my bundle is only 380KB total”, the most common cause is that some bundles have grown over multiple deploys without proper invalidation; the merchant is looking at a single bundle while Lighthouse sees the cumulative bytes across all loaded scripts. Sum across all script tags in DevTools Network for direct comparison.
Known limitations / merchant FAQs
Why does my bundle have 60 percent unused JS? Modern frameworks and libraries are designed to ship many features; any single page typically uses a small subset. Plus: legacy code accumulates, polyfills target browsers you no longer care about, dead features get bundled even when not used. The 60 percent figure is industry-typical, not a sign of unusual mismanagement. Code-splitting and tree-shaking are the standard fixes. Will removing unused JS break my site? If done correctly, no. Modern bundlers track imports/exports and tree-shake automatically; the unused code never makes it into the bundle. Manual code removal (deleting dead files) requires more care; verify with your test suite plus a 14-day staged deploy. Can I just defer all my JS? Technically yes, but conversion-critical scripts must run for the page to function. Deferring is for non-critical: chat widgets, session recording, A/B testing, analytics tags. Don’t defer: payment SDKs (must be ready when checkout fires), authentication scripts, scripts that handle initial-render content. Why does Klaviyo SDK show as 64 percent unused? Klaviyo ships a unified SDK with popup + behaviour tracking + product feeds + signup forms + opt-in management. Most pages use only behaviour tracking; the rest is dead weight per page-load. Lazy-loading the popup component is Klaviyo’s recommended optimisation; the SDK is configurable. Should I switch from jQuery to vanilla JS? Long-term, yes. Modern browsers support all jQuery’s core features natively (querySelector, fetch, addEventListener); jQuery added value 10 years ago when browser inconsistencies were common. Migration is gradual: write new code in vanilla JS, leave existing jQuery code in place, retire jQuery when the codebase is mostly migrated. Saves 84KB of bundle size when complete.
Can Vortex IQ refactor my JS for me?
Read-only by design. Vortex IQ identifies unused JS; the merchant’s developer or agency does the bundle work.
My BC site uses Catalyst. Does this still apply?
Yes, in different proportions. Catalyst sites use Next.js with built-in code-splitting; first-party JS unused bytes are typically 10-20 percent (vs 30-40 percent for Stencil). Third-party JS unused proportions are similar. The optimisation effort shifts: Catalyst sites focus on third-party deferral; Stencil sites focus on first-party code-splitting plus third-party deferral.
Is server-side rendering the answer?
Helps but isn’t a complete fix. SSR delivers fully-rendered HTML to the user, removing the need for JS to render initial content. Unused JS still ships and parses; it just doesn’t block the first paint. SSR’s main benefit is LCP improvement; unused-JS reduction requires the same code-splitting work on top.
Should I optimise unused JS or unused CSS first?
JS first, almost always. JS has higher bytes-per-page on most ecommerce sites (200-1000KB vs 50-200KB for CSS), and JS execution cost is more variable across devices than CSS. Unused JS impacts INP heavily; unused CSS mainly affects parse time which is smaller.