SEO de aplicações SPA: por que as SPA não ranqueiam, como SSR, geração estática e pré-renderização resolvem isso e como tornar o app legível para as IA.

Em resumo
uma aplicação de página única (SPA, do inglês single page application) carrega uma única estrutura HTML e monta cada tela com JavaScript no navegador. O Google consegue renderizar JavaScript, mas essa renderização chega com atraso e é frágil, e os rastreadores por trás do ChatGPT, do Claude e do Perplexity não executam JavaScript. Para ranquear e ser citada, cada tela de uma SPA precisa de uma URL própria, de um link real com href, de título e descrição únicos, de um código de status correto e, acima de tudo, do conteúdo principal presente no HTML enviado pelo servidor, por meio de renderização no servidor, geração estática ou pré-renderização.
Quer ir mais longe? Pergunte ao
O SEO de aplicações SPA é o conjunto de técnicas que tornam um app JavaScript feito com React, Vue, Angular ou Svelte tão fácil de rastrear quanto um site clássico. O problema é bem documentado: o Google explica nos seus princípios básicos de SEO para JavaScript que processa as páginas JavaScript em três fases (rastreamento, renderização, indexação), e cada ponto fraco de uma SPA está em algum lugar dessa cadeia. Este guia trata das SPA; para sites JavaScript em geral, leia nosso guia de SEO para JavaScript.
Um site tradicional devolve um documento HTML completo para cada URL. Uma SPA devolve quase o mesmo documento para todas as URLs: um <div id="root"> vazio, algumas meta tags e um grande pacote de JavaScript. O navegador baixa o pacote, chama uma API e depois desenha a página. Quando o visitante clica em um link, o JavaScript troca o conteúdo sem recarregar.
Para uma pessoa com um celular rápido, o resultado parece instantâneo. Para um rastreador, a primeira resposta é uma estrutura vazia: nenhum título, nenhum texto, nenhum link. Tudo depende de o bot executar o JavaScript, e de quando ele faz isso. Esse fato sozinho explica a maior parte dos problemas de SEO das SPA:
/#/pricing), e a parte depois do # nunca é enviada ao servidor, então todas as telas se reduzem a uma única URL.<title> e, se o roteador não o atualiza, todas as páginas o compartilham.href: botões e manipuladores onClick levam os usuários a outras telas, mas não dão aos rastreadores nada para seguir.O Googlebot primeiro busca o HTML bruto e lê os links e as diretivas que encontra ali. As páginas que retornam status 200 entram depois em uma fila do Web Rendering Service, um Chromium headless. O Google afirma que uma página «pode ficar nessa fila por alguns segundos, mas pode levar mais tempo». Depois da renderização, o HTML resultante é analisado de novo em busca de conteúdo e links, e então indexado.
Quatro detalhes da documentação do Google importam para as SPA:
<a> com href são links confiáveis. Links inseridos por JavaScript funcionam, desde que sigam esse formato.pushState) em vez de rotas com #. Ele descontinuou o antigo esquema de rastreamento AJAX (as URLs com #!) em outubro de 2015.noindex no HTML original prevalece. O Google pode pular a renderização quando vê noindex, então removê-lo depois com JavaScript não funciona.A consequência é direta: o Google consegue indexar uma SPA renderizada no cliente, mas você acrescenta a cada página uma segunda etapa, um atraso e um ponto de falha. Um tempo limite excedido, uma chamada de API bloqueada ou um erro de JavaScript durante a renderização deixam a versão indexada vazia. Verifique o que o Google vê com a ferramenta de inspeção de URL do Search Console e leia nosso guia sobre como funciona a indexação do Google se algumas páginas ficarem fora do índice.
Na maioria dos casos, não. Em um estudo publicado em dezembro de 2024 sobre o tráfego da sua rede, a Vercel e a MERJ constataram que «nenhum dos principais rastreadores de IA renderiza JavaScript atualmente»: GPTBot, OAI-SearchBot e ChatGPT-User (OpenAI), ClaudeBot (Anthropic), PerplexityBot, Meta-ExternalAgent e Bytespider leem apenas o HTML bruto. Eles até baixam arquivos JavaScript (cerca de 11,5% das requisições do ChatGPT e 23,8% das do Claude), mas não os executam. As exceções são o Gemini, que usa a infraestrutura de renderização do Google, e o AppleBot, que usa um rastreador baseado em navegador.
Para uma SPA renderizada no cliente, isso significa que os rastreadores de IA que alimentam o ChatGPT, o Claude e o Perplexity veem uma página vazia. Seu produto pode ranquear no Google e continuar invisível nas respostas das IA, porque o assistente nunca leu uma palavra dele. O mesmo vale para a maioria dos bots de pré-visualização de links das redes sociais e dos aplicativos de mensagem, que leem as tags Open Graph no HTML bruto. Quando o conteúdo estiver no HTML, verifique também se o seu robots.txt permite os rastreadores de IA que você quer receber.
A solução é enviar HTML real já na primeira resposta. Na sua documentação sobre renderização dinâmica, o Google chama a renderização dinâmica (servir uma versão pré-renderizada só para os bots) de «uma solução alternativa» que ele não recomenda, e indica em seu lugar a renderização no servidor, a renderização estática ou a hidratação. As definições abaixo seguem a referência Rendering on the Web do web.dev.
| Estratégia | Como funciona | Conteúdo no primeiro HTML | Ideal para | Limites |
|---|---|---|---|---|
| Renderização no cliente (CSR) | O navegador monta a página a partir do JavaScript e de uma API | Não | Painéis e páginas atrás de login | Indexação atrasada no Google, invisível para a maioria dos rastreadores de IA |
| Renderização no servidor (SSR) | O servidor gera o HTML a cada requisição e depois o JavaScript o hidrata | Sim | Catálogos, listagens, conteúdo que muda com frequência ou é personalizado | Custo de servidor, tempo de resposta maior sem cache |
| Geração estática (SSG) | O HTML é gerado no build para cada URL e servido por uma CDN | Sim | Páginas de marketing, blog, documentação, landing pages | Novo build necessário quando o conteúdo muda (existem opções incrementais) |
| Pré-renderização no build | Um navegador headless captura o estado inicial de cada rota como HTML estático | Sim | SPA existentes com um número limitado de rotas públicas | Dados congelados no momento do build, as rotas precisam ser listadas |
| Renderização dinâmica | Os bots recebem um snapshot pré-renderizado e os usuários, a SPA | Sim, só para os bots listados | Correção temporária para um app legado | Oficialmente uma solução alternativa, custo de manutenção, risco de servir aos bots um conteúdo diferente |
A maioria dos frameworks modernos permite combinar estratégias por rota: estática para as páginas de marketing, renderizada no servidor para o catálogo, renderizada no cliente para a área logada. Essa configuração híbrida entrega HTML completo aos rastreadores onde o tráfego de busca acontece e mantém a experiência SPA onde ela agrega valor.
| Biblioteca | Framework ou recurso para ter HTML no primeiro carregamento |
|---|---|
| React | Next.js (server components, SSR e geração estática), React Router no modo framework, Gatsby |
| Vue | Nuxt (renderização universal por padrão, geração estática disponível) |
| Angular | Angular SSR (renderização no servidor e pré-renderização no build) |
| Svelte | SvelteKit (renderização no servidor por padrão, pré-renderização por rota) |
| Qualquer uma delas | Astro (HTML estático por padrão, ilhas interativas carregadas só onde são necessárias) |
Os sites gerados por criadores de sites com IA merecem uma menção especial: muitos exportam um app React renderizado no cliente. Se você criou seu site com uma dessas ferramentas, veja nossas notas sobre SEO e GEO no Lovable antes de supor que o Google e o ChatGPT conseguem lê-lo.
Use a History API (/pricing, nunca /#/pricing), uma URL por conteúdo e a mesma URL, quer o visitante chegue direto, quer navegue dentro do app. Cada URL precisa carregar o conteúdo certo quando aberta em uma nova aba: esse é o teste que um rastreador faz.
Todo elemento de navegação que leva a uma página indexável deve ser um <a href="/path">. Os componentes de link dos frameworks (Link, NuxtLink, routerLink) geram essa marcação; manipuladores de clique personalizados em elementos div ou button, não. Bons links também sustentam a arquitetura do site: se uma página não recebe links, os rastreadores raramente a encontram.
Cada rota precisa do seu próprio título, meta description, canonical e tags Open Graph, gerados no servidor sempre que possível. Nossa página sobre meta tags lista o que definir. Mantenha uma única tag canonical: o Google recomenda defini-la no HTML e, se o JavaScript a alterar, o resultado não pode contradizer o original.
Produtos inexistentes e artigos excluídos não devem responder 200 com uma mensagem de erro. Com SSR, retorne um 404 ou 410 real do servidor. Em uma SPA pura, o Google aceita duas alternativas: redirecionar com JavaScript para uma URL que retorne 404 ou adicionar uma meta tag robots noindex à tela de erro.
Títulos, texto, preços, perguntas frequentes e dados estruturados JSON-LD devem estar na resposta do servidor, sem depender de um clique ou de uma rolagem para carregar. O conteúdo atrás de abas renderizadas sob demanda, ou de botões «Carregar mais», muitas vezes é ignorado.
Divida o pacote por rota, adie o que não é necessário para a primeira tela e evite renderizar a página inteira de novo durante a hidratação. Observe que os dados de campo do Chrome (CrUX) atribuem as métricas das navegações dentro do app à URL que o visitante carregou primeiro, então teste seus templates principais um por um.
Compare três versões de cada template principal: o HTML bruto (veja o código-fonte ou busque a página com uma ferramenta de linha de comando), o HTML renderizado pelo Google (Inspeção de URL e depois «Ver página rastreada») e a página com o JavaScript desativado. Se o texto principal só aparece na segunda versão, os rastreadores de IA não o veem. Nossa auditoria de rastreabilidade para IA gratuita e o verificador de indexabilidade fazem essas verificações em qualquer URL.
| Sintoma | Causa provável | Correção |
|---|---|---|
| O Search Console mostra muitas páginas «Rastreada, mas não indexada» | HTML vazio ou quase idêntico antes da renderização | SSR, SSG ou pré-renderização para as rotas públicas |
Todos os resultados de uma busca site: mostram o mesmo título | Título não atualizado por rota | Gestão do head por rota no servidor |
| Só a página inicial está indexada | Roteamento com hash ou links sem href | History API e links <a> reais |
| Páginas de erro aparecem no índice | Soft 404 (status 200 em todo lugar) | 404 no servidor, redirecionamento JavaScript para uma URL 404 ou noindex |
| Ranqueia no Google, mas nunca é citado pelo ChatGPT ou pelo Perplexity | Conteúdo visível só depois da execução do JavaScript | Conteúdo na primeira resposta HTML |
| Conteúdo antigo na visualização renderizada do Google | Arquivos JavaScript ou CSS em cache | Nomes de arquivo com impressão digital |
Durante anos, a renderização no cliente foi um risco administrável, porque o Google acabava renderizando o JavaScript. Agora que parte da descoberta acontece no ChatGPT, no Claude, no Gemini e no Perplexity, o custo mudou: uma página que só existe depois da execução do JavaScript fica de fora das fontes que a maioria dos assistentes consegue ler. A rastreabilidade no HTML bruto passou a ser a primeira condição da otimização para mecanismos generativos (GEO).
Com o HTML completo, o resto segue as regras de sempre: as páginas que respondem com clareza a uma pergunta, com fatos com fonte e dados estruturados, são as que os assistentes citam. Os recursos de otimização GEO da Sorank ajudam você a escrever e publicar esse conteúdo, e o monitoramento de menções em IA mostra se o ChatGPT, o Claude e o Gemini citam sua marca depois da correção da renderização.
A regra principal do SEO de aplicações SPA cabe em uma frase: tudo o que você quer que o Google ranqueie e que as IA citem precisa estar no HTML que o servidor envia. Mantenha a SPA para a área logada, renderize as páginas públicas no servidor ou no build e teste o que os bots recebem antes e depois de cada lançamento.
O Google não penaliza uma aplicação de página única, mas a configuração padrão dela, a renderização no cliente com uma única estrutura HTML, deixa a indexação mais lenta e menos confiável. A maioria dos rastreadores de IA não executa JavaScript, então vê uma página vazia. Com renderização no servidor, geração estática ou pré-renderização nas rotas públicas, uma SPA pode ranquear tão bem quanto qualquer site clássico.
O React em si é neutro: o que importa é onde o HTML é gerado. Um app React renderizado apenas no navegador tem os problemas habituais das SPA, enquanto os mesmos componentes renderizados no servidor com Next.js ou React Router no modo framework entregam HTML completo aos rastreadores. Escolha um framework que ofereça renderização no servidor ou estática para as páginas que você quer indexar.
Só como medida temporária. O Google descreve a renderização dinâmica como uma solução alternativa que ele não recomenda, porque manter uma versão separada para os bots aumenta custos e riscos. A renderização no servidor, a geração estática ou a pré-renderização no build entregam o mesmo HTML a todos os visitantes e são as soluções de longo prazo.
ELES EXPERIMENTARAM O SORANK ANTES DE VOCÊ
