The pattern behind the audits
After twenty or so Core Web Vitals engagements on small and medium business sites, WordPress and Next.js in roughly equal measure, the fix lists started to look the same. Every site was different in detail; the things that moved the numbers were not. Ten fixes, applied where they were relevant, delivered the large majority of the improvement across the set. The long tail of Lighthouse suggestions delivered the rest, at much higher cost per millisecond.
This is that list, with how often each applied and roughly what it moved when it did. The figures are approximate and from throttled-mobile lab measurements confirmed by field data; treat them as the shape of the return, not a promise.
1. Make the LCP image discoverable and prioritised
Applied on: nearly every site with a failing LCP. Moved: LCP by 0.8 to 2.0 seconds.
The hero was a CSS background, or lazy-loaded, or rendered by JavaScript, or all three. Rendering it as a real <img> in the initial HTML with fetchpriority="high" and no loading="lazy" was the single largest LCP change on most sites. Resource load delay in the trace went from over a second to under a hundred milliseconds.
2. Serve phone-sized images
Applied on: most sites. Moved: LCP by 0.3 to 1.0 seconds; total page weight by half or more.
Honest sizes attributes, a srcset with real widths, WebP or AVIF, and a cap on upload dimensions. On sites where the LCP image was already discoverable, this was what remained.
3. Get HTML cached at the edge
Applied on: most WordPress sites; a few Next.js sites with accidentally dynamic routes. Moved: TTFB by 0.3 to 1.5 seconds, and therefore everything after it.
Full-page caching that actually hit: cookie and query-string exclusions fixed, purge rules made targeted, a CDN caching HTML rather than only assets. On Next.js, finding the Date.now() or cookie read that made a marketing page dynamic and moving it behind Suspense.
4. Defer or remove third-party scripts
Applied on: almost every site. Moved: INP by 50 to 200 milliseconds; LCP by 0.2 to 0.5 seconds.
Tag manager after load, chat widget on click, session replay sampled or removed, social embeds replaced with server-rendered content, the heat-mapping tool from an old experiment deleted. On several sites this was the entire INP fix.
5. Fix the consent banner
Applied on: most sites with one. Moved: CLS by 0.1 to 0.25; INP on the Accept tap by 100 to 400 milliseconds.
Overlay instead of push, markup in the initial HTML, vendor script deferred, and the Accept handler storing consent and painting before loading tags in sequence. One fix, two metrics.
6. Reserve space for embeds
Applied on: about half of sites. Moved: CLS by 0.05 to 0.2.
Review widgets, maps and video with sized containers, and where possible replaced by server-rendered equivalents. On service-business sites the review carousel near the top of the page was the CLS problem by itself.
7. Self-host fonts with metric overrides
Applied on: about half of sites. Moved: CLS by 0.02 to 0.1; LCP by 0.1 to 0.3 seconds.
Fonts from the site's own origin, preloaded, with size-adjust and related descriptors on the fallback so the swap does not reflow. Framework font loaders do this automatically, which is why it applied mostly to WordPress and older sites.
8. Reduce shipped JavaScript
Applied on: WordPress sites with plugin sprawl; Next.js sites with client-heavy trees. Moved: INP by 50 to 150 milliseconds; LCP by 0.1 to 0.4 seconds.
Dequeue per page and remove unused plugins on WordPress; push 'use client' to the leaves and split heavy islands on Next.js. Slower to do than the fixes above and worth it where INP was still failing after third parties were handled.
9. Persistent object cache and database hygiene
Applied on: WordPress sites, especially stores. Moved: TTFB on uncached pages by 0.3 to 1.0 seconds; admin speed dramatically.
Redis or Memcached, autoloaded options trimmed, transients cleaned, server cron replacing page-load cron. The fix for checkout and account pages that no page cache can help.
10. Break up long tasks around interactions
Applied on: a minority of sites, mostly with search, filters or configurators. Moved: INP by 100 to 300 milliseconds on the specific interaction.
Immediate visual feedback, then the heavy work in a transition or after a yield; debounced inputs; virtualised lists. The most engineering-heavy item, and the one where field attribution was essential to know which interaction to target.
What did not make the list
Minification (already done by every build and most hosts). Removing unused CSS (real but small). Preconnect hints beyond one or two (diminishing). Server-side compression (a flag, already on). "Eliminate render-blocking resources" as a general activity, as opposed to the specific font and third-party fixes above. The Lighthouse score itself, which we stopped reporting.
The order
If you are starting an audit and have a day: 1, 2, 4, 5, in that order, measured after each. They apply to almost every site and together they typically move a Poor site to Needs improvement or Good on LCP and CLS and take a large bite out of INP. Then 3 or 9 depending on the stack, then 6 and 7, then 8 and 10 if INP is still failing and field attribution has named the interaction.
The number in the title
Across the set, sites that completed the relevant items from this list saw their mobile Core Web Vitals field data move from mostly Poor or Needs improvement to mostly Good, and the sites that tracked enquiries alongside saw conversion from mobile search rise by a material fraction, in the region of a quarter to a third, once the data settled. That figure is the one that gets the work approved, and it came from the ten fixes above far more than from anything in the long tail.
This list is the backbone of every Core Web Vitals engagement we run now: field data first to see which apply, traces to confirm, and then the ten in order until the numbers are where they need to be.