Ch 15 — Performance, page experience & mobile¶
Part V — Site design · The Technical SEO Reference
Playbook coupling:
seo-checklist.mdPhase 1's "Performance & experience" block (lines 105–108) states the CWV thresholds, mobile parity, the HTTPS framing, and the interstitials rule; Phase 2 adds the never-lazy-load-the-LCP-image caveat (line 128). This chapter supplies the compressed-away machinery: metric mechanics (what can even be your LCP element; INP's three phases; CLS session windows), the CrUX data pipeline and its blind spots, lab-vs-field doctrine, per-metric optimization playbooks, the exact ranking wording and its history, mobile-first indexing's completed timeline, and the prerender/bfcache measurement layer.
Two sentences define this domain's honest boundaries. Google: "Core Web Vitals are used by our ranking systems" — and: "Google Search always seeks to show the most relevant content, even if the page experience is sub-par." Performance is real, bounded, and mostly a user-experience investment that aligns with ranking; it is never a substitute for content, and no lab score anywhere is what Search consumes.
15.1 How CWV feed ranking — the wording, precisely¶
- 🟢 Current doctrine (page experience doc, 2025-12-10): "Core Web Vitals are used by our ranking systems." And the April 2023 definitive statement (blog): "There is no single signal. Our core ranking systems look at a variety of signals that align with overall page experience" — the page experience update "was not a separate ranking system, and it did not combine all these signals into one single 'page experience' signal."
- 🟢 On the four legacy signals (CWV, mobile-friendly, HTTPS, no interstitials), the April 2023 blog: "While not all of these may be directly used to inform ranking, we do find that all of these aspects of page experience align with success in search ranking, and are worth attention." The current doc (2025-12-10) is blunter still: "Beyond Core Web Vitals, other page experience aspects don't directly help your website rank higher in search results."
- 🟢 The two expectation-setting sentences for every client deck: "getting good results in reports like Search Console's Core Web Vitals report or third-party tools doesn't guarantee that your pages will rank at the top," and content wins: "even if the page experience is sub-par." Assessment is page-level "including when understanding aspects related to page experience," with "some site-wide assessments."
- 🟢 ⚠️ The ranking systems guide (2025-12-10, verified against live HTML) lists only Helpful content, Hummingbird, Panda, and Penguin under Retired systems — no "page experience system," "mobile-friendly system," "page speed system," or "secure sites system" appears anywhere on the page. Those named-system framings are historical.
- ⚪ Quarantined: "CWV are a tiebreaker" (informal Googler shorthand, not documentation); "the Dec 2025 core update upweighted page experience" (industry assertion, nothing in Google's docs or changelog); "Lighthouse score is a ranking factor" (§15.5); 🟢 "Page experience is not an eligibility requirement to appear anywhere in the 'Top stories' section."
15.2 Metric mechanics¶
LCP (web.dev/lcp, 2025-09-04) — 🟢 "the render time of the largest image, text block, or video visible in the viewport, relative to when the user first navigated to the page." Qualifying: <img>, <image> in SVG, <video>, url() background-image elements, block-level text. ⚠️ Excluded by heuristic: opacity-0 elements, full-viewport backgrounds, "placeholder images or other images with a low entropy." Size = visible in-viewport size, no margins/padding/borders, cropped portions don't count. Reporting stops at first interaction; background-tab loads ignored; ⚠️ bfcache restores are measured ("users experience them as distinct page visits"). Threshold ≤2.5s at p75, segmented mobile/desktop.
INP (web.dev/inp, 2025-09-02) — 🟢 "observes the latency of all interactions… and reports a single value which all (or nearly all) interactions were beneath." Counted: clicks, taps, key presses. ⚠️ Not counted: hovering, zooming, and scrolling — scroll jank never shows in INP. Outlier discount: "we ignore one highest interaction for every 50 interactions." Three phases: input delay ("time before any callback… is handled") → processing duration ("time for all the callbacks to execute") → presentation delay ("until the frame is presented"). 📘-adjacent mechanics: any task >50ms is a long task; its excess is a "blocking period" that becomes input delay for whatever arrives during it. Thresholds ≤200ms good, >500ms poor. ⚠️ Pages with zero qualifying interactions report no INP — coverage is structurally lower than LCP/CLS. Iframe interactions count (even though parent-page JS can't see them). ⚠️ FID is not merely replaced — "support for FID ended on September 9, 2024"; INP became the CWV on March 12, 2024.
CLS (web.dev/cls, 2023-04-12) — 🟢 score = "impact fraction × distance fraction," aggregated by session windows: "one or more individual layout shifts… with less than 1-second in between each shift and a maximum of 5 seconds for the total window duration" — CLS is the largest window, not a lifetime sum. ⚠️ Only unexpected shifts count: within 500ms of user input → hadRecentInput, excluded (your JS shifting things 600ms after a click does count). Transform/translate animations don't shift layout at all; top/left animations do. Threshold ≤0.1 at p75.
15.3 Field data: CrUX — the pipeline and its blind spots¶
From the CrUX methodology docs — "CrUX is the Google dataset of the Web Vitals program":
- 🟢 Who's in: Chrome users who "Enable usage statistic reporting. Sync their browser history. Not have a Sync passphrase set. Use a supported platform." ⚠️ Who's invisible: "Chrome on iOS," WebView apps, Edge and all other Chromium browsers. Every iPhone user on earth contributes nothing to your field data — an iPhone-heavy audience (or Malaysian market segments skewing iOS) means "mobile" field data describes an Android-only slice.
- 🟢 Which pages: "publicly discoverable using the same indexability criteria as search engines" — non-200-after-redirects and noindex disqualify (⚠️ noindexing a page also deletes its CrUX data), plus "sufficiently popular" ("An exact number is not disclosed" — any circulating threshold number is unverifiable by design).
- 🟢 Windows and cadence: "a 28-day rolling average"; API "updated daily around 04:00 UTC"; BigQuery monthly back to 2017;
collectionPeriodalways displays 28 days even when younger. Dimensions: form factor (phone/tablet/desktop), country (not in the APIs). ⚠️ ECT ("4G") dimension removed Feb 2025, replaced by RTT; ⚠️ the CrUX Dashboard (Looker Studio) was deprecated end of November 2025 — point workflows at CrUX Vis, the API/History API, or BigQuery. - 🟢 SPA limit: "the entire experience is attributed to the initial page view. This is a limitation of the web platform APIs" — route-level CWV via CrUX URLs is unreliable by design (→ Ch 6).
- 🟢 State of the web, June 2026 release (published Jul 14, 2026; V0-verified figures): 18,210,974 origins; 55.3% pass all three CWV (67.7% good LCP, 81.4% good CLS, 85.9% good INP) — a point-in-time baseline for "how bad is our number, really" conversations.
- 🟢 GSC's CWV report is CrUX: URL groups (≤200 rows), group status = "its most poorly performing metric," 28-day basis; "The CrUX database gathers information about URLs whether or not the URL is part of a Search Console property." "No data available" = insufficient CrUX for that device slice, not a site bug.
15.4 Lab data, and why it disagrees¶
- 🟢 PSI serves both worlds (about doc): field = CrUX 28-day p75s ("passes the Core Web Vitals assessment if the 75th percentiles of all three metrics are Good"); lab = "Lighthouse simulates the page load conditions of a mid-tier device (Moto G4)… on a mobile network for mobile."
- 🟢 ⚠️ The Lighthouse Performance score (0–100) is lab-only and is not what Search consumes — a page can score 100 and fail the field assessment, and vice versa. "Get the PageSpeed score to 90+" as an SEO deliverable is lore.
- 🟢 Systematic divergence causes (lab-and-field doc): cold-cache lab loads vs warm-cache users; viewport differences changing which element is the LCP; ⚠️ lab CLS "only considers layout shifts that occur above the fold and during load" vs field counting "throughout the lifespan of the page" (cookie banners, late ads — the #1 reason a Lighthouse-clean page fails field CLS); lab can't know when users interact (INP); personalization.
- 🟢 The priority rule: "if you have both field data and lab data for a given page, field data is what you should use to prioritize your efforts." Lab is for reproduction and debugging, field is for truth.
15.5 Optimization playbooks (per metric)¶
LCP (optimize-lcp, 2025-03-31) — think in four subparts: TTFB → resource load delay → resource load duration → element render delay; ideal shape ≈ 40% / <10% / 40% / <10% (re-verified live 2026-08-04 against optimize-lcp), with the two delays "as close to zero as possible."
- 🟢 "Your LCP resource should be discoverable from the HTML source" — not JS-injected, not hidden in late CSS (→ Ch 6 §6.11's hydration overlap).
- 🟢 ⚠️ "Never lazy-load your LCP image, as that will always lead to unnecessary resource load delay" (playbook line 128's source).
- 🟢 fetchpriority="high" on the LCP image; <link rel="preload"> only for non-discoverable resources. TTFB guide: ≤0.8s good, >1.8s poor — "Because TTFB isn't a Core Web Vitals metric, it's not absolutely necessary" to hit it (→ Ch 2 for server/CDN side).
- 🟢 Diagnostic signature: "A large delta between FCP and LCP… a classic sign of a site that relies heavily on client-side rendering" (→ Ch 6 §6.10).
INP (optimize-inp) — 🟢 "do as little work as possible" in event callbacks; split work so it doesn't become "a long task that blocks the main thread"; yield — 🟢 the current recommendation (optimize-long-tasks, 2024-12-19) is scheduler.yield() ("an API specifically designed for yielding to the main thread in the browser," with prioritized continuation; Chrome/Edge/Firefox, not Safari), with setTimeout as the legacy fallback (runs "in a new task"; nested calls hit the 5ms clamp); run visual updates first, defer the rest. DOM size scales rendering cost; content-visibility = lazy rendering. Third parties: Lighthouse flags scripts "that block the main thread for 250 ms or longer."
CLS (optimize-cls) — 🟢 the four canonical causes: "Images without dimensions. Ads, embeds, and iframes without dimensions. Dynamically injected content… Web fonts." Fixes: "Always include width and height size attributes on your images and video elements" (or aspect-ratio); reserve ad/embed slots at their largest size; inject low, not high ("content closer to the top of the viewport usually causes greater layout shifts"); fonts — font-display: optional, metric overrides (size-adjust, ascent-override, descent-override, line-gap-override), preload critical fonts. bfcache is a free win ("we saw noticeable improvements in CLS").
15.6 The other page-experience factors — current status¶
- HTTPS: 🟢 the only weight ever on record is 2014's: "a very lightweight signal — affecting fewer than 1% of global queries, and carrying less weight than other signals such as high-quality content." Today it survives as a self-assessment question ("Are your pages served in a secure fashion?"); no current doc names a secure-sites system. Table stakes, not a growth lever (implementation → Ch 17). The playbook's line 107 framing is exactly right.
- Interstitials (doc, 2025-12-10): 🟢 framed as a comprehension problem — they "make it hard for Google and other search engines to understand your content, which may lead to poor search performance" — not a named penalty with thresholds. Rules: "Don't obscure the entire page"; "Don't redirect the user to a separate page for their consent or input" (⚠️ the CMP overlap → Ch 6 §6.12); ⚠️ age gates for adult/casino content are exempted — overlay, don't redirect (directly relevant to the gambling portfolio; an 18+ gate done as an overlay is sanctioned). App promotion: banners, never full-page app interstitials. ❓ Whether the 2017 mobile interstitial demotion survives as a distinct signal is officially unanswered — the book states the current wording only.
- Mobile display and excessive ads: self-assessment questions; the machinery that used to measure them (next section) is gone.
15.7 Mobile-first indexing: complete — and what parity still means¶
- 🟢 The timeline: declared complete Oct 31, 2023 ("the trek to Mobile First Indexing is now complete"); final cutoff Jun 3, 2024 announcement — "After July 5, 2024, we'll crawl and index these sites with only Googlebot Smartphone. If your site's content is not accessible at all with a mobile device, it will no longer be indexable." ⚠️ Googlebot Desktop in your logs is still normal in one place: "sometimes used when crawling for product listings and Google for Jobs."
- 🟢 Parity requirements (mobile-first doc): same content, same robots meta tags, same structured data, same alt text, same headings as desktop. "Don't lazy-load primary content upon user interaction. Google won't load content that requires user interactions… to load" (→ Ch 6 §6.9). ⚠️ Error asymmetry: desktop fine + mobile erroring = "this page will be missing from the index."
- 🟢 Three configurations: responsive ("Google recommends Responsive Web Design because it's the easiest design pattern to implement and maintain"), dynamic serving (same URL, "user-agent sniffing and the Vary: user-agent HTTP response header"), separate URLs/m-dot — supported but unforgiving: "The desktop URL is always the canonical, and the mobile version is the alternate"; mobile hreflang → mobile URLs (→ Ch 11); ⚠️ since Nov 2024, large separate-HTML sites must carry all desktop links on mobile or discovery slows (crawl-budget doc note).
- ⚠️ The retired tooling: Mobile-Friendly Test, its API, and the Mobile Usability report all died Dec 1, 2023; the GSC Page Experience report became a link dashboard and the "Good page experience" search-appearance filter was retired (Nov 2023). Google's named direction: "many other robust resources… including Lighthouse from Chrome." Current mobile check: viewport tag (
width=device-width, initial-scale=1— Lighthouse audit), rendered parity via URL Inspection (→ Ch 6 §6.14), field data by device (§15.3).
15.8 Prerendering, speculation rules & bfcache — the measurement layer¶
- 🟢 (Chrome prerender doc, 2026-01-23) The Speculation Rules API prefetches ("processed in the same way that navigations are (but then not rendered)") or prerenders ("as if the page has been opened in an invisible background tab, and then is 'activated'"). Effect on metrics, verbatim: "Prerendering allows a near-instant page load… with near zero LCP, reduced CLS (since any load CLS happens before the initial view), and improved INP."
- 🟢 CrUX exposes the mix via the navigation types breakdown (navigate, navigate_cache, back_forward, prerender…) — the tool for spotting how much of your field data rides on caches/prerender, and the explanation for many "field is faster than lab" cases.
- ⚠️ Interpretation discipline: a site adopting speculation rules will genuinely improve its field CWV for prerendered navigations (real users really get instant loads) — but cross-site comparisons and before/after analyses must check navigation-type mix before crediting template work. ⚪ Analytics double-counting (prerenders firing pageviews before activation) is a real integration hazard — vendor-doc territory, verify per-stack. ❓ Googlebot and speculation rules: no official statement located; Googlebot fetches HTML and doesn't run a foreground browsing session, so speculation is presumptively irrelevant to crawling — flagged as inference, V2 re-check for any statement.
- 🟢 bfcache: restores count as page visits with near-instant paints (§15.2 LCP note) and improved CLS — unblocking bfcache (no
unloadhandlers, noCache-Control: no-storeon HTML where avoidable) is a free field-CWV win.
Symptoms & diagnosis¶
| Symptom | Likely cause | Where |
|---|---|---|
| Lighthouse 95+, GSC CWV report failing | Lab ≠ field: cold cache, viewport, post-load CLS, real-device INP | §15.4 |
| Passing desktop, failing mobile (or vice versa) | Separate p75 per device segment — check form-factor mix | §15.3 |
| Field CLS bad, lab CLS clean | Post-load shifts: late ads, cookie banners, tab UIs | §15.4, §15.5 |
| INP fine but users complain about scroll jank | Scrolling isn't in INP — profile rendering separately | §15.2 |
| "No data available" in GSC CWV | Insufficient CrUX (unpopular URL, noindexed, iOS-heavy audience) | §15.3 |
| LCP dominated by resource load delay | Lazy-loaded or JS-injected hero; undiscoverable LCP resource | §15.5 |
| Big FCP→LCP gap | Client-side rendering signature | §15.5, Ch 6 |
| Field CWV "improved" after adding speculation rules | Real, but check navigation-type mix before crediting template changes | §15.8 |
| Pages missing from index; desktop version fine | Mobile-version errors or interaction-gated primary content | §15.7 |
| Audit cites Mobile-Friendly Test / FID / CrUX Dashboard | Dead tooling (Dec 2023 / Sep 2024 / Nov 2025) | §15.7, §15.2, §15.3 |
Sources¶
All fetched 2026-08-04 (research corpus + one live fetch by drafter; V2 re-fetches all): - Page experience (2025-12-10) · CWV page (2025-12-10) · Ranking systems guide (2025-12-10) · April 2023 page-experience blog - web.dev: vitals (2024-10-31) · lcp (2025-09-04) · inp (2025-09-02) · cls (2023-04-12) · optimize-lcp (2025-03-31) · optimize-inp (2025-09-02) · optimize-cls (2025-02-07) · lab-and-field (2022-07-18) · ttfb (2025-11-28) · fid (2024-10-06) · optimize-long-tasks (2024-12-19) - CrUX: overview · methodology (2024-06-20) · dimensions (2025-02-11) · metrics (2025-11-28) · API (2025-02-11) · BigQuery (2025-02-11) · release notes (2026-07-14) - About PSI (2024-10-21) · GSC CWV report · Third-party summary · Viewport audit (2024-05-27) - Interstitials (2025-12-10) · Mobile-first indexing (2025-12-10) · Oct 2023 completion blog · Jun 2024 final cutoff blog · 2014 HTTPS blog - Prerender pages (Speculation Rules) (2026-01-23, fetched live by drafter) - V2 resolutions (2026-08-04): LCP subpart percentages re-verified live (~40%/<10%/~40%/<10%, optimize-lcp); scheduler.yield() now the documented primary yielding API (added §15.5); AVIF confirmed via changelog Aug 30, 2024 ("Added AVIF to the list of supported image formats"); Googlebot × speculation rules re-searched — still no official statement, ❓ inference stands. Still open: whether the 2017 interstitial demotion survives as a distinct signal (no primary either way)