# How to improve Core Web Vitals and pass the assessment

> How to improve Core Web Vitals: find the metric and template that fail in the field, fix the usual cause of each (LCP, INP, CLS) in the right order, and confirm the pass over 28 days.

Updated 2026-09-26 · Speed & Core Web Vitals · HTML version: https://getreport.app/guides/how-to-improve-core-web-vitals

To improve Core Web Vitals, first find which metric fails for real visitors and on which page template, then fix that metric's usual cause: a slow server or a late hero image for LCP, heavy JavaScript for INP, and images, ads or fonts without reserved space for CLS. Fix LCP first if several fail, change one thing at a time, and confirm the result in the field data, which takes about 28 days to catch up. Passing the assessment means all three metrics are good at the 75th percentile.

This guide is the working plan for site owners, marketers and developers who have seen "Core Web Vitals Assessment: Failed" in PageSpeed Insights or a Poor group in Search Console. It covers triage, the fixes with the biggest effect per metric, and how to verify. What each metric means is explained in [Core Web Vitals explained for site owners](https://getreport.app/guides/core-web-vitals-for-site-owners).

## Quick answer

- **Start from field data,** not the Lighthouse score. The assessment uses real Chrome visitors at the 75th percentile over 28 days.
- **Fix templates, not URLs.** Search Console groups similar pages; one product template fix covers thousands of URLs.
- **Mobile first.** It fails more often and is assessed separately from desktop.
- **LCP:** fast server response with page caching, a compressed hero image that is not lazy-loaded, fewer render-blocking files.
- **INP:** less JavaScript on the main thread, fewer third-party tags, lighter event handlers.
- **CLS:** width and height on images, reserved space for ads and embeds, fonts that do not reflow.
- **Verify twice:** the lab the same day, the field over the next four weeks.

## Step 1: read the assessment the way Google does

The Core Web Vitals assessment passes when LCP, INP and CLS are all "good" at the 75th percentile of real visits. The thresholds are Google's, published on web.dev:

| Metric | Good | Needs improvement | Poor |
| --- | --- | --- | --- |
| LCP | ≤ 2.5 s | 2.5–4.0 s | > 4.0 s |
| INP | ≤ 200 ms | 200–500 ms | > 500 ms |
| CLS | ≤ 0.1 | 0.1–0.25 | > 0.25 |

One metric outside "good" is enough to fail. A "Core Web Vitals Assessment: Failed" banner in PageSpeed Insights sits above the lab score, and it can appear on a page with a green lab score, because it comes from different data: 28 days of real visitors instead of one simulated load. The banner also tells you whether it is judging "this URL" or the whole origin; low-traffic pages are often judged on the origin's numbers.

Start with a test that shows both sources for the page:

> **Free tool:** [Core Web Vitals test: check LCP, INP and CLS](https://getreport.app/tools/core-web-vitals): Free Core Web Vitals test: LCP, INP and CLS from real Chrome users next to the lab values, rated against Google's thresholds, with what to fix. No sign-up.

The Core Web Vitals test reads LCP, INP and CLS from the Chrome UX Report for the URL and the origin, rates each against the thresholds, and runs a Lighthouse lab test beside it that names the element and the files responsible. INP only appears in the field data, because a lab run does not tap anything.

> **Check: Real-user Largest Contentful Paint.** LCP is when the biggest element on screen finishes loading. Google's threshold for "good" is 2.5 s at the 75th percentile of real Chrome users.
>
> 1. Find the LCP element in the Speed module and make it smaller, earlier or both.

> **Check: Real-user Interaction to Next Paint.** INP is how long the page takes to visibly react to taps and clicks, measured on real Chrome users over the last 28 days. Google's threshold for "good" is 200 ms.
>
> 1. Cut long JavaScript tasks and heavy third-party scripts; see the INP finding above.

> **Check: Real-user Cumulative Layout Shift.** CLS on real visitors' devices over the last 28 days. Google's threshold for "good" is 0.1; layout jumps hit hardest on slow phones with late-loading ads and fonts.
>
> 1. Reserve space for images, embeds and ads; see the CLS finding above.

For the whole site, open Search Console → Core Web Vitals, mobile report first. Each issue ("LCP issue: longer than 2.5 s (mobile)") lists groups of similar URLs with an example URL. Those groups are your work list.

## Step 2: triage a failed assessment

Match what you see to the likely cause before touching anything:

| What fails | What the lab shows | Likely cause | First fix |
| --- | --- | --- | --- |
| LCP | High TTFB (over 0.8 s) | Server: no page cache, slow host, redirects | Page caching, remove redirect hops, CDN |
| LCP | Fast TTFB, LCP element is an image | Hero image too large, lazy-loaded or found late | Resize, WebP/AVIF, `fetchpriority="high"`, no lazy-load |
| LCP | Fast TTFB, LCP element is text | Render-blocking CSS or a web font | Defer non-critical CSS and JS, `font-display: swap` |
| INP | High Total Blocking Time | Heavy JavaScript during load | Remove or delay third-party tags, split bundles |
| INP | Low Total Blocking Time | A slow interaction later in the visit | Find the slow tap in Chrome's Performance panel |
| CLS | Lab CLS high | Images or embeds without dimensions, fonts | `width`/`height`, `aspect-ratio`, font fallbacks |
| CLS | Lab CLS low | Shift after load: late ads, banners, infinite scroll | Reserve space for anything injected later |
| Nothing in the field | Lab only | Not enough Chrome traffic | Fix clear lab problems; wait for data |

If more than one metric fails, fix **LCP first**: it fails most often, it has the clearest fixes, and some of them (a faster server) help everything else. Then INP, then CLS, which is often the quickest.

## Step 3: fix LCP

Web.dev splits LCP into four parts, and each has its own fix. The lab result in the Core Web Vitals test shows the LCP element; the [LCP guide](https://getreport.app/guides/fix-largest-contentful-paint) explains how to read each part.

1. **Time to first byte.** The server's answer. Turn on full-page caching on a CMS, remove redirect chains, and put a CDN in front for distant visitors. See [TTFB: what a slow server looks like](https://getreport.app/guides/ttfb-what-a-slow-server-looks-like).
2. **Resource load delay.** The time before the browser starts downloading the LCP image. The image must be in the HTML, not added by JavaScript or a CSS background, and must not be lazy-loaded. Add `fetchpriority="high"` to it.
3. **Resource load duration.** The download itself. Serve the image at the size it is shown, in WebP or AVIF, with `srcset` for phones. See [image optimization](https://getreport.app/guides/image-optimization).
4. **Element render delay.** The time between the image arriving and being painted: render-blocking CSS and JavaScript in the `<head>`, or a web font the headline waits for. See [render-blocking resources](https://getreport.app/guides/render-blocking-resources).

```html
<!-- The hero image: in the HTML, eager, high priority, sized -->
<img src="https://getreport.app/img/hero-1200.webp"
     srcset="/img/hero-800.webp 800w, /img/hero-1200.webp 1200w, /img/hero-2000.webp 2000w"
     sizes="100vw" width="2000" height="900"
     fetchpriority="high" alt="Autumn collection on a wooden table">
```

> **Check: Largest Contentful Paint.** LCP is when the biggest thing on screen — usually the hero image or headline — finishes loading. Visitors judge "is this site slow?" on it, and Google uses it for ranking.
>
> 1. Find the LCP element (named in your report) and make it lighter, earlier or both — a compressed WebP/AVIF, sized to the screen, without lazy loading.
> 2. Preload it with <link rel="preload" as="image"> or add fetchpriority="high" on the <img>.
> 3. Cut what comes before it — render-blocking CSS/JS and slow server responses push LCP back.

> **Check: Offscreen images are lazy-loaded.** Images far below the fold compete for bandwidth with the ones visitors see first. Lazy loading defers them until they scroll into view.
>
> 1. Add loading="lazy" to images below the fold — but never to the hero/LCP image.
> 2. WordPress adds it by default since 5.5; check your theme or slider has not removed it.

## Step 4: fix INP

INP measures the delay between a tap, click or key press and the next frame the browser paints, and reports roughly the slowest interaction of the visit. It fails when JavaScript keeps the main thread busy at the moment the visitor interacts. The three parts, and what shortens each:

- **Input delay:** the browser is busy with other work when the tap arrives. Remove third-party tags nobody uses, delay the rest until after load or until interaction, and break long tasks into smaller ones.
- **Processing time:** the event handler itself does too much. Do the visible update first and defer the rest; in modern browsers `scheduler.yield()` (with a `setTimeout` fallback) gives the browser a chance to paint between steps.
- **Presentation delay:** rendering the result takes long, often because the page has a very large DOM or a change forces the whole layout to recalculate.

If the lab's Total Blocking Time is high, start with the scripts that run during load: the third-party finding lists them by domain with their blocking time. If TBT is low but field INP is poor, the slow interaction happens later: opening the menu, using filters, typing in search. Record it in Chrome's developer tools → Performance panel. [Fix Interaction to Next Paint](https://getreport.app/guides/fix-interaction-to-next-paint) and [long tasks and main-thread work](https://getreport.app/guides/long-tasks-and-main-thread-work) go through both cases.

> **Check: Total Blocking Time.** TBT adds up every moment the page was too busy running JavaScript to respond to a tap. It is the lab stand-in for INP and the heaviest-weighted Lighthouse metric.
>
> 1. Remove or defer JavaScript that is not needed for the first screen (defer, async, or load on interaction).
> 2. Split long tasks (> 50 ms) into smaller chunks; move heavy work to a web worker.
> 3. Audit third-party tags — chat widgets, tag managers and A/B tools are the usual culprits.

> **Check: Third-party code weight.** Tags, widgets and embeds from other companies run on your visitors' phones at your page's expense. Over 250 KB or 250 ms of blocking is a sign they dominate the load.
>
> 1. List what each third party gives you; remove the ones nobody looks at.
> 2. Load the rest after interaction or with a facade (a static thumbnail for YouTube, a click-to-load chat button).
> 3. Move tags into a tag manager that fires them late, not in <head>.

## Step 5: fix CLS

Layout shifts come from a short list of causes, and the fixes are mostly CSS:

1. **Images and video without dimensions.** Add `width` and `height` attributes, or `aspect-ratio` in CSS, so the browser reserves the space.
2. **Ads, embeds and iframes.** Give their containers a minimum height matching the most common size.
3. **Content injected above what the visitor is reading:** cookie banners, notices, "related products" rows. Overlay banners instead of pushing content, or insert below the viewport.
4. **Web fonts.** A fallback font with different metrics reflows the text when the web font arrives. Match the fallback's size with `size-adjust`, or preload the main font. See [web fonts without layout shift](https://getreport.app/guides/web-fonts-without-layout-shift).
5. **Animations** that change `top`, `height` or `margin`. Use `transform` instead.

Pages that can be restored from the browser's back/forward cache also avoid shifts and load instantly on back-navigation, so avoid what blocks it, such as `unload` event handlers. [Fix Cumulative Layout Shift](https://getreport.app/guides/fix-cumulative-layout-shift) has the CSS for each case.

> **Check: Cumulative Layout Shift.** CLS measures how much the page jumps around while loading — the button that moves just as someone taps it. It is one of Google's three Core Web Vitals.
>
> 1. Give every <img>, <video>, ad slot and embed explicit width and height (or aspect-ratio) so space is reserved before it loads.
> 2. Preload the main web font and use font-display optional, or swap with a size-adjusted fallback font, so text does not reflow.
> 3. Never insert banners or content above existing content after load.

> **Check: Every image declares width and height.** Without width and height the browser cannot reserve space, so the text jumps when each image arrives. That is the most common cause of a poor Cumulative Layout Shift score.
>
> 1. Add width and height attributes with the image's real proportions; CSS can still scale it.
> 2. In WordPress, recent versions add them automatically for images inserted through the editor; hard-coded theme images need them by hand.

## Step 6: verify, then wait

After each change, re-run the lab test on the same URL. The lab LCP and CLS should move the same day, and TBT should drop if you removed scripts. Keep the report link from before the change so you can compare.

The field data follows more slowly. The Chrome UX Report covers a rolling 28 days, so a fix shows in full after about four weeks. In Search Console, open the issue and click **Validate fix** once the change is live; Google then tracks the affected URLs over a 28-day window and reports whether the issue is resolved.

> **Free tool:** [Core Web Vitals report: 40 weeks of CrUX history](https://getreport.app/tools/cwv-history): Free Core Web Vitals report with up to 40 weeks of history: LCP, INP and CLS week by week from the Chrome UX Report, to spot the release that broke it.

The Core Web Vitals report tool plots up to 40 weekly data points from the CrUX History API for your origin or a popular page, against the thresholds. Look for the line crossing into the good band in the weeks after your release. If it does not move, the fix did not reach the visitors who count, often mobile visitors or a different template.

## Platform shortcuts

- **WordPress:** most of the work is one page cache, a lighter page builder setup, image settings and delaying JavaScript. [Core Web Vitals on WordPress](https://getreport.app/guides/wordpress-core-web-vitals) goes through the levers.
- **Shopify:** apps and images are the main levers; hosting is Shopify's. See [Shopify speed optimization](https://getreport.app/guides/shopify-speed-optimization).
- **Shops in general:** product galleries, variant pickers and filters have their own patterns; see [Core Web Vitals for e-commerce](https://getreport.app/guides/core-web-vitals-for-e-commerce-product-and-category-pages).
- **News and ad-funded sites:** reserved ad slots decide CLS; see [Core Web Vitals for news sites](https://getreport.app/guides/core-web-vitals-for-news-sites-ads-and-cls).

If the reason you are doing this is search, [Core Web Vitals and SEO](https://getreport.app/guides/core-web-vitals-seo) explains how much a pass is worth for rankings and what to expect after it.

## Common mistakes

- **Optimising the lab score.** A Lighthouse 100 does not pass the assessment; field data does.
- **Fixing the home page only.** Product, article and category templates carry most URLs in Search Console.
- **Changing ten things at once.** You will not know which change helped, or which broke the menu.
- **Lazy-loading the LCP image** in the name of speed.
- **Clicking Validate fix before the change is live** everywhere, including mobile templates and cached pages.
- **Expecting the field numbers to move the next day.** They cover 28 days.

## Questions people ask

### How do I improve Core Web Vitals?

Find which metric fails in the field data and on which template, then fix its usual cause. For LCP: page caching, a compressed hero image that is not lazy-loaded, and fewer render-blocking files. For INP: less JavaScript on the main thread and fewer third-party tags. For CLS: dimensions on images and reserved space for ads, embeds and banners. Re-test in the lab, then wait about 28 days for the field data.

### How do I pass the Core Web Vitals assessment?

All three metrics must be good at the 75th percentile of real visits over 28 days: LCP at 2.5 s or less, INP at 200 ms or less and CLS at 0.1 or less, judged separately for mobile and desktop. Fix the failing metric on the whole template, starting with LCP if several fail, then give the field data about four weeks to reflect the change.

### Why does PageSpeed Insights say the assessment failed when my score is green?

Because they measure different things. The assessment at the top uses 28 days of real Chrome visitors, often on slower phones and networks, while the performance score comes from one simulated lab visit. A page can load quickly in the lab and still be slow or jumpy for real visitors, for example because of late ads or slow interactions. Trust the assessment and use the lab to find causes.

### How do I fix Core Web Vitals issues in Search Console?

Open Core Web Vitals, start with the mobile report, and click an issue such as "LCP issue: longer than 2.5 s". It lists groups of similar URLs with an example. Test the example URL, fix the cause on the template the group shares, deploy it, then click Validate fix. Search Console tracks the group for 28 days and marks the issue resolved when the field data passes.

### Which fix improves Core Web Vitals fastest?

For most sites, making the LCP image load early: resize and compress it, remove lazy loading from it and add fetchpriority="high". Turning on page caching is equally quick on a CMS with a slow server. Adding width and height to images is the fastest CLS fix. INP usually takes longer, because it means removing or reworking JavaScript, often from third parties.
