Every SEO blog has a Core Web Vitals article. The confusing part in practice: a page can score badly in PageSpeed Insights and still be fast for the people who actually visit it. In Lumina's PageSpeed study of 47 DACH news sites, measured on 2026-09-17, all 47 had a good LCP in the field data (median 1.3 s), while the median mobile lab score was 52. Same sites, same day, two very different answers.
Core Web Vitals are three metrics Google uses to score how a page feels to a real user. Largest Contentful Paint (LCP) measures when the main content appears. Interaction to Next Paint (INP) measures how fast the page reacts to clicks and taps. Cumulative Layout Shift (CLS) measures how stable the layout stays while the page loads. The scores come from Chrome's field data, the 28-day rolling averages of real users hitting your site, not from a lab simulation on a single machine.
What Core Web Vitals Actually Measure
Largest Contentful Paint (LCP): how fast the main content appears
LCP is the time from when the page starts loading to when the largest visible element in the viewport finishes rendering. That element is usually the hero image, the main heading, or a large block of body text. It's the frame where the user first feels "OK, the page is here."
Good LCP: 2.5 seconds or less at the 75th percentile. Poor: more than 4 seconds. Most sites that fail LCP are failing because of one of four things: an unoptimized hero image (too large, wrong format, no fetchpriority="high"), render-blocking third-party scripts, slow server response time (TTFB), or a web font that blocks text rendering.
Interaction to Next Paint (INP): how fast the page reacts
INP measures the latency of every user interaction on the page: clicks, taps, key presses. It captures the full round-trip from the input event to the next paint that visibly acknowledges it, including event handler time, DOM updates, style and layout recalculation, paint. The value reported is the slowest interaction on the page. On pages with many interactions, Google ignores the single highest one for every 50, so one outlier in a long session doesn't decide the score.
Good INP: 200 milliseconds or less. Poor: more than 500 ms. INP replaced First Input Delay (FID) on March 12, 2024. FID measured only the first interaction's input delay. The sites that fail INP are running heavy JavaScript on the main thread, things like analytics scripts that block for 300 ms on click, React re-renders that iterate thousands of virtual DOM nodes, event handlers wrapped in a setTimeout(0) queue that doesn't drain fast enough.
Cumulative Layout Shift (CLS): how stable the layout stays
CLS tracks unexpected layout shifts, which happen when elements on the page jump position as new content loads. Every shift contributes a score based on how much of the viewport moved and how far. Google sums the shifts within session windows (shifts less than 1 second apart, each window capped at 5 seconds) and takes the largest window as your CLS. Clicks and taps within 500 ms of a shift don't count (so user-triggered animation is fine).
Good CLS: 0.1 or less. Poor: more than 0.25. The usual causes: images without explicit width and height attributes (the browser reserves no space until the image loads, then pushes content down), ads or embeds that inject dynamically, web fonts that swap mid-paint and resize the text block, and hero sections with a late-loading video that pushes the article below it.
The 2026 Thresholds
Google publishes three thresholds per metric: Good, Needs Improvement, Poor. You qualify for "Good" on a metric only when the 75th percentile of your real users hits that bucket. That means 25% of your traffic can still be in the Poor bucket and you still "pass".
| Metric | Good (≤ 75% at) | Needs Improvement | Poor (>) |
|---|---|---|---|
| LCP (Largest Contentful Paint) | 2.5 s | 2.5 s – 4.0 s | 4.0 s |
| INP (Interaction to Next Paint) | 200 ms | 200 ms – 500 ms | 500 ms |
| CLS (Cumulative Layout Shift) | 0.1 | 0.1 – 0.25 | 0.25 |
A page is "Good on Core Web Vitals" only when all three metrics are Good at the 75th percentile. One Poor metric drops you out. Across the web, LCP is the metric sites miss most often. In the CrUX release for August 2026, 68.1% of origins had good LCP, against 81.5% for CLS and 85.3% for INP. INP is slipping, though, and the Chrome team calls its continued regression a cause for concern.
Field Data vs Lab Data
The single biggest source of CWV confusion: two tools can give you wildly different answers for the same page. Both are right. They're measuring different things.
Field data is the 28-day rolling aggregate of real Chrome users hitting your page. Google collects it via the Chrome User Experience Report (CrUX), which collects anonymized metrics from users who opted in. Field data is what Google actually uses for ranking. It's surfaced in PageSpeed Insights at the top of the report, in Search Console's Core Web Vitals report, and in the raw CrUX BigQuery dataset for site-wide analysis.
Lab data is a single simulated run on a throttled mobile profile. Lighthouse inside Chrome DevTools or the PageSpeed Insights lab run both do this. The profile: 1.6 Mbps down, 750 Kbps up, 150 ms round-trip time, 4× CPU slowdown. It's an approximation of a mid-range mobile device on a 4G connection. Lab data is reproducible: same inputs, same result, which makes it the place to catch regressions before you ship. But no single real user is on this exact profile.
When field and lab disagree, the gap tells you something. In the same DACH study, br.de had a lab LCP of 39.5 seconds on mobile, while its field LCP (CrUX origin data, 75th percentile) was 1.3 seconds. The two numbers don't even land in the same bucket: Poor in the lab, Good in the field. The study can't tell why. A common reason is that Lighthouse always loads a page cold, while real visitors often arrive with warm caches and open connections. The opposite pattern, where lab passes but field fails, usually means real users have slow devices or ad-blockers that break your JavaScript.
Trust field data for ranking decisions. Trust lab data for debugging.
Google uses field data. A page that fails Lighthouse but passes CrUX is usually fine, because real users just aren't hitting the lab bottleneck. But lab is still where you catch regressions before they reach users, so use both.
How to Measure Core Web Vitals
Five tools, each with its own job.
The canonical starting point. Paste a URL, get both field (CrUX) and lab (Lighthouse) scores on desktop and mobile. Free, no login, identical API to every other PSI wrapper. Lumina's PageSpeed tool adds AI-generated fix snippets from the audit data.
Lumina PageSpeed →The Core Web Vitals report shows pass/fail status for every page on your site, grouped by URL patterns. Uses field data only, 28-day rolling window. Best for spotting which URL clusters regressed after a deploy.
GSC Dashboard →Chrome DevTools → Lighthouse tab → generate report. Single-URL lab run, same engine as PSI. Use it when you need the trace tab, the LCP element breakdown, or to reproduce a specific regression offline.
Lighthouse docs →Google's 3 KB JavaScript library. Drop it in any page, pipe the callbacks to your analytics endpoint. You get per-user CWV data for your own site, without waiting for CrUX to include you. The only way to measure CWV on low-traffic URLs.
web-vitals on GitHub →Google publishes the full CrUX dataset to BigQuery every month. Query any origin's CWV going back years, aggregate across competitors, benchmark your vertical. BigQuery's free tier (1 TB of queries a month) covers most single-site use. Beyond that, normal BigQuery pricing applies.
CrUX BigQuery →What you do not need: third-party RUM vendors for CWV alone. web-vitals.js plus your existing analytics covers what most sites need for CWV. Buy a commercial RUM product only if you need user-session replay or cross-service tracing on top of CWV.
Do Core Web Vitals Affect Google Rankings?
Marginally. Google says it shows the most relevant content first, even when the page experience is poor, and that a good page experience can help when many pages are similarly helpful. Core Web Vitals are used by its ranking systems, but they don't outweigh relevance. Google has described page experience this way since it rolled Core Web Vitals out as a signal in 2021.
The case for caring about CWV anyway is not rankings; it's the users you already have. A page with a 5-second LCP loses real users before they see the content. A page with 500 ms INP feels broken on every click. A page with CLS 0.3 ejects users mid-read when the layout jumps. These are conversion problems and retention problems. The ranking bump is a rounding error next to the UX loss.
Google doesn't publish how much weight Core Web Vitals carry, and its page experience guidance doesn't say they count more in competitive SERPs. If a page isn't relevant enough to compete, passing CWV won't change that.
How to Fix LCP, INP, and CLS
Skip the general "make the page faster" advice. The right tactic depends on which metric is failing.
Fix LCP: make the largest element arrive first
Identify the LCP element first. PageSpeed Insights tells you in the Diagnostics section. Look for "Largest Contentful Paint element" with the exact HTML. It's usually a hero image, a heading, or a large text block. Once you know what it is, the fix catalog is:
- Preload the LCP image. Add
<link rel="preload" as="image" href="..." fetchpriority="high">in the head. This starts the fetch before the browser discovers the<img>tag during parsing. Only add it if you have verified the element is actually the LCP, since preloading the wrong image slows your real LCP down (see Lumina's own homepage LCP investigation from 2026-04-20 for the pattern). - Serve the LCP image in WebP or AVIF. WebP saves 25–35% vs JPG at matched quality. AVIF another 20% on top. Both are supported by every browser in 2026. Cloudflare Images, ImageKit, Next.js Image, or a build-time conversion script covers this.
- Set
loading="eager"andfetchpriority="high"on the LCP image. The default isloading="lazy"in some CMSes, which delays the fetch by hundreds of milliseconds on above-fold images. Eager + high priority signals the critical path. - Fix the server's Time To First Byte (TTFB). Every millisecond of TTFB adds to LCP directly. Cache at the edge (Cloudflare, Fastly, Netlify). If your app server takes 800 ms to render, no front-end optimization recovers it.
- Inline the critical CSS. External stylesheets block the first paint. Extract the CSS needed for above-the-fold content and inline it in the head. Defer the rest with
<link rel="preload" as="style" onload="this.rel='stylesheet'">.
Fix INP: keep the main thread responsive
INP fails when JavaScript blocks the main thread during a user interaction. The fix catalog is all about shortening long tasks:
- Break up long tasks. Any synchronous JavaScript block running > 50 ms is a "long task" in Chrome's vocabulary. Split it with
scheduler.yield()(modern) orawait new Promise(r => setTimeout(r, 0))(compatible) inside loops. - Defer non-essential third-party scripts. Analytics, chat widgets, ad scripts, heatmap trackers. Load them after first interaction, not at page load. Lumina's own GTM setup uses interaction-only deferral (scroll, click, keydown, mousemove) to keep gtag.js out of the pre-interaction main thread.
- Avoid forced layout inside event handlers. Reading
offsetWidth,getBoundingClientRect,clientHeightright after a DOM write forces the browser to recalculate layout synchronously. Batch reads before writes; userequestAnimationFramewhen you need layout data. - Use CSS transitions instead of JavaScript animations. Transitions on
transformandopacitycan run on the compositor thread, while JavaScript animations run on the main thread. What INP measures is the delay until the next paint, so keep the click handler itself short and let CSS do the visual work. - Cut React re-renders. React components re-rendering on every interaction, especially context providers with frequently-changing state, cascade into hundreds of virtual DOM diffs. Memoize with
React.memo, use refs for non-UI state, split context by update frequency.
Fix CLS: reserve space before content arrives
The CLS list is short but often ignored:
- Always set
widthandheighton every<img>. The browser reserves space via the aspect ratio before the image loads. Without these attributes, the image inserts with zero height initially, then pushes everything below down when it paints. - Reserve space for ads, embeds, and dynamically-injected content. Wrap the slot in a
<div>with a fixedmin-heightmatching the expected content size. When the ad loads, it fills the reserved space instead of pushing the article. - Use
font-display: swapcarefully. It prevents invisible text but triggers a layout shift when the web font loads and replaces the fallback. If the fallback and web font have similar metrics (usesize-adjust,ascent-override,descent-overrideon the@font-face), the swap is invisible. If they don't, the text reflows. - Avoid inserting content above existing content after load. Banner notifications, cookie prompts, newsletter overlays. If they render at the top of the page mid-load, they shift everything down. Render them as fixed-position overlays instead.
After the fixes, verify with the Lumina PageSpeed tool (field + lab in one report), run JS vs No-JS to see how much CWV depends on your JavaScript layer, and check the Alt Text Checker for missing image dimensions that cause CLS. All three are free, no login.
FAQ
Where to Start
Five moves in order. A 30-minute baseline for a small site, half a day for a medium one:
Run your homepage and top 5 content URLs through Lumina's PageSpeed tool. Write down the field LCP, INP, CLS at the 75th percentile per URL. This is your "today" number, not lab. Only field moves Google.
PageSpeed tool →Of the 3 metrics, usually one is the blocker site-wide. Fix it first, not all three in parallel. If it's LCP, jump to image + TTFB fixes. If INP, JS main-thread work. If CLS, image dimensions + ad slot reservation.
The fix catalog ↑CrUX reports a rolling 28-day window and skips low-traffic pages. Drop Google's web-vitals.js library into your page, pipe callbacks to GA4 or your analytics endpoint. You get near-real-time CWV on every URL.
GA4 Dashboard →Lighthouse inside Chrome DevTools is fast, reproducible, and free. Add a Lighthouse check to your pre-deploy checklist. Field data shifts gradually because it averages the last 28 days; lab data catches the regression in 30 seconds.
Lighthouse docs →Google's CWV report in Search Console shows URL clusters that regressed. A single deploy can degrade hundreds of URLs sharing a template. Check once a month, fast-fix patterns.
GSC Dashboard →Audit Core Web Vitals in 30 seconds
Lumina's free PageSpeed tool runs both the PSI lab audit and the CrUX field data side by side, plus AI-generated fix snippets for the top opportunities. No login. The free tier allows 50 PageSpeed runs and 10 AI fix runs per day.
Run the PageSpeed tool →