Join our community of websites already using SEOJuice to automate the boring SEO work.
See what our customers say and learn about sustainable SEO that drives long-term growth.
Explore the blog →TL;DR: La SEO per SPA non è più un problema di rendering, ma di delivery: URL, codici di stato, metadati e contenuto principale devono esistere prima che JavaScript entri in gioco, perché Google potrebbe renderizzare in ritardo e i crawler basati su AI spesso non renderizzano affatto.
La maggior parte dei consigli sull’SEO per SPA parte ancora dalla domanda sbagliata: Google riesce a renderizzare JavaScript?
Sì. Google sa renderizzare JavaScript. Martin Splitt lo ripete da anni, eppure molti continuano a fare debug delle SPA guardando view-source: come se fosse la pagina che Google ha indicizzato.
«Molte persone continuano a guardare il sorgente. Non è quello che usiamo per l’indicizzazione. Noi usiamo l’HTML renderizzato.»
Martin Splitt, Developer Advocate @ Google
Questa citazione conta perché smonta una cattiva abitudine. Se controlli solo il sorgente iniziale di un’app React, Vue, Angular, SvelteKit, Nuxt, Remix o Next.js, rischi di perdere ciò che Google vede davvero. Il DOM renderizzato fa la differenza.
Ma questo non significa che il rendering lato client sia sicuro per ogni route pubblica. Renderizzare costa tempo, può fallire e può avvenire dopo la scansione. Altri bot potrebbero non renderizzare mai. La vera domanda per lo spa seo è se il crawler riceve un documento significativo abbastanza presto.
“View source” mostra la prima risposta HTML. In una classica app CSR, quella risposta può essere un guscio vuoto, un nodo radice, un bundle di script e una preghiera. Google potrebbe renderizzare la pagina più tardi, eseguire la route, chiamare le API e scoprire il contenuto reale. Forse.
Quel «forse» è dove i ranking diventano strani. La pagina può sembrare perfetta nel tuo browser e risultare fragile per la ricerca: il browser è paziente, i crawler sono sistemi con code, budget, timeout e modalità di errore.
seojuice.io è diviso di proposito: le pagine pubbliche consegnano HTML statico first, la dashboard dopo il login si comporta da app. Due strategie di rendering sotto un solo dominio, perché quelle route hanno compiti diversi.
Blog, strumenti e landing page devono essere trovati, scansionati, compresi, condivisi e citati. La dashboard non deve posizionarsi per “interfaccia valutazione salute pagina” e mai lo farà. JavaScript può migliorare la pagina pubblica dopo il caricamento, ma la prima risposta deve già sembrare una pagina.
Per anni ho trattato il problema come se riguardasse solo Google (mi sbagliavo). Poi i crawler AI hanno reso il vecchio shortcut ancora peggiore.
«I risultati mostrano con coerenza che nessuno dei principali crawler AI attualmente renderizza JavaScript.»
Vercel Engineering
Se GPTBot, ClaudeBot, PerplexityBot o un altro crawler vede solo un app shell, per quella superficie il tuo contenuto è come se non esistesse. Il supporto al rendering di Google aiuta Google (e solo Google): non salva ogni crawler, bot di anteprima, strumento di monitoraggio, parser social o sistema di ingestione AI.
È lo step che la maggior parte dei team salta. Chiedono se l’intera SPA abbia bisogno di SSR. Quel frame spreca tempo di engineering.
Una vera SPA mescola quasi sempre due cose: pagine indicizzabili e stati dell’app privati. Pagine prezzi, post del blog, documentazione, template, integrazioni, pagine di confronto e landing di prodotto sono pagine. Dashboard, step di onboarding, modali, filtri, schermate account e report salvati sono stati dell’app.
La correzione parte dalla classificazione. Non chiedere agli sviluppatori di «sistemare la SEO dell’app». Chiedi di segnare quali route meritano traffico di ricerca, poi scegli rendering, indicizzazione, canonical e codici di stato per ciascuna route.
| Tipo di route | Dovrebbe posizionarsi? | Scelta di rendering | Regola di indicizzazione |
|---|---|---|---|
| Post del blog | Sì | SSG o SSR | Index, canonical self |
| Landing di prodotto | Sì | SSG o SSR | Index, canonical self |
| Pagina di risultati di ricerca | Di solito no | CSR o SSR | Spesso noindex |
| Route dashboard | No | CSR va bene | Bloccata dietro auth o noindex |
| URL con filtro facet | A volte | SSR solo se curato | Canonical o noindex |
Così lo spiego in un audit SEO tecnico. Una SPA con 40 URL pubblici e 4 000 stati di dashboard non ha 4 040 pagine SEO. Ha 40 pagine e un’interfaccia di prodotto.
Questa distinzione cambia la roadmap. Le route pubbliche hanno bisogno di URL stabili, canonical self, metadati consegnati dal server, link crawlable, HTML utile al primo byte e codici di stato corretti. Le route di dashboard richiedono interazione veloce, auth, gestione stato e privacy. Forzare entrambi i gruppi in un solo modello di rendering di solito peggiora entrambi.
Da mindnow era l’errore SPA più comune che vedevo nei progetti cliente. Il team voleva un’unica architettura frontend elegante. La search voleva documenti noiosi. Il compromesso non era abbandonare l’app, ma smettere di fingere che ogni route avesse lo stesso scopo.
La strategia di rendering è una scelta architetturale, non un flag in un plugin SEO: se scegli il modello sbagliato, ogni ticket successivo diventa una patch.
Il rendering lato client va benissimo per schermate software autenticate. Se l’utente deve fare login, i crawler non dovrebbero indicizzare la route comunque. Il CSR diventa rischioso quando lo stesso shell serve pagine prezzi, documenti, articoli e pagine prodotto dove il contenuto appare solo dopo che JavaScript gira e le API rispondono.
La generazione statica crea le pagine in HTML prima del tempo (di solito in fase di build o deploy). Per blog, documentazione, changelog, pagine glossario, template e gran parte del marketing, l’SSG è imbattibile: veloce, cache-able, economico e amico dei crawler.
Il rendering lato server è più adatto quando il contenuto pubblico varia per richiesta, geografia, inventario, permessi o freschezza. Lee Robinson ha descritto il modello Next.js in modo semplice:
«Next.js pre-renderizza la pagina in HTML sul server a ogni richiesta.»
Lee Robinson, VP Developer Experience @ Vercel
L’SSR dà ai crawler HTML senza aspettare il bundle client, pur riflettendo dati freschi.
L’Incremental Static Regeneration (pagine statiche aggiornate dopo la pubblicazione) è spesso il miglior compromesso per grandi library di contenuti. Ottieni HTML statico per la maggior parte delle richieste e rigenerazione quando il contenuto cambia. Per SEO programmatico, docs e grandi librerie di template, l’ISR evita rebuild infiniti senza tornare al CSR completo.
Il rendering dinamico serve una versione ai crawler e un’altra agli utenti. Può salvare una SPA legacy quando la migrazione non è pronta — ma non disegnerei una nuova strategia search basandomi su di esso.
«Lo vedrei come un workaround temporaneo – dove temporaneo può voler dire un paio d’anni – ma resta una soluzione a tempo.»
John Mueller, Search Advocate @ Google
È il modello mentale giusto. Usa il rendering dinamico quando serve un ponte, poi sostituisci il ponte con route pubbliche server-rendered o static-first.
I veri fallimenti SPA SEO sono di solito noiosi. Non sono misteriose penalizzazioni di ranking, ma bug di delivery.
La prima trappola è lo shell universale. Ogni URL restituisce la stessa risposta 200, lo stesso nodo vuoto e lo stesso bundle. Il router decide dopo se /pricing, /docs/api o /totally-fake-url esistano. Costringe i crawler a lavorare troppo e crea la seconda trappola: i soft 404.
«Invece di restituire 404, risponde con 200 … mostrando sempre una pagina basata sull’esecuzione JavaScript.»
Martin Splitt, Developer Advocate @ Google
Le route non valide dovrebbero restituire veri 404 o 410. Un carino componente “page not found” lato client servito con 200 è comunque un cattivo segnale (è la trappola soft 404 che divora il budget di indicizzazione).
La terza trappola è la navigazione che i crawler non possono seguire. Bottoni, click handler, componenti custom e eventi del router vanno bene per l’interazione, ma la scoperta interna ha ancora bisogno di anchor crawlable con veri attributi href. Se le tue pagine più importanti sono raggiungibili solo dopo un click JavaScript, la crawlabilità è più debole di quanto sembri.
I metadati sono un altro punto critico. Molte SPA aggiornano titoli, descrizioni, canonical, tag robots, Open Graph e schema dopo i cambi di route. In un browser funziona visivamente, ma può fallire per crawler, parser social e bot AI. I metadati specifici di route devono essere presenti nell’HTML restituito per ogni URL indicizzabile.
I canonical meritano un avviso a parte. Ho visto app idratate sovrascrivere un canonical corretto con un dominio di staging, un URL root o la route precedente. Questi bug sono silenziosi. Nessuno se ne accorge finché gli URL duplicati non si raggruppano male o inizia a posizionarsi la pagina sbagliata.
L’infinite scroll è un’altra trappola quando nasconde contenuto dietro stato client. Se pagina due, tre e gli item più vecchi non hanno URL crawlable, i motori di ricerca potrebbero non scoprirli mai. Usa URL paginati di fallback per archivi e categorie importanti.
Contenuto principale caricato via API è fragile. Se H1, corpo, dettagli prodotto, recensioni o link interni richiedono due chiamate API dopo l’hydration, hai più punti di fallimento. Il traffico bot può colpire rate-limit. Le API possono bloccare user-agent sconosciuti. Timeout possono lasciare il DOM renderizzato scarno.
Il routing con hash dovrebbe restare fuori dalle pagine pubbliche indicizzabili. Un URL tipo /docs#pricing va bene per i frammenti, ma l’hash-routing per pagine reali complica discovery, canonical e analytics.
Infine, occhio ad auth e peso del bundle insieme. Contenuto pubblico avvolto per errore da check login può sparire dai crawler. Bundle pesanti possono ritardare il rendering e sprecare budget. Entrambi i problemi sembrano “JavaScript SEO”, ma la soluzione pratica è confini di route più puliti e meno lavoro client per le pagine pubbliche.
La miglior regola SPA SEO che conosca è semplice: se la route merita traffico di ricerca, la prima risposta deve sembrare una pagina.
Ciò significa che ogni URL pubblico deve restituire HTML utile con i segnali core già presenti:
<title> corretto;
Poi JavaScript può idratare componenti, personalizzare elementi, caricare calcolatori, tracciare eventi, filtrare tabelle e arricchire l’esperienza. Non dovrebbe essere necessario perché il crawler capisca di cosa parla la pagina.
Qui si incontrano architettura del sito e SPA SEO. Una route pubblica senza link crawlable che puntino a essa è comunque debole, anche se è server-rendered. Un documento perfettamente renderizzato ma sepolto a cinque click dietro navigazione client-only non performa come una pagina collegata da una rete interna chiara.
La regola document-first mantiene onesti i team. Pricing è un documento. Un post del blog è un documento. Una pagina docs è un documento. Un filtro dashboard salvato, un modal aperto o uno step di onboarding sono stati dell’app. Trattare lo stato dell’app come pagina search crea bloat d’indice. Trattare le pagine pubbliche come stato dell’app crea invisibilità.
Su seojuice.io questa divisione è intenzionale. Le route pubbliche devono essere abbastanza noiose per i crawler. Il prodotto può restare interattivo dopo il login. Le due idee possono convivere.
Se testi solo l’esperienza browser, stai testando il percorso più felice. La SEO per SPA ha bisogno di test più scomodi.
curl -I https://example.com/missing-route.Il test scomodo è quello dell’H1. Se Googlebot ha bisogno di cinque step e due chiamate API per trovare l’H1, la pagina è fragile anche se alla fine viene indicizzata.
Screaming Frog, Sitebulb, Google Search Console, Chrome DevTools, Rich Results Test e log server aiutano tutti. Lo strumento specifico conta meno del confronto: vuoi sapere cosa esiste alla prima risposta, cosa appare dopo il rendering e cosa Google ha effettivamente indicizzato.
Qui molti audit JavaScript SEO si fermano troppo presto: dimostrano che Google può renderizzare una pagina. Bene. Ora testa route non valide, paginazione, cambi canonical, cambi metadata, fail API, risposte lente e crawler non-Google.
Usa questa checklist a livello di route. Un “pass” globale nasconde troppi fallimenti SPA.
404 o 410, non 200.href reali.«Se non viene scansionato, non può essere mostrato in search. Qualsiasi sia la surface.»
Jamie Indigo, Technical SEO Consultant @ Not a Robot
Quella frase è l’intera checklist compressa in una riga. Search, risposte AI, anteprime link e sistemi di discovery dipendono prima dall’accesso. Il ranking viene dopo.
Se partissi oggi con una SPA moderna pensando al traffico search, non renderei server-rendered l’intero prodotto. Lo dividerei.
| Area del sito | Approccio consigliato |
|---|---|
| Sito marketing | Generazione statica |
| Blog e docs | Generazione statica o ISR |
| Pagine prodotto | SSR o ISR |
| Pagine SEO programmatiche | Generazione statica con forte pruning |
| Dashboard | CSR dietro auth |
| Pagine search e filtro | Noindex a meno che curate manualmente |
| Route non valide | Vere 404 o 410 |
| Layout condiviso | Metadati e navigazione server-rendered |
Così lo dividerei su seojuice.io. Le pagine marketing e gli articoli devono essere HTML-first. Le superfici di prodotto che richiedono freschezza possono usare SSR o ISR. La dashboard può restare app-like perché posizionarla sarebbe inutile.
Le pagine SEO programmatiche richiedono disciplina extra. La generazione statica rende facile creare migliaia di pagine, incluse migliaia che nessuno dovrebbe indicizzare. Genera solo pagine con reale domanda di ricerca, contenuto utile e link interni. Pota il resto prima che Google debba decidere al posto tuo.
La SPA vincente non è quella che dimostra che i crawler possono eseguire JavaScript. È quella che non costringe i crawler a fare lavoro inutile.
Sì. Una SPA può posizionarsi se le route indicizzabili restituiscono contenuto crawlable, metadati corretti, link interni e codici di stato validi. Google sa renderizzare JavaScript, ma affidarsi al rendering per tutto rende il sito più fragile.
No, non per ogni route. L’SSR è utile per pagine pubbliche con contenuto che cambia. L’SSG o l’ISR sono spesso migliori per contenuti stabili. Il CSR va bene per dashboard private, schermate account e stati app che non dovrebbero essere indicizzati.
I route con hash sono una scelta povera per pagine indicizzabili. Possono andare bene per frammenti on-page, ma il contenuto pubblico dovrebbe avere URL puliti, metadati specifici di route e codici di stato a livello server.
Di solito no. Le pagine di ricerca interne e i filtri facet spesso generano URL sottili o duplicati. Pagine filtro curate possono essere indicizzate quando hanno domanda unica, contenuto stabile e una chiara strategia canonical.
Richiedi un URL fittizio e controlla il codice di stato. Se /questa-pagina-non-dovrebbe-esistere restituisce 200 con un messaggio client-side “not found”, hai un rischio soft 404.
SEOJuice aiuta i team a rafforzare i link interni crawlable sulle pagine pubbliche che meritano davvero traffico search. Se la tua SPA ha route orfane, template sepolti o pagine che Google sembra non raggiungere mai, l’automazione del linking interno può rendere più semplice per i crawler seguire il layer documento.
no credit card required