Skip to content
Coder71
Performance

Core Web Vitals for ecommerce: what to fix, in order

Three metrics, a handful of causes, and a fixed order of work. Most storefronts fail Core Web Vitals for the same four reasons, and third-party scripts are usually two of them.

Coder71 Team · 12 min read
core web

The short answer

Core Web Vitals are three metrics: LCP (largest content painted, target 2.5s), INP (interaction responsiveness, target 200ms) and CLS (layout stability, target 0.1). On storefronts, the usual causes are unoptimised hero images, third-party scripts, client-side rendering of prices, and images or banners inserted without reserved space.

Site speed conversations tend to produce a hundred-item audit and no change. This is the opposite: three metrics, the four causes that account for most storefront failures, and the order to work in.

The Core Web Vitals are Google's attempt to reduce "is it fast" to something measurable from real users' browsers. They are a ranking factor, though a modest one — the stronger argument is that they measure things that genuinely cost you sales, which is a better reason to care.

The three metrics, and what each really measures

Core Web Vitals thresholds and what each captures
MetricGoodNeeds workWhat it captures
LCP — Largest Contentful Paint≤ 2.5s2.5–4.0sHow long until the main thing on screen appears
INP — Interaction to Next Paint≤ 200ms200–500msHow quickly the page responds when someone taps or clicks
CLS — Cumulative Layout Shift≤ 0.10.1–0.25How much content moves around while loading

Two things about how these are assessed matter more than most guides admit.

They are measured at the 75th percentile of real visits, not on your laptop. A quarter of your visitors must be worse than the threshold before you fail it, which means a lab score from a fast connection tells you very little. The Chrome UX Report is the field data source, and it is what Search Console's Core Web Vitals report is built on.

They are assessed per URL group, so your homepage passing tells you nothing about your product pages. In ecommerce the templates that matter — category and product — are usually the worst performers and the least tested.

LCP: almost always the hero image

On a storefront the largest contentful element is nearly always a product photograph or a homepage banner. So LCP is a question about one image, and it decomposes into four parts you can measure separately.

  1. Time to first byte — How long the server takes to respond. If this is over about 600ms you have a back-end or caching problem, and nothing you do to the image will save you.
  2. Resource load delay — The gap between the HTML arriving and the browser starting to fetch the image. Caused by the image being discovered late — referenced from CSS, injected by JavaScript, or sitting behind a lazy-loading attribute it should not have.
  3. Resource load time — How long the image itself takes. This is format, dimensions and compression.
  4. Render delay — The image has arrived but has not painted, usually because the main thread is busy executing script or waiting on a blocking stylesheet or font.

The fixes, in the order that pays back fastest:

  • Never lazy-load the LCP image. It is the single most common self-inflicted LCP problem, and it happens because a blanket lazy-loading rule was applied to every image on the site. Above-the-fold images must load eagerly.
  • Preload it, or use a framework mechanism that does. It should start downloading with the HTML, not after the CSS has parsed.
  • Serve AVIF or WebP at the size actually displayed, with a correct srcset. Shipping a 2400px image into a 600px slot is common and costs seconds on mobile.
  • Reserve its space with width and height or an aspect ratio — this fixes CLS at the same time.
  • Self-host fonts and use font-display: swap, so text is not waiting on a network round trip to a third party.

A note specific to carousels: a rotating hero is an LCP problem by construction, because the browser must load the first slide before painting and the slider library must run before anything is positioned. If a homepage carousel is your LCP element, replacing it with a single static hero is usually worth more than every other optimisation combined.

INP: third-party scripts, almost every time

INP replaced First Input Delay in 2024, and it is a much harder metric — it measures the full time from an interaction to the next paint, across every interaction in the visit, rather than only the delay before the first one.

For storefronts this means add-to-cart, filter toggles, variant selectors and menu opens are all being measured. If tapping a size chip takes 400ms to visibly respond, that is your INP.

The causes, in order of how often they are responsible:

What breaks INP on a storefront
CauseHow it shows upFix
Third-party tagsAnalytics, heatmaps, chat, personalisation and A/B tools competing for the main threadAudit and remove; load the survivors after interaction where possible
Long tasks in app codeFiltering a large product list synchronously on the main threadBreak work into chunks and yield; move heavy filtering server-side
Over-hydrationA framework rehydrating the entire page when three components are interactiveServer components, islands, or simply less client JavaScript
Layout thrash on interactionA filter change forcing a full re-layout of a long gridVirtualise long lists; avoid reading layout in a loop
Unnecessary re-rendersState at the top of a tree re-rendering everything below itMove state down; memoise the expensive subtrees

The first row is where the work is. On a typical mid-sized store the tag manager alone carries a dozen scripts, several of which nobody can identify and at least one of which belongs to an agency that stopped working with the company two years ago.

Do the audit as an exercise in subtraction: remove everything, confirm the site works, then add back only what somebody can name an owner and a purpose for. It is faster and more honest than trying to optimise around them.

CLS: reserved space, and the two banners

Layout shift is the easiest of the three to fix and the most irritating to experience — a customer taps "add to bag" and a promotion banner pushes it out from under their thumb.

Almost all of it comes from five sources:

  1. Images without dimensions. Set width and height or an aspect ratio on every image, always. The browser then reserves the box before the file arrives.
  2. Banners and notification bars injected after load. Cookie notices, free-shipping bars, sale banners. Reserve the space in the initial HTML or overlay them rather than inserting into flow.
  3. Web fonts swapping. A fallback font with different metrics reflows the text. Use size-adjust and matched fallback metrics.
  4. Ads and embeds. Reserve a fixed slot sized for the largest expected creative.
  5. Content inserted above the viewport. Anything that appears above what the user is looking at pushes everything down. Insert below, or reserve.

Consent banners and promotion bars are worth calling out because they are usually owned by marketing rather than engineering, and they are frequently the entire CLS score. If a banner must be injected, give it a reserved height in the HTML from the start, even if it renders empty for some visitors.

The order to work in

Doing this in the wrong order is why speed projects stall. This sequence puts measurement first and the expensive work last.

  1. Get field data, per template — Search Console's Core Web Vitals report, grouped by URL pattern. Establish which of home, category, product and checkout actually fail, on mobile specifically. Do not start from a lab score.
  2. Audit third-party scripts — Almost always the cheapest large win, and it needs no engineering — it needs a decision. Remove everything unowned.
  3. Fix the LCP image on the worst template — Eager loading, preload, correct format and size, reserved dimensions. One template at a time, measured after each.
  4. Eliminate layout shift — Dimensions on images, reserved space for banners, matched font metrics. Mechanical work with an immediate, visible result.
  5. Reduce client-side JavaScript — Now, not first. This is the most expensive category of work and it is wasted effort if a tag manager is still loading eleven scripts alongside it.
  6. Improve server response and caching — If TTFB is the problem, this is where it gets solved — edge caching, better queries, fewer round trips before the first byte.
  7. Set a budget and enforce it — Agree the numbers, measure every release against them, and treat a regression as a bug. Without this, everything above decays within a year.

That last step is what separates a speed project from a fast site. Performance regresses by default — a new tag here, an unoptimised image there — and the only durable fix is making the number somebody's ongoing responsibility rather than a one-off engagement.

Lab and field data disagree, and both are right

A recurring confusion: Lighthouse says 94 and Search Console says the pages fail. Both are correct, because they measure different things.

Lab data is a single simulated load on a specific device and connection, in a controlled environment. It is repeatable, it is available before you ship, and it is excellent for comparing two versions of a page. It is not evidence about your customers.

Field data is what real visitors experienced, aggregated over 28 days at the 75th percentile. It includes the visitor on a five-year-old Android on a train, and the one who arrived with a cold cache. It is what Google assesses, and it lags by weeks.

The practical consequences:

  • Use lab data to iterate, because you get an answer in seconds and can compare two builds directly.
  • Use field data to decide what to work on, because it is the only source that tells you what is actually happening.
  • Expect a lag. A fix shipped today shows in field data over the following weeks as the 28-day window rolls forward. Do not conclude a fix failed after four days.
  • Do not chase a Lighthouse score. It is a weighted composite of lab metrics, and optimising the number rather than the experience produces work with no field effect.
  • Segment field data by device. Desktop usually passes while mobile fails. An aggregate figure hides which one you have.

INP deserves a specific warning here: it is the metric where lab and field diverge most, because it depends on what a real person does after the page loads. A lab tool cannot tap your filter chips. If INP is your failing metric, field data and real-user monitoring are the only useful instruments.

Images, in the detail that matters

Images are the largest payload on almost every storefront, and the decisions are more consequential than the compression settings people spend time on.

Format. AVIF gives the best compression and is now widely supported; WebP is the safe fallback; JPEG is the last resort. Serve them by content negotiation or a picture element so each browser gets the best it understands. The gain from JPEG to AVIF on product photography is large — usually much larger than any quality-slider tuning within one format.

Dimensions. The most common and most expensive mistake is serving one large image everywhere. A product grid thumbnail displayed at 300px does not need a 1600px file, and on a product listing that error is repeated twenty-four times on one page. Generate several sizes and declare them in srcset with an accurate sizes attribute.

That sizes attribute is where most implementations quietly fail. It tells the browser how wide the image will be before CSS has been applied, so a wrong value means the browser picks the wrong candidate — usually a much larger one. It is worth checking directly on each template rather than assuming.

Loading strategy.

How each image on a page should load
ImageLoadingPriority
The LCP imageEager, preloadedHigh
Other above-the-fold imagesEagerAuto
Below-the-fold imagesLazyAuto
Images in a closed accordion or tabLazyLow
Decorative background artCSS, lazy where possibleLow

Always set dimensions or an aspect ratio. This is both an LCP and a CLS fix and it costs nothing.

Serve from a CDN with on-the-fly resizing rather than committing a dozen variants of every product photograph. Every serious image service and every serious framework does this now, and hand-managing sizes at catalogue scale is not sustainable.

A performance budget you can actually enforce

Performance regresses by default. A new tag, a heavier hero, a library added for one component — each is individually defensible, and eighteen months later the site is slow again with no single decision to blame.

A budget is the only durable answer, and it works only if it is specific, enforced automatically, and owned.

  1. Set numbers per template, not per site — Product, category, home and checkout have different jobs and different budgets. A single site-wide number is either too loose for the homepage or too tight for checkout.
  2. Budget bytes as well as metrics — "JavaScript on a product page stays under N kilobytes compressed" is a rule a developer can act on. "LCP under 2.5s" is an outcome that depends on the network.
  3. Measure it in CI, on every pull request — A budget checked manually once a quarter is not a budget. Run Lighthouse CI or an equivalent in the pipeline and fail the build on a regression.
  4. Require a decision to exceed it — Not a block — a decision, made by a named person, recorded. Sometimes shipping the heavier thing is right. What must not happen is exceeding it silently.
  5. Put third-party scripts on the same budget — This is the political part, and the reason most budgets fail. If marketing can add a tag without it counting against anything, the budget only constrains engineering — which is where the weight usually is not.
  6. Review field data monthly — Fifteen minutes, per template, per device. Enough to catch a regression while it is still one change ago.

The fifth step is the one that decides whether any of this holds. In most organisations the tag manager is outside engineering's control, and every performance project that ignores that fact gets undone within a year. The workable version is a shared rule: any new tag needs an owner, a stated purpose, a review date, and a measured before-and-after. Most candidates do not survive that conversation, which is the point.

Platform-specific notes

On Shopify

  • Liquid renders server-side, so content is in the HTML by default — a significant head start.
  • The platform CDN is fast and not something you will casually improve on.
  • Your problems are almost certainly apps, theme scripts and unoptimised images — in that order.
  • Removing three apps often beats any amount of theme optimisation.

On a custom or headless build

  • You own rendering strategy, so client-side data fetching is a self-inflicted LCP problem.
  • Hydration cost is yours to manage — prefer server rendering and ship less JavaScript.
  • Caching and revalidation decide TTFB, and getting them wrong shows up here first.
  • You also inherited the same third-party tags. They did not get faster.

Key takeaways

  • LCP ≤ 2.5s, INP ≤ 200ms, CLS ≤ 0.1, at the 75th percentile of real mobile visits.
  • Assessment is per URL group. Your homepage passing says nothing about product pages.
  • LCP is nearly always the hero image, and lazy-loading it is the most common self-inflicted cause.
  • INP is nearly always third-party scripts. Audit by subtraction.
  • CLS is reserved space — images, banners and font metrics.
  • Do the cheap subtraction before the expensive engineering, and set a budget or it all decays.

If you want the field data read properly and a short list of what to actually do, that is where our performance work starts. Send us the URL.

Frequently asked questions

LCP at 2.5 seconds or under, INP at 200 milliseconds or under, and CLS at 0.1 or under — measured at the 75th percentile of real visits, mostly mobile. The percentile matters: a quarter of your visitors have to be worse than the threshold before you fail, so a fast result on your own laptop is not evidence. Assessment is also per URL group, so check category and product templates separately.

Circle Logo Icon gray small
Coder71 TeamEcommerce engineering and delivery team

The engineers, architects and strategists who build Coder71's client work — storefronts, custom software, mobile apps and the automation behind them.

10+ years building ecommerce systems · Delivery across the US · Canada · the UK · Australia · Europe and the Middle East · Builders of Fastmart · Footprint and Wallpaper71

Next step

Tell us the goal. We’ll scope the work.

New website, a rebuild, Shopify, a mobile app, custom software or SEO — one paragraph is enough. You get scope, risks and a timeline back within one business day, from the engineer who would build it.