Settimana scorsa un cliente mi chiama disperato: "Il mio sito è sparito dalla prima pagina, eppure i contenuti sono perfetti". Apro Search Console e boom - tutti i Core Web Vitals in rosso. LCP a 4.8 secondi, CLS che salta ovunque come un grillo impazzito.
Due settimane dopo, stesso sito: LCP a 1.6s, CLS a 0.04, e il traffico organico aumentato del 130%. Non abbiamo toccato neanche una virgola del contenuto. Solo performance.
Ecco il punto: da quando Google ha inserito i Core Web Vitals nell'algoritmo (metà 2021), la velocità non è più "nice to have" - è un fattore di ranking vero e proprio. E non parlo di test sintetici fatti su Lighthouse dal tuo Mac super performante. Google prende i dati reali da milioni di utenti Chrome che visitano il tuo sito ogni giorno (field data). Se il tuo sito è lento per loro, sei fregato.
Le 3 metriche fondamentali dei Core Web Vitals
1. Largest Contentful Paint (LCP) - quanto ci metti a caricare?
Target: sotto 2.5 secondi (ma punta a 1.8s se vuoi stare tranquillo)
L'LCP è semplicemente quanto ci metti a mostrare il pezzo più grosso della pagina. Apri il tuo sito e cronometra: quando vedi l'immagine hero principale, o il titolo grande, o quel dannato video in cima? Quello è il tuo LCP.
Il problema classico che vedo sempre: immagine hero da 3.2MB perché il cliente ha caricato la foto direttamente dal telefono senza passare per un tool di compressione. Risultato? LCP di 4+ secondi anche con fibra.
La mia checklist di debug (in ordine di impatto):
- Immagini ottimizzate - converti tutto in WebP o AVIF. Un JPG da 800KB diventa un WebP da 120KB. Stessa qualità visiva, 85% di peso in meno. Lo faccio sempre con Squoosh o ImageOptim.
- Preload dell'hero image - metti
<link rel="preload" as="image" href="/hero.webp">nell'head. Così il browser la carica subito invece di scoprirla solo dopo aver parsato tutto il CSS. - CDN decente - se il tuo server è a Milano e un utente ti visita da Palermo, la latenza da sola può aggiungere 200-300ms. Cloudflare gratis risolve questo problema in 5 minuti.
- TTFB sotto i 600ms - se il server ci mette più di mezzo secondo solo per rispondere, hai un problema di backend/hosting. Spesso basta passare da un shared hosting scrauso a un VPS base per vedere miglioramenti del 70%.
Implementazione pratica:
<!-- Preload dell'immagine hero critica -->
<link rel="preload" href="/hero.webp" as="image">
<!-- Lazy loading per immagini below-the-fold -->
<img src="/image.webp" loading="lazy" width="800" height="600" alt="Descrizione immagine">
2. First Input Delay (FID) / Interaction to Next Paint (INP) - quando clicco, rispondi subito
Target INP: sotto 200ms (il FID è praticamente morto, Google usa l'INP dal marzo 2024)
Hai mai cliccato su un pulsante e il sito ha fatto finta di niente per 2 secondi? Ecco, quello è un INP di merda. Misura il tempo che passa tra quando l'utente fa qualcosa (click, tap, digitazione) e quando il browser risponde visivamente.
Il colpevole numero uno? JavaScript. Troppo JavaScript che blocca il main thread.
Esempio reale che ho debuggato la settimana scorsa:
Sito e-commerce, INP a 680ms. Apro Chrome DevTools → Performance → registro 6 secondi di interazione. Vedo un long task di 1.2 secondi causato da... Google Analytics che si caricava in modo sincrono insieme a 4 altri script di tracking. Fix: spostato tutto in defer, INP sceso a 140ms.
Come fixare (ordine di priorità):
- Defer di tutto lo script che non serve subito - analytics, chatbot, pixel di tracciamento vari. Metti
deferoasyncsu tutti i tag script che non sono critici per il rendering. - Code splitting - se hai un bundle JS da 800KB, è normale che il browser si impalli. Splitta il codice e carica solo quello che serve per la pagina corrente.
- Lazy load dei componenti pesanti - la chat di supporto in homepage può aspettare 2 secondi prima di caricarsi, credimi.
- Togli le librerie inutili - ho visto siti con jQuery + Lodash + Moment.js quando usavano 3 funzioni in totale. Rimpiazzale con vanilla JS moderno e risparmi 150KB.
Implementazione pratica:
<!-- Differimento di script analytics non critici -->
<script src="/analytics.js" defer></script>
<!-- Caricamento asincrono di librerie terze -->
<script async src="/third-party-lib.js"></script>
3. Cumulative Layout Shift (CLS) - smettila di saltare ovunque
Target: sotto 0.1 (ma sotto 0.05 è meglio)
Il CLS è la metrica più fastidiosa da debuggare ma anche la più importante per l'UX. Misura quanto la pagina "salta" mentre si carica.
Scenario classico: stai per cliccare su un link, improvvisamente salta giù un banner pubblicitario, e finisci per cliccare sull'annuncio invece che sul link. Oppure: stai leggendo un articolo, si carica un'immagine senza dimensioni predefinite, tutto il testo salta giù di 400px e perdi il punto in cui eri arrivato.
Il peggior caso che ho visto:
Sito di news, CLS a 0.87 (orribile). Il problema? Banner pubblicitari caricati asincronamente senza placeholder. Ogni 3 secondi si caricava un nuovo banner e il contenuto saltava su e giù come una molla. Gli utenti scappavano dopo 10 secondi.
Soluzione: riservato lo spazio fisso per i banner (anche vuoto) prima che si carichino. CLS sceso a 0.03 e bounce rate diminuito del 40%.
I 4 colpevoli principali del CLS (e come fixarli):
- Immagini senza dimensioni - SEMPRE metti width e height nell'HTML. Il browser può riservare lo spazio giusto prima che l'immagine si carichi. Se non lo fai, il browser non sa quanto spazio serve e quando l'immagine arriva, sposta tutto il resto.
- Font web che si caricano tardi - usa
font-display: swapooptional. Altrimenti il browser mostra prima il font di sistema, poi carica il tuo font custom e ricalcola tutto il layout. Due render = doppio shift. - Banner/annunci dinamici - riserva sempre lo spazio con un placeholder CSS. Meglio un buco vuoto per 2 secondi che far saltare tutta la pagina.
- Contenuti caricati via JavaScript - se carichi contenuti dinamicamente, riserva lo spazio prima. Usa skeleton loaders o placeholder con altezza minima.
Implementazione pratica:
<!-- Specifica width e height per prevenire layout shift -->
<img src="/logo.png" width="200" height="100" alt="Logo aziendale">
<!-- Font loading ottimizzato -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap">
CSS per animazioni performanti:
/* ✅ Performante - usa GPU acceleration */
.element {
transform: translateY(0);
transition: transform 0.3s ease;
}
.element:hover {
transform: translateY(-5px);
}
/* ❌ Causa reflow - evitare */
.element {
top: 0;
transition: top 0.3s ease;
}
Gli strumenti che uso davvero (senza stronzate)
Per misurare i dati reali:
- Google Search Console - vai su "Core Web Vitals" nella sidebar. Ti mostra i dati veri degli ultimi 28 giorni da utenti reali. Se è rosso lì, hai un problema vero.
- PageSpeed Insights - metti l'URL, scroll fino a "Field Data". Ignora i lab data per ora, guarda solo i dati reali.
Per debuggare:
- Chrome DevTools (tab Performance) - registro 6-10 secondi di caricamento pagina e vedo esattamente cosa rallenta. I long tasks sopra i 50ms sono i tuoi nemici.
- WebPageTest - quando voglio simulare connessioni 3G o vedere come si comporta il sito da New York invece che da Milano.
Pro tip: non ossessionarti con i punteggi di Lighthouse. Ho visto siti con 95/100 su Lighthouse che facevano schifo su field data perché erano testati da ufficio con fibra 1Gbps. I dati veri di Search Console sono quelli che contano.
Il mio processo step-by-step quando fisso un sito
Settimana 1 - diagnosi:
- Apro Search Console → Core Web Vitals
- Identifico le pagine peggiori (di solito homepage + pagine prodotto)
- Le testo su PageSpeed Insights + WebPageTest
- Faccio uno screenshot del "prima" per avere confronto dopo
Settimana 2-3 - fix:
- Inizio sempre dall'LCP (impatto maggiore)
- Poi CLS (spesso fix veloci)
- Infine INP (di solito richiede più tempo)
Settimana 4+ - monitoraggio: Aspetto che Google raccolga dati nuovi (ci vogliono ~28 giorni). Controllo Search Console ogni settimana. Se i numeri migliorano, continuo. Se no, torno al punto 3.
Errore comune: modificare 15 cose insieme e non sapere cosa ha funzionato. Fai UNA modifica alla volta, aspetta qualche giorno, misura. Rinse and repeat.
La verità sui Core Web Vitals
Guarda, non ti mentiamo: ottimizzare le performance è un lavoro continuo. Non è "fai una volta e via". Le cose cambiano - aggiungi nuove feature, carichi più script, i clienti vogliono quel banner animato figherrimo (che pesa 2MB).
Ma vale la pena? Assolutamente sì. Negli ultimi 2 anni ho visto:
- E-commerce passare da 2.1% a 3.8% di conversion rate solo fixando il CLS nel checkout
- Blog aumentare il tempo medio di permanenza da 1:20 a 3:45 dopo aver ottimizzato LCP
- Siti aziendali scalare dalla pagina 2 alla pagina 1 in 6 settimane (nessuna modifica ai contenuti)
Il punto è questo: Google premia chi fa le cose bene. Un sito veloce non è solo "nice to have" - è un vantaggio competitivo reale.
Se vuoi un check gratuito del tuo sito, prova PerSeo Insights. Ti fa una scansione completa e ti dice esattamente cosa fixare, in ordine di priorità. Poi sei liberə di implementare da solo o chiederci una mano.