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):

  1. 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.
  2. 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.
  3. 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.
  4. 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:

html
<!-- 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à):

  1. Defer di tutto lo script che non serve subito - analytics, chatbot, pixel di tracciamento vari. Metti defer o async su tutti i tag script che non sono critici per il rendering.
  2. 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.
  3. Lazy load dei componenti pesanti - la chat di supporto in homepage può aspettare 2 secondi prima di caricarsi, credimi.
  4. 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:

html
<!-- 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):

  1. 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.
  2. Font web che si caricano tardi - usa font-display: swap o optional. Altrimenti il browser mostra prima il font di sistema, poi carica il tuo font custom e ricalcola tutto il layout. Due render = doppio shift.
  3. Banner/annunci dinamici - riserva sempre lo spazio con un placeholder CSS. Meglio un buco vuoto per 2 secondi che far saltare tutta la pagina.
  4. Contenuti caricati via JavaScript - se carichi contenuti dinamicamente, riserva lo spazio prima. Usa skeleton loaders o placeholder con altezza minima.

Implementazione pratica:

html
<!-- 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:

css
/* ✅ 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:

  1. Apro Search Console → Core Web Vitals
  2. Identifico le pagine peggiori (di solito homepage + pagine prodotto)
  3. Le testo su PageSpeed Insights + WebPageTest
  4. Faccio uno screenshot del "prima" per avere confronto dopo

Settimana 2-3 - fix:

  1. Inizio sempre dall'LCP (impatto maggiore)
  2. Poi CLS (spesso fix veloci)
  3. 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.