Core Web Vitals are a confirmed ranking signal and, more importantly, a conversion factor. The current trio:
- LCP (Largest Contentful Paint) — main content visible in < 2.5s. Fixes: static/ISR rendering,
priorityhero image, minimal render-blocking CSS, fast TTFB (see Rendering strategy). - INP (Interaction to Next Paint) — replaced FID in March 2024; every interaction should respond in < 200ms. Fixes: fewer/lazier third-party scripts, smaller client bundles (
"use client"only where needed), breaking long tasks. - CLS (Cumulative Layout Shift) — < 0.1. Fixes: dimensions on all images/embeds, reserved space for banners and ads,
next/font(no font-swap jumps).
Measure both ways:
- Lab: Lighthouse in CI (e.g.
@lhci/clion every PR) catches regressions before deploy. - Field: real-user data is what Google actually ranks on. Wire it up in one hook:
// app/web-vitals.tsx
"use client";
import { useReportWebVitals } from "next/web-vitals";
export function WebVitals() {
useReportWebVitals((metric) => {
// send to your analytics endpoint
navigator.sendBeacon("/api/vitals", JSON.stringify(metric));
});
return null;
}
Check field data in Search Console → Core Web Vitals, or PageSpeed Insights (which shows CrUX data when available).
Checklist:
- LCP < 2.5s, INP < 200ms, CLS < 0.1 in field data, not just Lighthouse
- Lighthouse CI or equivalent guarding against regressions
-
useReportWebVitalsfeeding real-user metrics to your analytics - Mobile checked separately — that's where most sites fail