Core Web Vitals & Speed Audit — Phase 10
Executive Summary
Core Web Vitals are confirmed Google ranking signals. In 2025, INP (replaced FID March 2024) is the hardest CWV metric to pass — only ~65% of sites meet Good threshold (Cloudflare 2025). Pages with all CWV in "Good" range see average 15–25% CTR improvement (Google CrUX 2024). Speed directly impacts conversion: 1-second LCP delay = 20% conversion drop (Portent 2023). Always compare client CWV against top 3 competitors.
Tools for This Phase
| Tool | Purpose | Cost | |------|---------|------| | Google PageSpeed Insights | CWV scores + diagnostics (mobile + desktop) | Free | | Chrome DevTools → Lighthouse | Lab data with filmstrip, coverage tab | Free | | Chrome DevTools → Performance | INP profiling, main thread analysis | Free | | WebPageTest (webpagetest.org) | Waterfall, filmstrip, multi-location test | Free | | GTmetrix | Performance grade, waterfall, page size, requests | Free/Paid | | CrUX (Chrome User Experience Report) | Real-user field data from CrUX dataset | Free | | Cloudflare Speed (speed.cloudflare.com) | INP + TTFB from Cloudflare edge | Free | | DebugBear | CWV monitoring, regression detection | Paid | | site_crawler.py | Identify image-heavy pages, JS payload size | Free (local) |
Step 1: Read Project Context
Read {AUDIT_DIR}/intake-data.md — URL, tech stack (CMS affects optimization options). Read {AUDIT_DIR}/technical-findings.md — any speed-related technical issues already flagged.
Step 2: Baseline CWV Data Collection
2025 CWV Thresholds (Updated — INP replaced FID March 2024)
| Metric | Good | Needs Improvement | Poor | Measures | |--------|------|-------------------|------|----------| | LCP (Largest Contentful Paint) | < 2.5s | 2.5–4.0s | > 4.0s | Perceived load speed | | INP (Interaction to Next Paint) | < 200ms | 200–500ms | > 500ms | Responsiveness to interaction | | CLS (Cumulative Layout Shift) | < 0.1 | 0.1–0.25 | > 0.25 | Visual stability | | TTFB (Time to First Byte) | < 800ms | 800ms–1.8s | > 1.8s | Server responsiveness | | FCP (First Contentful Paint) | < 1.8s | 1.8–3.0s | > 3.0s | Initial render | | TBT (Total Blocking Time) | < 200ms | 200–600ms | > 600ms | Main thread blocking |
INP scoring guide (2025 priority):
- < 100ms = Excellent (competitive advantage)
- 100–200ms = Good (meets threshold)
- 200–500ms = Needs Improvement (flag for fixes)
- > 500ms = Poor (critical — likely INP veto trigger)
Data Collection Protocol
- PageSpeed Insights → Mobile (primary — Google ranks mobile-first):
`` URL: https://pagespeed.web.dev/ Test: [client URL] Record: Performance score, LCP, INP, CLS, TTFB, FCP, TBT ``
- PageSpeed Insights → Desktop (secondary benchmark):
`` Record same metrics — gap > 30pts Mobile vs Desktop = mobile-specific issue ``
- Top 3 Competitors — test same URL structure (homepage):
`` Record mobile performance scores for competitive benchmark table ``
- WebPageTest (real network conditions):
`` Location: nearest city to target audience Connection: Mobile 4G LTE Run: 3 tests → median result Record: TTFB, Start Render, Fully Loaded, Total Page Size, Total Requests ``
- Field data vs. Lab data check (PageSpeed "Discover what your real users are experiencing"):
`` CrUX field data available? Compare field vs. lab — large gaps indicate real-user outliers ``
Section 1: LCP Optimization
Identify LCP Element
PageSpeed Insights "Diagnostics" section identifies the LCP element automatically.
LCP element type → fix strategy:
| LCP Element Type | Primary Fix | Secondary Fix | |-----------------|------------|---------------| | Hero image | Preload + WebP/AVIF + fetchpriority="high" | Serve from CDN | | H1 text block | Improve TTFB (server/hosting) + self-host fonts | Inline critical CSS | | Background image (CSS) | Move to <img> tag to allow preload | fetchpriority="high" | | Video thumbnail | Replace with image poster + lazy-load video | Serve from CDN |
LCP Image Fixes (Most Common — 68% of LCP failures)
<!-- Preload the LCP image in <head> -->
<link rel="preload" as="image" href="hero.webp" fetchpriority="high">
<!-- LCP img tag -->
<img src="hero.webp" width="1200" height="630"
fetchpriority="high" loading="eager"
alt="[descriptive alt]">
Image format targets:
- AVIF: 50–80% smaller than JPEG — ideal for LCP (Chrome + Firefox + Safari 16+)
- WebP: 25–35% smaller than JPEG — broad browser support
- Max LCP image size: ≤ 200KB (above fold, compressed)
LCP Server Response (TTFB Fix)
If TTFB > 800ms — server is bottleneck: | Action | Expected TTFB Improvement | Effort | |--------|--------------------------|--------| | Add Cloudflare (free tier) | 30–50% reduction | 30 min | | Enable page caching (WP: WP Rocket/LiteSpeed) | 50–80% reduction | 1–2 hrs | | Upgrade shared → VPS hosting | 40–70% reduction | 2–4 hrs | | Move server geographically closer | 20–40% reduction | 4–8 hrs | | Enable Brotli compression | 10–20% reduction | 30 min |
Section 2: INP Optimization (2025 Priority Signal)
INP measures how quickly a page responds to user interactions (clicks, taps, keyboard input). It's the hardest CWV to fix — requires JavaScript profiling.
Common INP Culprits
| Culprit | How to Detect | Fix | Effort | |---------|--------------|-----|--------| | Long tasks on main thread (>50ms) | Chrome DevTools → Performance → "Long Tasks" | Break with scheduler.yield() or setTimeout(fn, 0) | 4–16 hrs | | Third-party scripts (chat, analytics) | DevTools → Performance → filter by domain | Delay load until after user interaction | 1–4 hrs | | Large JavaScript bundles | DevTools → Coverage tab → unused JS | Code splitting + tree shaking | 8–24 hrs | | Excessive DOM nodes (>1,500) | DevTools → Performance Insights | Virtualize long lists | 4–16 hrs | | Unthrottled scroll/resize handlers | DevTools → Performance → Event Listeners | Debounce/throttle + passive listeners | 1–4 hrs |
INP profiling command (Chrome DevTools):
- Open DevTools → Performance tab
- Click "Record" → perform click/interaction on page → Stop
- Look for "Interaction" entries in the timeline → identify blocking time
Section 3: CLS Optimization
| Cause | Fix | Effort | |-------|-----|--------| | Images without dimensions | Add width and height to all <img> tags | 1–2 hrs | | Ads / iframes without reserved space | Add min-height CSS container before ad loads | 2–4 hrs | | Web fonts causing FOUT | font-display: optional + preload font | 1–2 hrs | | Late-loading embeds (maps, social) | Use fixed-height skeleton placeholder | 1–4 hrs | | Dynamically injected content above fold | Reserve space or inject only below fold | 2–8 hrs | | CSS animation not using transform | Replace top/margin with transform: translateY() | 30 min |
Section 4: Image Optimization (Highest ROI Area)
Image issues cause 60–75% of speed failures on local business sites (Screaming Frog audit data, 2024).
Image Audit Checklist
From python3 scripts/site_crawler.py output + manual check:
- [ ] All above-fold images in WebP or AVIF?
- [ ] Hero/LCP image ≤ 200KB?
- [ ] Below-fold images use
loading="lazy"? - [ ]
srcsetdefined for responsive images? - [ ]
width+heightattributes on all<img>(prevents CLS)? - [ ] No images served larger than display size (e.g., 2000px image at 400px display)?
- [ ] Images served from CDN (not same server as HTML)?
Image optimization tools: | Tool | Purpose | Cost | |------|---------|------| | Squoosh (squoosh.app) | Manual WebP/AVIF conversion | Free | | ImageOptim (Mac app) | Batch lossless compression | Free | | TinyPNG API | Automated batch PNG/JPG compression | Free/Paid | | Cloudinary | On-the-fly optimization + CDN | Free/Paid | | ShortPixel (WordPress) | Au