Lazy loading e SEO: farlo bene senza bloccare Google

Lazy loading e SEO: farlo bene senza bloccare Google

Il lazy loading è una tecnica di ottimizzazione: invece di scaricare subito tutte le immagini, gli iframe o certi blocchi di contenuto, il browser rimanda il caricamento delle risorse non ancora visibili fino al momento in cui l'utente vi si avvicina scorrendo la pagina. Il vantaggio è reale — meno byte al primo caricamento, meno lavoro per il motore di rendering. Il rischio, altrettanto reale, è che una risorsa rimandata nel modo sbagliato non venga mai recuperata da chi non si comporta come un utente umano che scorre con il mouse o il dito. E Googlebot, quando renderizza una pagina, non scorre, non clicca e non muove il puntatore.

Questo articolo risponde a un problema preciso: come implementare il lazy loading — nativo o via JavaScript — di immagini, iframe e blocchi di contenuto in modo che Googlebot li veda comunque durante il rendering; perché la stessa tecnica non va mai applicata all'immagine che appare per prima, sopra la piega dello schermo; e come controllare se il contenuto rimandato è finito o no nella versione della pagina che Google indicizza. Non è un articolo sui Core Web Vitals o sul Cumulative Layout Shift, già coperti altrove su questo blog come effetto misurabile del lazy loading: qui la domanda è un'altra, il contenuto rimandato Google lo vede o no.

Che cosa succede tecnicamente quando rimandi un caricamento

Quando il browser incontra un tag immagine con l'attributo src valorizzato, il preload scanner — il componente che legge l'HTML ancora prima che sia interpretato del tutto — individua subito quella URL e avvia il download in parallelo al resto dell'analisi della pagina. È uno dei motivi per cui le pagine caricano le immagini così rapidamente.

Il lazy loading deve rompere deliberatamente questo meccanismo. Nella versione nativa, l'attributo loading impostato su lazy dice al browser: non trattare questa risorsa come le altre, decidi tu quando avvicinarti abbastanza da giustificare il download. Nella versione via JavaScript, la URL reale resta nascosta in un attributo che il browser non interpreta come riferimento da caricare — tipicamente data-src — finché uno script non la sposta al posto giusto.

In entrambi i casi, nell'HTML che arriva dal server prima di ogni esecuzione di script, la risorsa non è raggiungibile con un riferimento diretto. Chi legge solo quell'HTML grezzo — un vecchio scraper, un lettore RSS — non la vede affatto. Googlebot non è in questa categoria: renderizza le pagine con un motore basato su Chromium, il Web Rendering Service, eseguendo JavaScript come un browser reale. Il problema quindi non è se Google esegue gli script, ma se la loro logica è pensata per attivarsi anche senza un utente umano davanti allo schermo.

Lazy loading nativo: l'attributo loading

La soluzione più semplice, e nella maggior parte dei casi la più robusta, è l'attributo loading impostato su lazy sui tag immagine e iframe. Non richiede librerie esterne né JavaScript di terze parti che potrebbe fallire o venire bloccato, ed è supportata da tutti i browser moderni. Il browser stesso decide, con un margine che varia in base alla connessione rilevata, quando avviare il download.

Google ha dichiarato nella propria documentazione per sviluppatori che il Web Rendering Service riconosce e rispetta questo attributo come farebbe Chrome su un computer. Un dettaglio spesso trascurato: il renderer di Googlebot lavora con una finestra virtuale pensata apposta per intercettare la maggior parte dei contenuti differiti, così che le risorse con loading lazy finiscano comunque scaricate durante il rendering, senza che sia avvenuto uno scroll reale.

Non è una garanzia assoluta per ogni caso, motivo per cui più avanti trovi il metodo per verificarlo pagina per pagina invece di darlo per scontato. Vale la pena ricordare, senza dilungarsi, che ogni immagine dovrebbe comunque dichiarare le proprie dimensioni per evitare uno spostamento del layout quando la risorsa arriva: è un tema di layout, non di indicizzazione, già trattato nel post di questo blog sui dati CrUX e i Core Web Vitals.

Lazy loading via JavaScript: il metodo che fa la differenza

Ci sono casi in cui l'attributo nativo non basta: immagini di sfondo via CSS, caroselli personalizzati, blocchi interi di contenuto — non solo media — che un tema o un builder nasconde finché non si avvicinano al viewport. Qui la logica va scritta a mano, ed è qui che si gioca la differenza tra un'implementazione che Google vede e una che non vede.

Il metodo corretto è l'Intersection Observer API: si registra un osservatore su ogni elemento differito, e il browser notifica lo script quando quell'elemento entra — anche solo parzialmente, secondo la soglia configurata — in un'area di osservazione allargabile rispetto al viewport reale tramite l'opzione rootMargin. Alla notifica, lo script sposta subito la URL reale nell'attributo giusto o rimuove la classe che nasconde il blocco. Non serve alcuna azione dell'utente: l'osservatore si attiva anche se l'elemento entra nell'area osservata solo perché la pagina viene renderizzata con un viewport più ampio del normale, come accade nel rendering di Googlebot.

Il metodo sbagliato, ancora diffuso in librerie vecchie o scritte artigianalmente, è agganciare la rivelazione a eventi come scroll, resize o mousemove sulla finestra, spesso con un calcolo manuale della posizione tramite getBoundingClientRect. Google ha documentato che il proprio crawler non genera eventi di scroll, non muove un puntatore e non compie interazioni utente durante il rendering: se la logica dipende esclusivamente da quegli eventi, non si attiverà mai durante la visita di Googlebot, per quanto funzioni bene per un visitatore umano.

Una rete di sicurezza economica, e per questo spesso saltata, è un fallback — un tag noscript con la risorsa reale, o un elemento visibile di default che lo script nasconde solo dopo essersi caricato — che garantisce la presenza del contenuto anche se lo script fallisce, viene bloccato, o non fa in tempo a eseguirsi entro il budget che Google assegna al rendering di ogni pagina. Se la rivelazione dipende da una catena lunga di script di terze parti in sequenza, conviene accorciarla: più passaggi separano il caricamento dalla comparsa del contenuto, più cresce il rischio che il rendering venga interrotto prima che arrivi.

Iframe, video e mappe incorporate

L'attributo loading su lazy funziona, allo stesso modo, anche sui tag iframe: mappe incorporate, player video, widget di terze parti possono essere rimandati con la stessa sintassi usata per le immagini, con lo stesso beneficio in byte non trasferiti finché non servono.

C'è però una differenza concettuale: il documento dentro un iframe è una risorsa a sé, che Google può scansionare o meno indipendentemente dalla pagina che lo ospita. Rimandarne il caricamento non risolve — e non deve sostituire — la necessità di avere il testo importante per il posizionamento scritto nell'HTML della pagina stessa, non solo dentro il contenuto embeddato. Un indirizzo, un orario, una descrizione del prodotto mostrato nella mappa o nel video vanno scritti anche fuori dall'iframe, come testo normale.

Un caso specifico è il pattern della 'facciata': al posto di un iframe video pesante, un'immagine statica cliccabile carica il vero player solo dopo il clic, per risparmiare peso al primo caricamento. Ottima tecnica di performance, ma resta un contenuto che compare solo dopo un'azione che Googlebot non compie durante il rendering standard. Se l'obiettivo è che la pagina venga associata al video anche in ricerca, la descrizione testuale, il titolo e i dati strutturati vanno nell'HTML statico, non affidati solo al contenuto dietro il clic — il post di questo blog sulla SEO per i video approfondisce il markup specifico.

Perché non va usato sull'immagine sopra la piega

Qui arriva l'errore più comune, e il più controintuitivo: applicare loading lazy anche all'immagine principale, quella che appare per prima — spesso l'elemento più grande visibile nel primo riquadro, quello che di norma diventa il Largest Contentful Paint della pagina.

Il motivo per cui questo peggiora le cose sta nel meccanismo descritto all'inizio: loading lazy esclude deliberatamente la risorsa dal preload scanner, che normalmente avvia il download delle immagini visibili nell'HTML iniziale in parallelo al resto dell'analisi. Se quell'immagine è già dentro il viewport al primo caricamento, escluderla dal preload scanner non fa risparmiare nulla — non c'era scroll da aspettare — mentre aggiunge un ritardo, perché il browser deve prima valutare l'intersezione invece di partire subito come farebbe di default.

La regola pratica: qualunque cosa sia visibile su un tipico schermo mobile senza scorrere di un pixel non va marcata come lazy; tutto quello sotto quella linea è un candidato legittimo. Per l'immagine che probabilmente diventerà il Largest Contentful Paint, oltre a non rimandarla, ha senso valutare fetchpriority impostato su high, che segnala al browser di trattarla con priorità più alta rispetto alle altre risorse eager — un dettaglio distinto dal lazy loading, ma parte della stessa decisione su cosa deve arrivare per primo.

Come verificare che Google veda davvero il contenuto

La teoria si conferma o si smentisce con un test, non con un'ipotesi. Lo strumento più diretto è l'Ispezione URL dentro Search Console: dopo il test su una pagina, la scheda del risultato include un pulsante per visualizzare la pagina sottoposta a scansione. Nella sezione HTML di quella schermata si vede il DOM così come si è presentato dopo il rendering — cioè dopo che il JavaScript, incluso quello del lazy loading, ha già avuto la possibilità di girare.

Il controllo concreto consiste nel cercare, dentro quell'HTML renderizzato, la URL reale dell'immagine o il testo del blocco differito. Se l'attributo che il browser interpreta per il caricamento contiene già la URL vera, o il testo compare per intero invece che nascosto dietro una classe invisibile, quella logica si è attivata anche per Googlebot. Se nel DOM renderizzato trovi ancora solo il placeholder, o il testo risulta assente, quel contenuto non sta arrivando all'indice come pensavi.

La stessa schermata offre uno screenshot di come il renderer ha visualizzato la pagina: utile per capire in un colpo d'occhio se un embed è rimasto vuoto, prima ancora di scendere nel codice. Per pagine non ancora verificate su una proprietà di Search Console, uno strumento pubblico come il Test dei risultati multimediali offre un HTML renderizzato molto simile.

Un errore comune è fermarsi al codice sorgente originale del browser: mostra l'HTML come arriva dal server, prima di ogni script, quindi mostrerà sempre solo i placeholder. Non dice nulla su cosa vede Google — serve il DOM renderizzato, di Search Console o degli strumenti per sviluppatori dopo aver lasciato il tempo agli script di completare l'esecuzione.

Errori frequenti da evitare

Alcuni errori tornano con una regolarità sorprendente in siti che, sulla carta, hanno implementato il lazy loading correttamente per gli utenti umani ma non per il rendering che conta ai fini dell'indicizzazione.

  • Contenuto che compare solo dopo un clic reale — un accordion, una scheda 'leggi di più' caricata via richiesta separata — perché Googlebot non clicca durante il rendering standard, e quel testo resta fuori dall'indice.
  • Placeholder senza dimensioni dichiarate: l'assenza di larghezza, altezza o aspect-ratio provoca uno spostamento del layout quando il contenuto arriva, problema distinto ma collegato, già trattato nel post sui dati CrUX.
  • Librerie legate solo all'evento di scroll della finestra invece che all'Intersection Observer API: funzionano con un utente che scorre davvero, possono non attivarsi mai durante un rendering che non genera quell'evento.
  • Script del lazy loading bloccato dal file robots.txt: se Googlebot non può scaricarlo non può eseguirlo, e ogni elemento che dipende da esso resta nel suo stato iniziale nascosto, ai fini dell'indicizzazione.
  • Lazy loading su risorse che il layout richiede fin dal primo istante, come fogli di stile o font critici: la tecnica ha senso per media e contenuti accessori, non per ciò che la pagina non può fare a meno di avere subito.
  • Fallback mancante dal placeholder all'attributo reale per i casi in cui lo script di terze parti non si carica affatto, lasciando utente e crawler davanti a un buco vuoto invece che a un contenuto presente.

Un controllo per template, non per ogni singola pagina

Se il componente di lazy loading è lo stesso su tutte le pagine che condividono un tema o un builder — la stessa galleria immagini, lo stesso carosello, lo stesso embed di mappa — non serve ripetere l'ispezione URL su ogni pagina del sito. Basta verificarlo a fondo su una pagina rappresentativa di ciascun modello di pagina che lo utilizza, e ripetere il controllo solo dopo un aggiornamento del componente stesso, di un tema, o del builder che lo genera. È lo stesso ragionamento che si applica a qualunque elemento tecnico condiviso: il problema, quando c'è, non è mai isolato a una pagina, ed è lì che vale la pena mettere il tempo di verifica.

Domande frequenti

Il lazy loading nativo (loading impostato su lazy) basta da solo per la SEO?

Nella maggior parte dei casi sì, per immagini e iframe: Google supporta l'attributo nativamente e i browser moderni lo gestiscono senza bisogno di JavaScript aggiuntivo. Resta comunque buona pratica dichiarare le dimensioni dell'elemento e verificare il risultato con l'Ispezione URL, perché il momento esatto in cui il browser avvia il caricamento può variare.

Perché un'immagine lazy sopra la piega peggiora le prestazioni invece di migliorarle?

Perché l'attributo esclude quell'immagine dal preload scanner del browser, che normalmente avvia il download delle risorse visibili nell'HTML iniziale in parallelo al resto dell'analisi della pagina. Se l'immagine è già visibile al primo caricamento, escluderla da quel meccanismo aggiunge un ritardo invece di eliminarne uno.

Il lazy loading di blocchi di testo, non solo di immagini, è più rischioso per l'indicizzazione?

Sì, perché un testo mancante nel DOM renderizzato non lascia un segnaposto visibile come quello di un'immagine non ancora caricata. Se la logica che lo rivela dipende da un'azione che Googlebot non compie, come uno scroll reale o un clic, quel testo può non comparire mai nella versione della pagina che viene indicizzata.

Come si controlla rapidamente un sito con molte pagine che usano lo stesso lazy loading?

Se il componente è identico su tutto il sito, verificarne il comportamento con l'Ispezione URL su una pagina rappresentativa per ogni modello di pagina è generalmente sufficiente. Ha senso ripetere il controllo solo dopo un aggiornamento del componente, del tema o dello script che lo gestisce.

Aggiornato: 17 ottobre 2026

Tutti gli articoli