Magento

Core Web Vitals for Magento stores: where the time actually goes

What LCP, INP and CLS measure, the usual reasons a Magento store fails them, and the fixes to make first, starting with the full-page cache.

On most Magento stores, poor Core Web Vitals come from three places: pages that miss the full-page cache and so start slowly, a large hero image the browser discovers late, and the amount of JavaScript that the Luma front end and third-party tags run on the main thread. Fix them roughly in that order. Caching and images are the cheapest wins. JavaScript is the hardest, and it is where a move to Hyvä earns its place.

The three metrics in plain terms

Largest Contentful Paint (LCP)

LCP is the time from the start of the page load until the largest piece of content in the visible area has rendered. On a store that is usually the hero banner, the main product image or a large heading. Google’s threshold for good is 2.5 seconds or less.

Interaction to Next Paint (INP)

INP measures how quickly the page responds visually when someone taps, clicks or types. It looks at interactions across the whole visit and reports one of the slowest. Good is 200 milliseconds or less.

INP replaced First Input Delay as a Core Web Vital in March 2024. The older metric only measured the delay before the first interaction was handled, so INP is much harder for a JavaScript-heavy page to pass.

Cumulative Layout Shift (CLS)

CLS measures how much visible content moves unexpectedly while the page is in use. It is a score, not a time. Good is 0.1 or less.

Google assesses each metric at the 75th percentile of visits, separately for mobile and desktop. A fast result on your own laptop tells you little.

Field data and lab data

Field data comes from real visitors. The Chrome User Experience Report (CrUX) collects it from Chrome users and publishes it as a rolling 28 day figure. You see it in PageSpeed Insights and in the Core Web Vitals report in Search Console, which groups similar URLs together. This is the data Google’s assessment is based on. It is slow to react: a fix takes weeks to show in full.

Lab data comes from a tool such as Lighthouse loading the page once on a simulated device and connection. It is the right tool for debugging. It cannot measure INP, because nobody interacts with the page during the test, so it reports Total Blocking Time as a stand-in.

Use field data to decide whether you have a problem and whether it is solved. Use lab data to find the cause. Stores with low traffic may have no CrUX data for individual pages, in which case you need to collect your own.

Where the time goes on a Magento store

Slow server response

Time to first byte is not a Core Web Vital, but every millisecond of it counts towards LCP. A page served from Varnish arrives quickly. A page that misses the cache makes Magento start up, build the layout, render every block and query the database before the browser receives anything.

The common reasons pages miss the cache:

  • A block marked cacheable="false" in layout XML. One such block makes every page that uses that layout uncacheable, and extensions are the usual source.
  • The cache being flushed in full on every deployment or after routine catalogue and stock updates, so visitors keep arriving at cold pages.
  • Tracking parameters in URLs that the cache treats as separate pages.
  • Heavy blocks on the pages that do have to be generated: large navigation menus, layered navigation on big categories and product lists that run many queries.

Cart, checkout and account pages are never served from the full-page cache, so there the raw speed of the application and hosting is what counts.

Hero images

Once the HTML arrives, LCP usually depends on one image. It is slow when the file is far larger than the space it fills, when it is served in an older format, when it is lazy-loaded even though it sits at the top of the page, or when it is a CSS background or is inserted by a slider script. In the last two cases the browser cannot find the image until the stylesheet or script has loaded.

Luma’s JavaScript weight

Magento’s default Luma front end loads its JavaScript through RequireJS as a large number of separate modules, alongside Knockout, jQuery and jQuery UI. The browser has to download, parse and run a great deal of code before the page is ready to respond. On a mid-range phone the main thread stays busy, and taps wait their turn. That is an INP problem, and it can delay LCP too.

Third-party tags

Tag managers, chat widgets, review platforms, personalisation, testing tools, heatmaps and consent banners all compete for the same main thread. They are often added through a tag manager without a developer seeing them, and they accumulate.

Layout shift

The usual causes of CLS on a Magento store:

  • Promotional bars, cookie notices and banners that load late and push the page down.
  • Images without width and height attributes, so the browser cannot reserve their space.
  • Web fonts that swap in after the text has been drawn in a fallback font of a different size.
  • Sliders, review widgets and customer-specific content that arrive after the first render and change the height of their container.

Fixes, in the order we would make them

The order is impact for the effort involved. The last item is the largest piece of work.

  1. Full-page cache hit rate and Varnish. Adobe recommends Varnish in production over the built-in cache. Confirm from the response headers that category, product and content pages are actually being cached. Find and fix uncacheable blocks, avoid full cache flushes and warm the cache after a deployment.
  2. Image sizing and modern formats. Serve images at the dimensions they are displayed, with responsive sizes for mobile, in WebP or AVIF through an extension, the CDN or an image service.
  3. Prioritise the LCP image. Put it in the HTML as a normal image, do not lazy-load it, and preload it or mark it as high priority. Lazy-load the images further down the page.
  4. Remove unused extensions. Each one can add JavaScript, CSS, layout and server-side work to every page. Switching a feature off in the configuration is not the same as removing the module.
  5. Defer third-party scripts. Audit the tag manager, delete what is no longer used, and load the rest after the page is usable.
  6. Reserve space. Add image dimensions, give late-loading banners a fixed height and preload the fonts used at the top of the page.
  7. Hyvä. When Luma’s own JavaScript is the bottleneck, tuning has a ceiling. Bundling and minification change how the code is delivered, but the browser still has to run it. Hyvä replaces RequireJS, Knockout and jQuery with a much lighter stack. It is a front-end rebuild, which is why it comes last, but it is often the change that finally fixes INP.

Symptom, likely cause, first fix

Symptom Likely cause First fix
Slow server response on category and product pages Pages missing the full-page cache Check the cache headers and look for an uncacheable block
Fast server response but slow LCP Hero image too large, lazy-loaded or set as a CSS background Resize it, serve it as a normal image and prioritise it
LCP good in Lighthouse, poor in field data Real visitors arriving at uncached pages or on slower devices Measure the cache hit rate and split field data by page type
Poor INP across the whole site Luma JavaScript and third-party tags Audit the tags, then assess Hyvä
Poor INP on one page type A specific widget or extension Profile the interaction in the browser’s performance tools
Page jumps down shortly after loading A late promotional bar, cookie notice or banner Reserve the space or overlay it
Product lists shift as images load Images without dimensions Add width and height attributes
Text moves when fonts load Web font swapping with a mismatched fallback Preload the font and choose a closer fallback

Measure properly, and do not chase a Lighthouse score

The Lighthouse performance score is a weighted blend of lab metrics from one simulated page load. It varies between runs, does not include INP, and does not know whether your real visitors hit the cache. A store can score well and still fail in the field.

A method that works:

  • Take a baseline from field data for each page type: home, category, product, cart and checkout.
  • Collect your own real user data, for example with Google’s open source web-vitals library reporting into your analytics. It shows the effect of a change in days, not weeks.
  • Use lab tests to diagnose, on a throttled mobile profile, and test both a cached and an uncached page.
  • Change one thing at a time, so you know what worked.
  • Check on a real mid-range phone.

The target is field data that passes at the 75th percentile on mobile for the page types that earn revenue. The score is a by-product.

What to do next

Open the Core Web Vitals report in Search Console and note which metric fails and on which group of pages. Then load a category page and a product page with the browser’s network tools open, and check the response headers to see whether they came from the cache. Those two checks tell you which section above applies to you.

If the cause is caching or images, the work is contained and can start straight away. If it is JavaScript, list your third-party tags and decide which you still need before considering anything larger. Our Magento performance optimisation page sets out how we approach the same diagnosis, measured before and after.

Keep reading

More from Insights