SEO delle applicazioni SPA: perché le SPA non si posizionano, come SSR, generazione statica e prerendering risolvono il problema e come farsi leggere dalle IA.

In breve
un'applicazione a pagina singola (SPA, dall'inglese single page application) carica un unico scheletro HTML e costruisce ogni vista con JavaScript nel browser. Google sa eseguire il rendering del JavaScript, ma lo fa in differita e in modo fragile, e i crawler di ChatGPT, Claude e Perplexity non lo eseguono affatto. Per posizionarsi ed essere citata, ogni vista di una SPA ha bisogno di un proprio URL, di un vero link con href, di un titolo e una descrizione unici, di un codice di stato corretto e, soprattutto, del suo contenuto principale presente nell'HTML inviato dal server, tramite rendering lato server, generazione statica o prerendering.
Vuoi approfondire? Chiedi a
La SEO delle applicazioni SPA è l'insieme delle tecniche che rendono un'app JavaScript costruita con React, Vue, Angular o Svelte facile da scansionare quanto un sito classico. Il problema è ben documentato: Google spiega nelle sue nozioni di base sulla SEO per JavaScript che elabora le pagine JavaScript in tre fasi (scansione, rendering, indicizzazione), e ogni punto debole di una SPA si trova da qualche parte in questa catena. Questa guida si concentra sulle SPA; per i siti JavaScript in generale, legga la nostra guida alla SEO per JavaScript.
Un sito tradizionale restituisce un documento HTML completo per ogni URL. Una SPA restituisce quasi lo stesso documento per tutti gli URL: un <div id="root"> vuoto, qualche meta tag e un grosso bundle JavaScript. Il browser scarica il bundle, chiama un'API e poi disegna la pagina. Quando il visitatore clicca su un link, il JavaScript sostituisce il contenuto senza ricaricare.
Per una persona con uno smartphone veloce, il risultato sembra istantaneo. Per un crawler, la prima risposta è uno scheletro vuoto: nessun titolo, nessun testo, nessun link. Tutto dipende dal fatto che il bot esegua il JavaScript, e da quando lo fa. Questo solo fatto spiega la maggior parte dei problemi SEO delle SPA:
/#/pricing), e la parte dopo il # non viene mai inviata al server, quindi tutte le viste si riducono a un unico URL.<title> e, se il router non lo aggiorna, tutte le pagine lo condividono.href: pulsanti e gestori onClick fanno navigare gli utenti ma non danno ai crawler nulla da seguire.Googlebot recupera prima l'HTML grezzo e legge i link e le direttive che vi trova. Le pagine che restituiscono uno stato 200 vengono poi messe in coda per il Web Rendering Service, un Chromium headless. Google afferma che una pagina «potrebbe rimanere in questa coda per pochi secondi, ma può volerci anche più tempo». Dopo il rendering, l'HTML ottenuto viene analizzato di nuovo per contenuti e link, quindi indicizzato.
Quattro dettagli della documentazione di Google contano per le SPA:
<a> con un href sono link affidabili. I link inseriti tramite JavaScript vanno bene purché rispettino questo formato.pushState) invece delle route con #. Ha dismesso il suo vecchio schema di scansione AJAX (gli URL con #!) nell'ottobre 2015.noindex nell'HTML originale ha la precedenza. Google può saltare il rendering quando vede noindex, quindi rimuoverlo dopo con JavaScript non funziona.La conseguenza è diretta: Google può indicizzare una SPA con rendering lato client, ma lei aggiunge a ogni pagina un secondo passaggio, un ritardo e un punto di errore. Un timeout, una chiamata API bloccata o un errore JavaScript durante il rendering lasciano vuota la versione indicizzata. Verifichi ciò che vede Google con lo strumento Controllo URL di Search Console e legga la nostra guida su come funziona l'indicizzazione di Google se alcune pagine restano fuori dall'indice.
Per lo più no. In uno studio pubblicato a dicembre 2024 sul traffico della propria rete, Vercel e MERJ hanno rilevato che «nessuno dei principali crawler di IA esegue attualmente il rendering del JavaScript»: GPTBot, OAI-SearchBot e ChatGPT-User (OpenAI), ClaudeBot (Anthropic), PerplexityBot, Meta-ExternalAgent e Bytespider leggono tutti solo l'HTML grezzo. Scaricano sì i file JavaScript (circa l'11,5% delle richieste di ChatGPT e il 23,8% di quelle di Claude), ma non li eseguono. Le eccezioni sono Gemini, che si appoggia all'infrastruttura di rendering di Google, e AppleBot, che usa un crawler basato su browser.
Per una SPA con rendering lato client, questo significa che i crawler di IA che alimentano ChatGPT, Claude e Perplexity vedono una pagina vuota. Il suo prodotto può posizionarsi su Google e restare invisibile nelle risposte delle IA, perché l'assistente non ne ha mai letto una parola. Lo stesso vale per la maggior parte dei bot di anteprima dei link dei social network e delle app di messaggistica, che leggono i tag Open Graph nell'HTML grezzo. Una volta che il contenuto è nell'HTML, verifichi anche che il suo robots.txt consenta l'accesso ai crawler di IA che desidera.
La soluzione è inviare HTML reale fin dalla prima risposta. Nella sua documentazione sul rendering dinamico, Google definisce il rendering dinamico (servire una versione prerenderizzata solo ai bot) «una soluzione temporanea» che non raccomanda, e indica invece il rendering lato server, il rendering statico o l'idratazione. Le definizioni che seguono riprendono il riferimento Rendering on the Web di web.dev.
| Strategia | Come funziona | Contenuto nel primo HTML | Ideale per | Limiti |
|---|---|---|---|---|
| Rendering lato client (CSR) | Il browser costruisce la pagina a partire da JavaScript e da un'API | No | Dashboard e pagine dietro un login | Indicizzazione ritardata su Google, invisibile per la maggior parte dei crawler di IA |
| Rendering lato server (SSR) | Il server genera l'HTML a ogni richiesta, poi il JavaScript lo idrata | Sì | Cataloghi, annunci, contenuti che cambiano spesso o personalizzati | Costo del server, tempo di risposta più lento senza cache |
| Generazione statica (SSG) | L'HTML viene generato in fase di build per ogni URL e servito da una CDN | Sì | Pagine marketing, blog, documentazione, landing page | Serve una nuova build quando il contenuto cambia (esistono opzioni incrementali) |
| Prerendering in fase di build | Un browser headless cattura lo stato iniziale di ogni route come HTML statico | Sì | SPA esistenti con un numero limitato di route pubbliche | Dati congelati al momento della build, le route vanno elencate |
| Rendering dinamico | I bot ricevono uno snapshot prerenderizzato, gli utenti la SPA | Sì, solo per i bot elencati | Soluzione temporanea per un'applicazione datata | Ufficialmente una soluzione temporanea, costi di manutenzione, rischio di servire ai bot contenuti diversi |
La maggior parte dei framework moderni permette di combinare le strategie per route: statico per le pagine marketing, rendering lato server per il catalogo, rendering lato client per l'area riservata. Questa configurazione ibrida fornisce ai crawler HTML completo dove arriva il traffico di ricerca e mantiene l'esperienza SPA dove porta valore.
| Libreria | Framework o funzionalità per avere HTML al primo caricamento |
|---|---|
| React | Next.js (server component, SSR e generazione statica), React Router in modalità framework, Gatsby |
| Vue | Nuxt (rendering universale di default, generazione statica disponibile) |
| Angular | Angular SSR (rendering lato server e prerendering in fase di build) |
| Svelte | SvelteKit (rendering lato server di default, prerendering per route) |
| Tutte | Astro (HTML statico di default, isole interattive caricate solo dove servono) |
I siti generati dai website builder basati sull'IA meritano una menzione a parte: molti esportano un'app React con rendering lato client. Se ha creato il suo sito con uno di questi strumenti, consulti le nostre note su SEO e GEO con Lovable prima di dare per scontato che Google e ChatGPT possano leggerlo.
Usi la History API (/pricing, mai /#/pricing), un URL per ogni contenuto e lo stesso URL sia che il visitatore arrivi direttamente sia che navighi all'interno dell'app. Ogni URL deve caricare il contenuto giusto quando viene aperto in una nuova scheda: è il test che esegue un crawler.
Ogni elemento di navigazione che porta a una pagina indicizzabile dovrebbe essere un <a href="/path">. I componenti link dei framework (Link, NuxtLink, routerLink) producono questo markup; i gestori di clic personalizzati su elementi div o button no. I buoni link sostengono anche l'architettura del sito: se una pagina non riceve link, i crawler la trovano di rado.
Ogni route ha bisogno di un proprio title, una meta description, un canonical e dei tag Open Graph, generati sul server quando possibile. La nostra pagina sui meta tag elenca cosa impostare. Mantenga un solo tag canonical: Google consiglia di impostarlo nell'HTML e, se il JavaScript lo modifica, il risultato non deve contraddire l'originale.
I prodotti mancanti e gli articoli eliminati non devono rispondere 200 con un messaggio di errore. Con l'SSR, restituisca un vero 404 o 410 dal server. In una SPA pura, Google accetta due soluzioni di ripiego: reindirizzare con JavaScript verso un URL che restituisce 404, oppure aggiungere alla vista di errore un meta tag robots noindex.
Titoli, testo, prezzi, FAQ e dati strutturati JSON-LD dovrebbero trovarsi nella risposta del server, non essere caricati dopo un clic o uno scroll. Il contenuto nascosto dietro schede renderizzate su richiesta, o dietro pulsanti «Carica altro», viene spesso perso.
Suddivida il bundle per route, rimandi ciò che non serve alla prima vista ed eviti di eseguire di nuovo il rendering dell'intera pagina durante l'idratazione. Tenga presente che i dati sul campo di Chrome (CrUX) attribuiscono le metriche delle navigazioni interne all'app all'URL caricato per primo dal visitatore, quindi testi i suoi template principali uno per uno.
Confronti tre versioni di ogni template principale: l'HTML grezzo (guardi il codice sorgente o recuperi la pagina con uno strumento da riga di comando), l'HTML renderizzato da Google (Controllo URL, poi «Visualizza pagina sottoposta a scansione») e la pagina con il JavaScript disattivato. Se il testo principale compare solo nella seconda versione, i crawler di IA non lo vedono. Il nostro audit di scansionabilità per le IA gratuito e il verificatore di indicizzabilità eseguono questi controlli su qualsiasi URL.
| Sintomo | Causa probabile | Soluzione |
|---|---|---|
| Search Console mostra molte pagine «Scansionata, ma attualmente non indicizzata» | HTML vuoto o quasi identico prima del rendering | SSR, SSG o prerendering per le route pubbliche |
Tutti i risultati di una ricerca site: mostrano lo stesso titolo | Titolo non aggiornato per route | Gestione dell'head per route sul server |
| Solo la home page è indicizzata | Routing con hash o link senza href | History API e veri link <a> |
| Le pagine di errore compaiono nell'indice | Soft 404 (stato 200 ovunque) | 404 dal server, reindirizzamento JavaScript verso un URL 404 oppure noindex |
| Si posiziona su Google ma non viene mai citato da ChatGPT o Perplexity | Contenuto visibile solo dopo l'esecuzione del JavaScript | Contenuto nella prima risposta HTML |
| Contenuti vecchi nella vista renderizzata di Google | File JavaScript o CSS in cache | Nomi di file con impronta |
Per anni il rendering lato client è stato un rischio gestibile, perché prima o poi Google eseguiva il rendering del JavaScript. Ora che parte della scoperta avviene in ChatGPT, Claude, Gemini e Perplexity, il costo è cambiato: una pagina che esiste solo dopo l'esecuzione del JavaScript è assente dalle fonti che la maggior parte degli assistenti può leggere. La scansionabilità nell'HTML grezzo è diventata la prima condizione dell'ottimizzazione per i motori generativi (GEO).
Una volta completo l'HTML, il resto segue le regole consuete: le pagine che rispondono chiaramente a una domanda, con fatti documentati e dati strutturati, sono quelle che gli assistenti citano. Le funzionalità di ottimizzazione GEO di Sorank la aiutano a scrivere e pubblicare questi contenuti, e il monitoraggio delle menzioni nelle IA mostra se ChatGPT, Claude e Gemini citano il suo marchio dopo la correzione del rendering.
La regola chiave della SEO delle applicazioni SPA sta in una frase: tutto ciò che vuole far posizionare da Google e far citare dalle IA deve trovarsi nell'HTML inviato dal server. Usi la SPA per l'area riservata agli utenti connessi, esegua il rendering delle pagine pubbliche sul server o in fase di build, poi verifichi cosa ricevono i bot prima e dopo ogni rilascio.
Google non penalizza un'applicazione a pagina singola, ma la sua configurazione predefinita, il rendering lato client con un unico scheletro HTML, rende l'indicizzazione più lenta e meno affidabile. La maggior parte dei crawler di IA non esegue il JavaScript, quindi vede una pagina vuota. Con il rendering lato server, la generazione statica o il prerendering sulle route pubbliche, una SPA può posizionarsi bene quanto qualsiasi sito classico.
React in sé è neutro: conta dove viene prodotto l'HTML. Un'app React renderizzata solo nel browser ha i classici problemi delle SPA, mentre gli stessi componenti renderizzati sul server con Next.js o React Router in modalità framework forniscono HTML completo ai crawler. Scelga un framework che supporti il rendering lato server o statico per le pagine che vuole far indicizzare.
Solo come misura temporanea. Google descrive il rendering dinamico come una soluzione temporanea che non raccomanda, perché mantenere una versione separata per i bot aggiunge costi e rischi. Il rendering lato server, la generazione statica o il prerendering in fase di build forniscono lo stesso HTML a tutti i visitatori e sono le soluzioni a lungo termine.
HANNO PROVATO SORANK PRIMA DI TE
