Core Web Vitals in 2025: what actually moves the needle
Google's metrics evolved. We audited 40 sites and found the same culprits: third-party scripts, unoptimized images, and layout instability from injected content.
We audited forty production websites in Q1 2025. The goal was simple: identify what actually impacts Core Web Vitals versus what developers obsess over unnecessarily.
The data
| Metric | Sites Failing | Primary Cause |
|---|---|---|
| LCP | 28/40 | Unoptimized images |
| CLS | 19/40 | Injected third-party content |
| INP | 31/40 | Long JavaScript tasks |
| TTFB | 12/40 | Slow origin response |
LCP: it is almost always images
Twenty-eight sites failed LCP. Twenty-six of them had hero images served without optimization.
What works:
- AVIF format: 30-50% smaller than WebP at equivalent quality
fetchpriority="high": On the LCP image only- Preload hints: For above-fold images
- Proper sizing: No oversized images scaled down with CSS
- CDN with HTTP/3: Reduces time-to-first-byte for the image itself
What does not help much:
- Lazy loading above-fold images (actively hurts)
- Over-engineered loading spinners
- Complex placeholder generation
CLS: the third-party script problem
Nineteen sites had layout shift issues. In fifteen cases, the culprit was third-party scripts injecting banners, chat widgets, or ads after initial render.
Our fix: reserved space for all known injected elements.
.cookie-banner { min-height: 60px; }
.chat-widget { aspect-ratio: 1 / 1; width: 60px; }If the script loads, it fills the reserved space. If it fails, the layout does not shift.
INP: the JavaScript tax
Thirty-one sites failed Interaction to Next Paint. The common thread: main-thread saturation from analytics, A/B testing frameworks, and client-side hydration.
Specific fixes that worked:
- Defer non-critical analytics: Send beacon requests after
requestIdleCallback - Split A/B test logic: Run assignment server-side, not client-side
- Hydration boundaries: Use React Server Components for static content
- Web Workers: Move heavy computation off the main thread
- Event delegation: Reduce individual event listener overhead
One client reduced INP from 380ms to 72ms simply by moving their A/B testing framework from client-side to an edge worker.
TTFB: the forgotten metric
Only twelve sites had poor TTFB, but when it is bad, everything downstream suffers.
The fix is usually geographic: move compute closer to users. Edge functions, regional databases, and CDN caching at the PoP level.
Our audit checklist
Before any client launch, we run:
- Lighthouse CI in CI/CD with 90+ thresholds
- WebPageTest from 3 continents on 4G
- Chrome UX Report comparison for origin-level data
- Real-user monitoring with 75th percentile targets
- Third-party script inventory with performance budgets
The bottom line
Most performance issues are not exotic. They are images, scripts, and layout shifts. Fix the basics before chasing micro-optimizations.