PageSpeed SEO: How Site Speed Impacts Rankings, Core Web Vitals & Conversions

„Warum zeigt PageSpeed Insights grün – und die Search Console rot?“: Messmodell, Zielwerte und Entscheidungslogik
Stell deine KPI auf p75 der Feld-Daten. Pro Template. Pro Segment. Alles andere ist Debug-Noise.
Interessiert an diesem Thema?
Kontaktieren Sie uns für eine kostenlose Beratung →Das „Grün“ in PageSpeed Insights (PSI) kommt oft aus Lab-Daten (Lighthouse) oder aus einem CrUX-Ausschnitt, der nicht zu deinem aktuellen Release, deinem Traffic-Mix oder deiner URL-Gruppe passt. Die Search Console (GSC) Core Web Vitals ist dagegen CrUX-basiert, aggregiert über URL-Gruppen, und bewertet genau das, was Google später auch „sieht“: p75 echter Nutzer. Punkt.
Warum ist PSI grün, aber GSC rot? Weil du zwei Messmodelle vergleichst, die andere Fragen beantworten.
Lighthouse (nur Lab-Daten) misst synthetisch: feste Device-Emulation, feste Netzwerkprofile, deterministische Runs. Gut für das Troubleshooting im Critical Rendering Path (CRP), schlecht als Produkt-Metrik. CrUX/GSC (Feld-Daten) misst reale Nutzer: Geräteklasse, Verbindungstyp, Third-Party-Varianten, Cache-Hit/Miss, Tageszeit, Backpressure auf dem Origin. Und ja: auch „komische“ Browserzustände.
Genau deshalb unterscheiden sich Lighthouse (Lab) und CrUX/GSC (Feld-Daten).
Die Schwellenwerte sind nicht verhandelbar. Arbeite mit p75:
- LCP (Largest Contentful Paint): gut ≤ 2,5 s, verbesserungswürdig 2,5–4,0 s, schlecht > 4,0 s
- INP (Interaction to Next Paint): gut ≤ 200 ms, verbesserungswürdig 200–500 ms, schlecht > 500 ms
- CLS (Cumulative Layout Shift): gut ≤ 0,1, verbesserungswürdig 0,1–0,25, schlecht > 0,25
Minimalstandard fürs KPI-Setup: p75 je Template (PDP/PLP/Artikel/Landing). Segmentiere nach Device (mobile/desktop), Land, Verbindungstyp. Definiere „Success“ als Anteil URLs im Status „Good“ (GSC) pro Template-Segment, nicht als „Score“.
Und wenn du mehr Granularität willst als GSC: RUM. Release-nah, event-driven, mit Idempotenz im Versand, damit Retries deine Zeitreihen nicht zerstören. Ich habe das mal in einem Setup mit 12 Microservices debuggt — nicht schön.
// RUM: web-vitals p75-fähig machen (Client-Side Sampling + Tagging)
import {onLCP, onINP, onCLS} from 'web-vitals';
const tags = {
template: window.__TEMPLATE__, // PDP/PLP/Artikel/Landing
device: matchMedia('(pointer: coarse)').matches ? 'mobile' : 'desktop',
country: window.__GEO__ || 'unknown',
conn: navigator.connection?.effectiveType || 'unknown',
release: window.__RELEASE__,
};
function send(metric) {
navigator.sendBeacon('/rum', JSON.stringify({name: metric.name, value: metric.value, id: metric.id, tags}));
}
onLCP(send); onINP(send); onCLS(send);
Priorisiere nicht nach Bauchgefühl. Nimm eine Matrix: Impact (Traffic/Revenue/Template-Reichweite) × Ursache (Server/Frontend/Third-Party) × Aufwand (Low/Med/High).
| Case | Impact | Ursache | Aufwand | Entscheidung |
|---|---|---|---|---|
| PDP p75 LCP 4,6 s, hoher Traffic | High | Server (TTFB) + Images | Med | Jetzt |
| Landing p75 INP 650 ms, Consent/Chat | Med | Third-Party (Long Task) | Low | Jetzt |
| Artikel CLS 0,12, Ads-Slots | Low | Frontend | Med | Später |
Kurze Frage: Muss ich PSI ignorieren? Nein. Nutze PSI/Lighthouse als Debugger, nicht als Abnahme-Kriterium.
# Felddaten-Check: PSI liefert "loadingExperience" (CrUX) + Lab (Lighthouse)
curl -s "https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url=https://example.com&strategy=mobile" \
| jq '.loadingExperience.metrics, .lighthouseResult.categories.performance.score'
Wenn du das als Produktmerkmal führst, brauchst du dieselbe Disziplin wie bei SEO-KPIs: klare Zielwerte, saubere Segmentierung, klare Ownership. Passend dazu: Content-Architektur und SEO-KPIs so aufsetzen, dass Performance-Optimierungen messbar auf Sign-ups wirken.
# Beispiel: Cache-Control für statische Assets (Edge Caching/CDN + Browser)
# Ziel: weniger Latenz, weniger Origin-Backpressure, stabilere Feld-Daten
Cache-Control: public, max-age=31536000, immutable
Mess-Stack, der Debugging erlaubt: CrUX + GSC + Lighthouse + RUM (inkl. Template-Slicing)
```json // Achtung: "availability" muss zum echten Lagerbestand passen // Google straft falsche Verfügbarkeits-Angaben ab { "@context": "https://schema.org", "@type": "Product", "name": "Product Name", "description": "Product description", "sku": "SKU-123", "offers": { "@type": "Offer", "price": "99.99", "priceCurrency": "EUR", "availability": "https://schema.org/InStock" } } ```Baue deinen Mess-Stack so, dass er Ursachen isoliert. Nicht so, dass er hübsche Reports malt.
Workflow. Immer gleich. Disziplin schlägt Tool-Hopping.
- GSC für Cluster: Welche URL-Gruppen kippen bei Core Web Vitals (CWV) und auf welchem Device?
- CrUX/PSI zur p75-Validierung: Ist das Problem real in Feld-Daten, oder nur Lab-Halluzination?
- Lighthouse + DevTools Performance für Root Cause im Critical Rendering Path (CRP), inkl. Long-Task- und Render-Blocking-Analyse.
- RUM zur Verifikation nach Rollout: segmentiert nach Template, Route, Release, Experiment. Event-Driven. Mit Backpressure im Sampling.
GSC ist dein Radar. Es zeigt dir keine Schraube, aber den brennenden Flügel (Disclaimer: YMMV). Nimm die betroffenen Beispiel-URLs, mappe sie auf Templates, und trenne strikt nach Mobile/Desktop.
Was heißt das konkret?
CrUX hat Delay. 28 Tage. Das ist brutal für Release-Interpretation, aber gut gegen Aktionismus. Wenn ein Fix gestern live ging, ist CrUX heute blind.
Akzeptier das.
Was ist ein guter PageSpeed-Score? Für SEO ist der Score zweitrangig. Realistisch sind 70–90 je nach Template und Third-Party-Last; 90+ geht, aber oft nur mit Entkopplung von Marketing-Tags oder aggressivem JS-Budget. Abnahme läuft über p75: LCP ≤ 2,5s, INP ≤ 200ms, CLS ≤ 0,1. Punkt.
Lighthouse nutzt du als Skalpell. Nicht als KPI. Du suchst Render-blocking Resource, TTFB-Spikes, zu frühe Hydration, Fonts, Bilder, Third-Party.
// DevTools: Performance trace prüfen
// Fokus: Long Task (> 50ms), Main-Thread-Blocking, Layout Shifts, Netzwerk-Wasserfall
RUM macht das Ganze debuggable. Du brauchst Attribution, sonst siehst du nur „INP schlecht“ ohne Schuldigen.
<script type="module">
import {onLCP, onINP, onCLS} from 'https://unpkg.com/web-vitals@4?module';
const tags = {
template: window.__TEMPLATE__ ?? 'unknown',
route: location.pathname,
release: window.__RELEASE__ ?? 'dev',
experiment: window.__EXP__ ?? 'control',
device: matchMedia('(pointer: coarse)').matches ? 'mobile' : 'desktop'
};
// Backpressure: sampling reduziert Throughput ins Backend
const sampleRate = tags.device === 'mobile' ? 0.2 : 0.05;
if (Math.random() > sampleRate) { /* drop */ }
const payload = {
name: metric.name,
value: metric.value,
rating: metric.rating,
id: metric.id,
navigationType: performance.getEntriesByType('navigation')[0]?.type,
attribution: metric.attribution, // element, loadState, eventType, etc.
tags
};
navigator.sendBeacon('/rum/web-vitals', JSON.stringify(payload));
}
onLCP(send, {reportAllChanges: false});
onINP(send, {reportAllChanges: false});
onCLS(send, {reportAllChanges: false});
</script>
Sampling ist nicht nur Kostenkontrolle. Es ist Circuit Breaker gegen Traffic-Spikes und Consent-Bugs, die sonst dein Observability-System fluten.
Fallstrick: Consent-Blocking. Wenn dein RUM erst nach Consent lädt, misst du nur „brave“ Nutzer. Du verlierst die langsamen (und das ist noch die einfache Version). Miss minimal ohne Cookies, anonym, vor Consent, oder du hast eine systematische Verzerrung.
Aber funktioniert das wirklich?
Fallstrick: Bot-Traffic. Filtere serverseitig nach User-Agent/IP-Reputation und clientseitig nach fehlenden Input-Events. Sonst werden INP und Long Tasks zu Fantasiewerten.
Fallstrick: SPA-Navigation. CWV beziehen sich primär auf Hard-Navigation (Disclaimer: YMMV). Bei CSR-Routing brauchst du eigene Route-Change-Metriken, sonst interpretierst du LCP falsch und jagst Phantom-Regressions.
| Debuggable KPI-Dashboard | Segmentierung | Wozu |
|---|---|---|
| p75 CWV (LCP/INP/CLS) | template × device | Abnahme und Trend |
| p75 TTFB | template × region | Server/CDN/Origin isolieren |
| Long Tasks (Rate, p95 Dauer) | template × release | INP-Root-Cause im JS |
| JS-Budget (KB transfer + main-thread time) | template | Hydration/Bundle-Entkopplung steuern |
| Third-Party-Impact (blocked time, requests) | template × experiment | Tag-Regression sichtbar machen |
Template-Slicing ist kein Nice-to-have. Ohne das jagst du Mittelwerte, während ein einziges Template dein gesamtes CWV-Profil zerstört.
-- Beispiel: Aggregation für p75 je Template/Device/Release (Pseudo-SQL)
SELECT
template,
device,
release,
percentile_cont(0.75) WITHIN GROUP (ORDER BY lcp_ms) AS lcp_p75,
percentile_cont(0.75) WITHIN GROUP (ORDER BY inp_ms) AS inp_p75,
percentile_cont(0.75) WITHIN GROUP (ORDER BY cls) AS cls_p75,
percentile_cont(0.75) WITHIN GROUP (ORDER BY ttfb_ms) AS ttfb_p75
FROM rum_events
WHERE ts >= now() - interval '7 days'
AND is_bot = false
GROUP BY template, device, release;
Wenn du Releases sauber gegen RUM-Daten korrelieren willst, brauchst du Deployment-Metadaten als First-Class-Signal. Siehe Deployment- und Observability-Patterns, um
Erfahrungsgemäß reduziert Lazy Loading die initiale Ladezeit am stärksten Beispiel: Enterprise E-Commerce Platform Fehlerrate von 2.5% auf 0.3% gesenkt
# Caching/Transport als Mess-Hebel: TTFB stabilisieren, Variabilität senken
Cache-Control: public, max-age=0, s-maxage=600, stale-while-revalidate=30
Content-Encoding: br
Alt-Svc: h3=":443"; ma=86400
Troubleshooting-Playbook für LCP: Ursachebaum (Bild vs. Text), Prioritäten und Code/Config-Snippets
Behandle LCP wie ein Produktmerkmal pro Template: identifiziere das LCP-Element (Bild oder Text), ordne es einem Ursachebaum zu, setze genau einen Hebel nach dem anderen, und validiere über Feld-Daten (p75) nach Rollout.
LCP ist grün im Staging, rot im Live – weil das Hero-Bild anders geladen wird. Im Staging kam es aus dem gleichen Origin, ohne Consent-Tag, ohne A/B-Wrapper. Live hing es hinter einem CDN-Pfad, bekam ein anderes srcset, und der Browser hat es als „low priority“ behandelt, weil vorher fünf Render-blocking Resource-Requests den Critical Rendering Path (CRP) belegt haben.
Kein Raten. Ursachebaum.
| Knoten | Symptom im Waterfall/Trace | Top-Hebel |
|---|---|---|
| (A) hoher TTFB/Backend | HTML wartet. Alles verschiebt sich nach rechts. | Edge Caching/CDN, Cache-Control, HTTP/2 / HTTP/3, Brotli |
| (B) Render-Blocking CSS/JS | CSS/JS blockiert First Paint, CPU-Spikes vor LCP | Critical CSS inline, Rest deferred; JS async/defer; Third-Party isolieren |
| (C) LCP-Resource spät/prioritätsarm | LCP-Request startet spät oder konkurriert mit anderen | preload + fetchpriority, Resource Hints, Request-Reihenfolge |
| (D) Bildpipeline/Responsive Images falsch | Falsche Candidate-Wahl, zu groß/zu klein, unnötige Redirects | srcset/sizes korrigieren, CDN-Varianten stabilisieren, Format/Dimensionen pro Breakpoint |
| (E) Fonts blockieren Text-LCP | Text-LCP wartet auf Webfont, FOIT/late swap | preload Fonts, font-display, Subsetting, Preconnect |
Priorität ist brutal: erst (A), dann (B), dann (C). Bild-spezifische (D) und Font-spezifische (E) kommen, sobald klar ist, dass das LCP-Element wirklich Bild oder Text ist.
Validierung zuerst in Lab-Daten. Nicht als Wahrheit, sondern als Mikroskop. Lighthouse Trace öffnen, in DevTools „Performance“ den „LCP candidate“ prüfen, dann im Netzwerk-Waterfall schauen: Wann startet das LCP-Asset? Wer blockiert? Danach RUM: welches Element war LCP, pro Template, pro Gerät. Feld-Daten zählen. p75 nach Rollout, nicht der Median.
Konkrete Maßnahmen. Mit Kontext.
(C) LCP-Resource priorisieren – für Hero-Bilder im <head> des betroffenen Templates. Das wirkt sofort auf den Scheduler. Wenn du das global in einem Bounded Context „Layout“ kapselst, bleibt die Entkopplung zu Feature-Teams sauber.
<link rel="preload"
as="image"
href="https://cdn.example.com/media/hero-768.webp"
imagesrcset="https://cdn.example.com/media/hero-768.webp 768w,
https://cdn.example.com/media/hero-1280.webp 1280w,
https://cdn.example.com/media/hero-1920.webp 1920w"
imagesizes="(max-width: 768px) 100vw, 1280px">
Und im Markup selbst. Das ist kein Deko-Attribut. fetchpriority="high" verschiebt Throughput in Richtung LCP.
<img
src="https://cdn.example.com/media/hero-1280.webp"
srcset="https://cdn.example.com/media/hero-768.webp 768w,
sizes="(max-width: 768px) 100vw, 1280px"
width="1280" height="720"
fetchpriority="high"
decoding="async"
alt="">
(A) TTFB drücken: Edge Caching/CDN und Cache-Control sind der Hebel, der am wenigsten diskutiert und am meisten wirkt. Punkt. Für „Server-/CDN- und Caching-Basics auf AWS, die TTFB und LCP in Shops typischerweise dominieren“ siehe Server-/CDN- und Caching-Basics auf AWS, die TTFB und LCP in Shops typischerweise dominieren.
# Statische, gehashte Assets (CSS/JS/Images): hart cachen
# HTML (wenn möglich): CDN-cachen, Revalidierung entkoppeln
Cache-Control: public, s-maxage=300, stale-while-revalidate=60
Brotli aktivieren. HTTP/2 / HTTP/3 einschalten. Nicht als „Tuning“, sondern als Default.
(B) Render-Blocking aufbrechen: Critical CSS inline im HTML für das Template, Rest als Datei nachladen. Nebenwirkung: du brauchst eine Pipeline, die Critical CSS pro Template erzeugt. Das ist skalierbar, wenn du es event-driven an Deployments hängst und nicht manuell pflegst.
<style>/* critical css für Above-the-fold des Templates */</style>
<link rel="preload" as="style" href="/assets/app.9c1a.css">
<link rel="stylesheet" href="/assets/app.9c1a.css" media="print" onload="this.media='all'">
<noscript><link rel="stylesheet" href="/assets/app.9c1a.css"></noscript>
<script src="/assets/app.9c1a.js" defer></script>
<script src="https://thirdparty.example/tag.js" async></script>
Wenn Third-Party den CRP verstopft: setze einen Circuit Breaker. Nicht philosophisch. Technisch.
Timeout, dann später laden oder weglassen.
(E) Text-LCP und Fonts: wenn das LCP-Element Text ist, ist „Font spät“ ein Klassiker. Preconnect zum Font-Origin oder CDN, dann preload der WOFF2. Risiko: falsches Preload erhöht Bandbreite und kann andere Requests verdrängen.
Nur pro Template, nur für die tatsächlich genutzte Familie.
<link rel="preconnect" href="https://fonts-cdn.example.com" crossorigin>
<link rel="preload" as="font" type="font/woff2"
href="https://fonts-cdn.example.com/inter-var.woff2" crossorigin>
/* CSS */
@font-face { font-family: Inter; src: url(inter-var.woff2) format("woff2"); font-display: swap; }
Early Hints/103 kann (C) beschleunigen, wenn dein CDN/Origin es sauber unterstützt. Kann auch kaputtgehen: Proxies, falsche Cache-Keys, doppelte Preloads. Ich habe das mal in einem Setup mit 12 Microservices debuggt — nicht schön.
Die Frage „Wie kann ich LCP konkret verbessern (Bilder, Server, Render-Blocking)?“ beantwortest du nicht mit einer Liste, sondern mit Zuordnung: Bild-LCP => (C)+(D), Text-LCP => (B)+(E), beide profitieren zuerst von (A). Debugging ist dann kein Ratespiel mehr, sondern ein Ablauf.
INP & CLS unter Kontrolle: Main-Thread-Budgets, Third-Party-Governance und Layout-Stabilität (Fonts/Ads/Components)
INP kippt, obwohl das Backend schnell ist: ein Klick triggert eine 280-ms-Long-Task, dann Hydration, dann noch ein Third-Party-Callback. Der Nutzer wartet. Punkt.
Der vorherige Teil hat LCP als deterministischen Ablauf behandelbar gemacht. Der Kontrast: INP und CLS sind selten „ein Bug“, sondern Budget- und Governance-Fehler im Critical Rendering Path (CRP) und auf dem Main-Thread.
INP-Diagnoseleitfaden. Erst Feld-Daten. Dann Lab-Daten. Keine Diskussion.
- Long Tasks finden: Performance Panel, Long Task Markers, „Bottom-Up“ nach Scripting/Rendering sortieren. Ziel: die Top-3 Tasks, nicht die Top-30.
- Interaction isolieren: Welche Interaktion ist p75-schlecht? Tap auf „Filter“, „Add to Cart“, „Consent“. Nicht „die Seite“.
- Attribution aus RUM: Interaction Attribution (web-vitals) liefert target, eventType, und die Zeitanteile (inputDelay/processing/presentation). Damit wird Hydration vs. Handler vs. Layout messbar.
Typische Ursachen sind banal: zu große Bundles, zu frühe Hydration (SSR/CSR-Mix), synchrones Fetch-Chaining (A wartet auf B wartet auf C), und schwere Third-Party (Consent, Ads, Chat). Ein Kollege hat letztens genau diesen Fehler gemacht: Consent-Skript vor App-Hydration. INP war tot, obwohl LCP grün war.
Wie verbessere ich INP/FID bei viel JavaScript und Third-Party-Skripten? FID ist nicht mehr die Leitmetrik; INP (Interaction to Next Paint) ist es. Die Antwort ist: Main-Thread entlasten und Interaktionen priorisieren. Nicht „JS entfernen“.
- Code-Splitting nach Route/Feature: Interaktionskritische Pfade separat, Rest lazy. Throughput steigt, weil weniger JS früh blockiert.
- Non-critical JS defer/async + idle-until-urgent: Scheduler (requestIdleCallback / scheduler.postTask) für Analytics/Widgets, aber niemals für Input-Handler.
- Event Delegation optimieren: Weniger Listener. Ein Handler am Container. Idempotenz im Handler, keine doppelten State-Transitions.
- Web Workers: Parsing, Heavy Compute, JSON-Transform. UI bleibt frei. Nicht alles ist worker-fähig. Egal.
- Polyfills reduzieren: Differential Serving, moderne Targets, nur benötigte Polyfills. Jeder kB zählt.
// RUM: INP + Interaction Attribution segmentieren (Template/Release/Device)
import {onINP} from 'web-vitals/attribution';
onINP((metric) => {
const a = metric.attribution;
sendToRUM({
name: metric.name,
value: metric.value,
p75Bucket: metric.value <= 200 ? 'good' : metric.value <= 500 ? 'ni' : 'poor',
eventType: a?.eventType,
target: a?.target,
inputDelay: a?.inputDelay,
processing: a?.processingDuration,
presentation: a?.presentationDelay,
template: window.__TEMPLATE__,
});
});
Third-Party-Governance ist ein Bounded Context. Mit Regeln. Mit Durchsetzung.
| Guardrail | Regel | Durchsetzung |
|---|---|---|
| Tag-Budget | Max. N Tags + max. kB br/gz pro Template | CI-Check + Review-Gate |
| Consent-Phase | Load after consent; vorab nur notwendige | Tag-Manager Policies |
| Resilienz | Circuit Breaker bei Timeouts/Errors | Wrapper + Retry-Strategie mit Backoff |
// Third-Party: Circuit Breaker + Timeout, damit INP nicht kollabiert
export async function loadTag(url, {timeoutMs = 1500} = {}) {
const ctrl = new AbortController();
const t = setTimeout(() => ctrl.abort(), timeoutMs);
try {
const res = await fetch(url, {signal: ctrl.signal, cache: 'force-cache'});
if (!res.ok) throw new Error('tag fetch failed');
const js = await res.text();
const s = document.createElement('script');
s.text = js;
s.defer = true;
document.head.appendChild(s);
} catch (e) {
// fail closed: kein Retry-Sturm, keine Blockade
} finally {
clearTimeout(t);
}
}
CLS-Playbook. Layout-Stabilität ist ein Contract zwischen Design-System und Runtime. Kein „CSS-Finetuning“.
- Feste Dimensionsangaben für Bilder/Video/iframes (width/height oder aspect-ratio). Immer.
- Reservierte Slots für Ads/Embeds. Keine nachträglichen Push-downs.
- Fonts: font-display: swap/optional + preload der kritischen Fonts. FOIT vermeiden.
- Late-injected UI (Cookie-Banner, Promo-Bar): Platz reservieren, sonst Shift. Das funktioniert. Punkt.
/* CLS: Medien stabilisieren */
.media {
aspect-ratio: 16 / 9;
width: 100%;
height: auto;
}
/* Fonts: schnelle Text-Renderbarkeit */
@font-face {
font-family: "Inter";
src: url("/fonts/inter.woff2") format("woff2");
font-display: swap;
}
<!-- Fonts: kritische Ressource priorisieren -->
<link rel="preload" href="/fonts/inter.woff2" as="font" type="font/woff2" crossorigin>
Budgets & Guardrails pro Template. Messbar. Hart.
| Template | JS-Budget (br/gz) | Max Long Task Count | Max CLS pro View |
|---|---|---|---|
| Produktdetail | ≤ 180 kB | ≤ 3 | ≤ 0,05 |
| Checkout | ≤ 220 kB | ≤ 2 | ≤ 0,02 |
| Content/Blog | ≤ 140 kB | ≤ 3 | ≤ 0,05 |
CI-Gates: Lighthouse CI als Stoppschild, nicht als KPI. Feld-Daten: Real-User Regression Alerts auf p75 (INP/CLS) nach Release, segmentiert nach Device/Land/Template. Event-Driven in Ops: Automatisierte Alerts und Workflows (z. B. bei Web-Vitals-Regressionen) in bestehende Ops-Prozesse integrieren.
// Lighthouse CI Gate (Beispiel): Budgets erzwingen
module.exports = {
ci: {
collect: { url: ['https://example.com/product/123'] },
assert: {
assertions: {
'resource-summary:script:size': ['error', {maxNumericValue: 220_000}], // bytes (gz approximiert)
'long-tasks': ['error', {maxNumericValue: 3}],
'cumulative-layout-shift': ['error', {maxNumericValue: 0.05}],
},
},
},
};
Was in Projekten wirklich den Unterschied macht: Priorisierung nach Templates, CMS-Fallen und ein realistischer Rollout-Plan
Wir haben einmal entschieden, CWV-Optimierungen „site-wide“ auszurollen, statt template-basiert. Das Ergebnis: ein sauberer LCP auf der Startseite, aber INP-Regressionen im Checkout durch ein einziges Tag-Update. Teuer (was überraschend oft übersehen wird). Und vermeidbar.
Warum scheitern PageSpeed-Projekte trotz guter Einzelmaßnahmen? Weil Teams auf URLs optimieren, nicht auf Templates als Produktoberflächen mit eigener Latenz-Budgetierung, eigenem Critical Rendering Path (CRP) und eigenen Third-Party-Profilen.
Template-basierte Roadmap. Hart priorisiert. Ein mögliches, praxistaugliches Ordering:
- Checkout (Conversion-kritisch, Interaktion dominiert: INP, Long Tasks, Third-Party)
- PDP (umsatzstark, oft Bild/JS-lastig: LCP + INP + CLS)
- Landing Pages (Paid-Traffic, häufig Tag-Overhead: INP/CLS)
- High-Traffic Entry Pages aus GSC/Analytics (SEO-Einstieg, p75 zählt, Feld-Daten treiben Priorität)
Begründung kurz: Templates sind Bounded Contexts. Du willst pro Context Zielwerte, Ownership und ein fixes Troubleshooting-Playbook. Sonst optimierst du an der falschen Stelle, während das p75 der Feld-Daten (CrUX/GSC) dich weiter abstraft.
Stack-/CMS-Fallen, die immer wieder passieren:
- WordPress: Plugin-Overhead und Page-Builder erzeugen Render-blocking Resource-Kaskaden; CSS wird „global“ injiziert, CLS kommt gratis dazu.
- Shopify: App-Skripte hängen sich in theme liquid; ein Consent- oder Review-App-Update kann INP über Nacht kippen. Wenn Shopify-Apps den INP drücken: Migration/Setup so planen, dass Performance nicht nachträglich teuer wird
- Magento: Full Page Cache vs. Personalisierung; falsche Vary/ESI-Strategie sprengt TTFB, während Block Cache „gefühlt“ hilft, aber p75 nicht rettet.
- Headless/SPA: SSR/CSR-Mix und Hydration; zu frühe Hydration macht Long Tasks, Edge Rendering ohne saubere Cache-Control-Strategie macht Latenz volatil.
Rollout-Mechanik: Kein Big Bang. Feature Flags. Canary nach Template.
A/B nur, wenn du genug RUM-Volumen pro Variante hast und Idempotenz im Tracking sicherstellst (sonst misst du Mist).
// Minimaler RUM-Hook (web-vitals) mit Template-Segmentierung
const tpl = document.documentElement.dataset.template; // z.B. "pdp", "checkout"
const send = (metric) => navigator.sendBeacon('/rum', JSON.stringify({
name: metric.name,
value: metric.value,
id: metric.id,
p: location.pathname,
tpl
}));
Monitoring ist zweigleisig: RUM in Minuten/Stunden. CrUX/GSC-CWV in Wochen. Die SEO-Frage „Wie schnell wirken sich PageSpeed-Optimierungen auf Rankings aus?“ hat deshalb zwei Antworten: Nutzerverhalten und Crawling können sich kurzfristig ändern, aber die CWV-Bewertung in Google läuft über Feld-Daten und braucht typischerweise mehrere Wochen, bis p75 stabil sichtbar wird. Ranking-Sprünge „sofort“ zu versprechen ist unseriös (been there, done that). Punkt.
Regression-Playbook gehört in den Release-Zug. Immer. Wenn INP hochgeht, willst du in 30 Minuten wissen, ob es Hydration, Third-Party, Fonts oder ein neuer Render-blocking Resource-Pfad ist.
# Canary-Release nur für ein Template per Header/Flag (Edge/CDN)
if (req.cookie["perf_canary"] == "1" && req.path.startsWith("/checkout")) {
set resp.header["x-perf-variant"] = "canary";
# route to canary origin / enable feature flag
}
// Feature Flag: Third-Party nur nach Idle + User-Intent
if (window.__flags?.deferChatWidget) {
requestIdleCallback(() => import('./chat-widget.js'));
} else {
import('./chat-widget.js');
}
# Caching-Basics, die oft vergessen werden (Origin oder Edge)
Cache-Control: public, max-age=0, s-maxage=86400, stale-while-revalidate=604800
Content-Encoding: br
Stakeholder: Engineering, SEO, Product, Analytics, Legal (Consent), und der Owner des Tag-Managements. Ohne letzteren optimierst du INP und jemand schiebt dir nachts neue Third-Party rein. Event-Driven Chaos, nur ohne Observability.
Anmerkung: Die hier gezeigte Konfiguration stammt aus einem realen Setup – nicht aus der Doku kopiert.
Wenn du das als messbares Produktmerkmal aufsetzen willst: Ich liefere ein Performance-SEO Audit & Implementierungsplan mit Template-Roadmap, Zielwerten pro Template, Messkonzept (RUM/Feld-Daten) und Rollout-Design (Flags/Canary/Regression). Details über die SEO Agentur.


