Web-Vitals-Monitor im Tab — LCP / CLS / INP in der Output Console ohne DevTools
Web Vitals (LCP, CLS, INP) sind 3 Metriken, die Google als SEO-Ranking-Faktor verwendet. Der Standardweg, sie zu messen: Lighthouse in den DevTools — 30 Sekunden pro Audit, manueller Auslöser. Alternative: die in Browser eingebaute PerformanceObserver-API. Plus eine JustZix-JS-Regel = ein passiver Monitor, der für jede besuchte Seite an die Output Console meldet. Perfekt für einen schnellen Check eigener Projekte oder die Analyse von Mitbewerbern.
JS-Regel — vollständige Web-Vitals-Erfassung
Scope: *://*/* oder pro Domain, wenn du nur deine eigenen Seiten überwachen willst.
// JS-Regel „Web Vitals Monitor"
const vitals = { LCP: null, CLS: 0, FCP: null, TTFB: null, INP: null };
// === LCP (Largest Contentful Paint) ===
new PerformanceObserver((list) => {
const entries = list.getEntries();
const last = entries[entries.length - 1];
vitals.LCP = Math.round(last.startTime);
}).observe({ type: 'largest-contentful-paint', buffered: true });
// === CLS (Cumulative Layout Shift) ===
let clsEntries = [];
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (!entry.hadRecentInput) {
clsEntries.push(entry);
vitals.CLS = clsEntries.reduce((s, e) => s + e.value, 0);
}
}
}).observe({ type: 'layout-shift', buffered: true });
// === FCP (First Contentful Paint) ===
new PerformanceObserver((list) => {
const fcp = list.getEntries().find(e => e.name === 'first-contentful-paint');
if (fcp) vitals.FCP = Math.round(fcp.startTime);
}).observe({ type: 'paint', buffered: true });
// === TTFB (Time to First Byte) ===
const nav = performance.getEntriesByType('navigation')[0];
if (nav) vitals.TTFB = Math.round(nav.responseStart - nav.requestStart);
// === INP (Interaction to Next Paint) ===
let worstINP = 0;
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.duration > worstINP) {
worstINP = Math.round(entry.duration);
vitals.INP = worstINP;
}
}
}).observe({ type: 'event', buffered: true, durationThreshold: 16 });
// Bericht 5 Sekunden nach dem Laden + beim Unload (finale Werte)
const report = () => {
const status = (val, good, poor) =>
val === null ? '?' : val <= good ? '✓' : val <= poor ? '⚠' : '✗';
JUSTZIX.log('=== Web Vitals ===');
JUSTZIX.log(`LCP: ${vitals.LCP ?? '?'}ms ${status(vitals.LCP, 2500, 4000)} (Ziel <2.5s)`);
JUSTZIX.log(`CLS: ${vitals.CLS.toFixed(3)} ${status(vitals.CLS, 0.1, 0.25)} (Ziel <0.1)`);
JUSTZIX.log(`FCP: ${vitals.FCP ?? '?'}ms ${status(vitals.FCP, 1800, 3000)} (Ziel <1.8s)`);
JUSTZIX.log(`TTFB: ${vitals.TTFB ?? '?'}ms ${status(vitals.TTFB, 800, 1800)} (Ziel <800ms)`);
JUSTZIX.log(`INP: ${vitals.INP ?? '?'}ms ${status(vitals.INP, 200, 500)} (Ziel <200ms)`);
};
setTimeout(report, 5000);
window.addEventListener('beforeunload', report);
JUSTZIX.info(`[Vitals] Monitor aktiv für ${location.hostname}`);
Was du in der Output Console siehst
5 Sekunden nach dem Laden:
[INFO] [Vitals] Monitor aktiv für www.justzix.com
[LOG] === Web Vitals ===
[LOG] LCP: 1240ms ✓ (Ziel <2.5s)
[LOG] CLS: 0.024 ✓ (Ziel <0.1)
[LOG] FCP: 680ms ✓ (Ziel <1.8s)
[LOG] TTFB: 145ms ✓ (Ziel <800ms)
[LOG] INP: 85ms ✓ (Ziel <200ms)
Jede Metrik mit visuellem Status:
- ✓ = im guten Bereich (Googles „Good")
- ⚠ = im Bereich „Needs improvement"
- ✗ = im Bereich „Poor"
Anwendungsfall 1 — eigene Seite ohne Lighthouse auditieren
Klassiker: auf Staging deployen, den Tab öffnen, prüfen, ob die Web Vitals grün sind. Mit Lighthouse: 30 s Wartezeit. Mit JustZix: 5 s, und es meldet für jede weitere in dieser Sitzung besuchte Seite.
Anwendungsfall 2 — mit Mitbewerbern vergleichen
Besuche einen Mitbewerber. Die Output Console zeigt dessen LCP/CLS/INP. Deine Seite — 1:1-Vergleich, gleiche Netzwerkbedingungen, gleiches Gerät.
Anwendungsfall 3 — Live-Monitor während der Entwicklung
Snappe ein Output-Console-Pane an die rechte Seite. Starte deinen Localhost-Dev-Server. Jedes F5 → ein JUSTZIX.log mit frischen Vitals. Du siehst live, wie deine Änderungen wirken (z. B. Lazy-Load-Bild → LCP rauf, Layout-Shift → CLS rauf).
Anwendungsfall 4 — JSON-Export mit einer BUTTON-Aktion
// Aktion BUTTON „📊 Vitals exportieren"
const data = {
url: location.href,
timestamp: new Date().toISOString(),
vitals: window.JZ_LATEST_VITALS || {}
};
const json = JSON.stringify(data, null, 2);
navigator.clipboard.writeText(json);
JUSTZIX.log('Vitals in die Zwischenablage exportiert.');
Füge in der JS-Regel eine Zeile hinzu: window.JZ_LATEST_VITALS = vitals; nach jedem Update. Der BUTTON hat jetzt den aktuellen Snapshot zum Export in Doku / Slack.
Fallstricke
- LCP in Single-Page-Apps. SPA-Routenwechsel lösen keine neue LCP-Messung aus. Workaround: auf popstate-Events hören und die Observer zurücksetzen.
- CLS läuft nach dem Laden weiter. Seiten mit Lazy-Load-Bildern können den CLS stundenlang erhöhen. Finaler CLS = Wert beim Unload (beforeunload). Lighthouse stoppt die Messung nach 3-5 s.
- INP erfordert echte Interaktion. Eine statische Seite ohne Klicks → INP = null. Öffne die Seite + scrollen/klicken, bevor du die Metriken liest.
- TTFB = responseStart - requestStart, OHNE DNS/Connect. Voller TTFB ist
responseStart - fetchStart. Implementierungen variieren. - PerformanceObserver buffered: true — erfasst Events, die vor der Initialisierung des Observers passiert sind. Ohne das gehen Pre-Init-Einträge verloren.
Wie es weitergeht
- Output Console im Detail — wo JUSTZIX.log landet
- GTM ohne Devs debuggen — verwandtes Monitoring-Muster
- window.JZ + JUSTZIX — programmatische API
Installiere JustZix — ein Zero-Config-Web-Vitals-Monitor, der das Problem BEMERKT, bevor der Nutzer es tut.
Bewerte diesen Beitrag
Noch keine Bewertungen — sei der Erste.