Monitor Web Vitals nella scheda — LCP / CLS / INP nell'Output Console senza DevTools
I Web Vitals (LCP, CLS, INP) sono 3 metriche che Google usa come fattore di ranking SEO. Il modo standard di misurarli: Lighthouse nei DevTools — 30 secondi per audit, attivazione manuale. Alternativa: l'API PerformanceObserver integrata nei browser. Più una regola JS JustZix = un monitor passivo che riporta nell'Output Console per ogni pagina visitata. Perfetto per un controllo rapido dei propri progetti o per analizzare i concorrenti.
Regola JS — cattura completa dei Web Vitals
Scope: *://*/* oppure per dominio se vuoi monitorare solo i tuoi siti.
// Regola JS «Monitor Web Vitals»
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 });
// Report 5 secondi dopo il caricamento + all'unload (valori finali)
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)} (obiettivo <2.5s)`);
JUSTZIX.log(`CLS: ${vitals.CLS.toFixed(3)} ${status(vitals.CLS, 0.1, 0.25)} (obiettivo <0.1)`);
JUSTZIX.log(`FCP: ${vitals.FCP ?? '?'}ms ${status(vitals.FCP, 1800, 3000)} (obiettivo <1.8s)`);
JUSTZIX.log(`TTFB: ${vitals.TTFB ?? '?'}ms ${status(vitals.TTFB, 800, 1800)} (obiettivo <800ms)`);
JUSTZIX.log(`INP: ${vitals.INP ?? '?'}ms ${status(vitals.INP, 200, 500)} (obiettivo <200ms)`);
};
setTimeout(report, 5000);
window.addEventListener('beforeunload', report);
JUSTZIX.info(`[Vitals] Monitor attivo per ${location.hostname}`);
Cosa vedi nell'Output Console
5 secondi dopo il caricamento:
[INFO] [Vitals] Monitor attivo per www.justzix.com
[LOG] === Web Vitals ===
[LOG] LCP: 1240ms ✓ (obiettivo <2.5s)
[LOG] CLS: 0.024 ✓ (obiettivo <0.1)
[LOG] FCP: 680ms ✓ (obiettivo <1.8s)
[LOG] TTFB: 145ms ✓ (obiettivo <800ms)
[LOG] INP: 85ms ✓ (obiettivo <200ms)
Ogni metrica con uno stato visivo:
- ✓ = nell'intervallo buono (il «Good» di Google)
- ⚠ = nell'intervallo «Needs improvement»
- ✗ = nell'intervallo «Poor»
Caso d'uso 1 — fare l'audit del proprio sito senza Lighthouse
Classico: deploy su staging, apri la scheda, controlla se i Web Vitals sono verdi. Con Lighthouse: 30 s di attesa. Con JustZix: 5 s, e riporta per ogni pagina successiva visitata in quella sessione.
Caso d'uso 2 — confrontare con i concorrenti
Visita un concorrente. L'Output Console mostra i suoi LCP/CLS/INP. Il tuo sito — confronto 1:1, stesse condizioni di rete, stesso dispositivo.
Caso d'uso 3 — monitor dal vivo durante lo sviluppo
Snappa un pane Output Console sul lato destro. Avvia il tuo dev server localhost. Ogni F5 → un JUSTZIX.log con vitals fresche. Vedi dal vivo l'effetto delle tue modifiche (es. immagine lazy-load → LCP su, layout shift → CLS su).
Caso d'uso 4 — export JSON con un'azione PULSANTE
// Azione PULSANTE «📊 Esporta vitals»
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 esportate negli appunti.');
Nella regola JS aggiungi una riga: window.JZ_LATEST_VITALS = vitals; dopo ogni aggiornamento. Il PULSANTE ha ora lo snapshot corrente da esportare nella documentazione / Slack.
Trappole
- LCP nelle single-page app. I cambi di rotta SPA non attivano una nuova misurazione LCP. Workaround: ascolta gli eventi popstate e resetta gli observer.
- Il CLS continua dopo il caricamento. Le pagine con immagini lazy-load possono aumentare il CLS per ore. CLS finale = valore all'unload (beforeunload). Lighthouse smette di misurare dopo 3-5 s.
- L'INP richiede un'interazione reale. Una pagina statica senza clic → INP = null. Apri la pagina + scrolla/clicca prima di leggere le metriche.
- TTFB = responseStart - requestStart, SENZA DNS/connessione. Il TTFB completo è
responseStart - fetchStart. Le implementazioni variano. - PerformanceObserver buffered: true — cattura gli eventi avvenuti prima dell'inizializzazione dell'observer. Senza, le voci pre-init vanno perse.
Cosa fare dopo
- Output Console in dettaglio — dove atterra JUSTZIX.log
- Debug di GTM senza sviluppatori — pattern di monitoraggio gemello
- window.JZ + JUSTZIX — API programmatica
Installa JustZix — un monitor Web Vitals zero-config che NOTA il problema prima dell'utente.
Valuta questo articolo
Nessuna valutazione — sii il primo.