4 min read

Core Web Vitals for WooCommerce: what actually moves the numbers

Most WooCommerce speed advice is a list of plugins. Here is the order the work actually goes in — queries, then the critical path, then images, and caching last.

Core Web Vitals for WooCommerce: what actually moves the numbers — article cover

Almost every WooCommerce store I am asked to look at has already been “optimised”. There is a caching plugin, an image plugin, a minification plugin, and the scores have barely moved. That is not bad luck. It is the wrong order of work.

Core Web Vitals measure three things a shopper actually feels: how long until the main content paints (LCP), how quickly the page responds to their first interaction (INP), and how much the layout jumps while it loads (CLS). Plugins mostly attack the symptoms of the first one. Here is the order that fixes causes.

1. Queries, before anything else

Open a category page on a slow store and count the database queries. It is not unusual to find several hundred. A “featured products” widget with no limit, a filter loading every attribute term, a currency plugin fetching a remote rate on each request, a related-products block doing a full taxonomy query per product.

None of that is visible in Lighthouse — it shows up as Time To First Byte, which then eats most of your LCP budget before a single byte of HTML is parsed. Install Query Monitor on staging, load your three heaviest templates, and fix what it shows you. A store that responds in 200ms has a completely different set of problems from one that responds in 1.4 seconds, and only one of them is worth optimising images for.

2. The critical path

Next: what blocks the first paint. Every render-blocking stylesheet and every synchronous script in the head delays the LCP element.

The most common single cause I see is fonts. A store loads three families from Google Fonts, sometimes injected by JavaScript on the load event, which means the headline cannot render until a third-party connection, a CSS parse and a font download have all completed. Self-host the faces you actually use as subset woff2, preload only the one that paints above the fold, and set font-display: swap. On a typical store this alone is worth half a second.

Then look at what WooCommerce itself loads everywhere. The cart fragments script, the block library CSS, gateway scripts, review scripts — many of them are only needed on two templates. Dequeue them where they are not.

3. Images, with dimensions

Product photography is usually the LCP element on a product page, which makes it the single most important byte on the site.

  • Serve modern formats. A WebP at quality 78 is routinely a third of the JPEG.
  • Set explicit width and height on every image. This is the CLS fix, and it is free.
  • Lazy-load everything except the LCP image, and give that one fetchpriority="high". Lazy-loading your hero is a self-inflicted wound that is unfortunately the default in a lot of themes.
  • Check the actual served size. A gallery thumbnail displayed at 120px should not be a 1200px file.

4. INP: the one people skip

INP replaced FID and it is much harder to fake. It measures how long the page takes to respond when someone taps “add to cart” — including every listener a plugin has attached.

The usual culprits are jQuery-driven cart fragments firing on every page, a chat widget booting on load, and analytics that runs a long task on interaction. Defer what can be deferred, load the chat widget on interaction rather than on load, and delete the plugins nobody has opened in a year.

5. Caching, last

Only now does a page cache help. Configure it — do not just install it:

  • Exclude cart, checkout and account pages. All of them.
  • Exclude wp-sitemap.xml, robots.txt and the REST API. I have seen a production cache serving a 404 sitemap to Googlebot for weeks, while every browser test showed a perfectly good file.
  • Test with a cache-busting query string when you debug, or you will spend an hour fixing a page that was already fixed.

What good looks like

On a hand-coded store with this order applied, mobile LCP under two seconds is normal rather than heroic, CLS sits near zero because dimensions are set everywhere, and INP stays comfortably under 200ms because there is very little JavaScript to be slow.

If your store is stuck in the forties and the plugins have not helped, it is almost always step one — and no amount of step five will rescue it.

Let's build something that earns trust — and converts.

Tell me what you are building. You get a straight answer on scope, timeline and cost — not a sales sequence.