SEO para React
O React renderiza no lado do cliente por padrão, então os rastreadores veem um shell vazio até o JavaScript ser executado. Veja como o Google realmente processa aplicativos React, qual estratégia de renderização escolher e como corrigir roteamento, metadados e a armadilha de conteúdo duplicado por tempo limite de renderização.
Idiomas
React não é ruim para SEO — mas a renderização no lado do cliente por padrão é. Fora da caixa (CRA, Vite + React), o servidor envia um shell vazio e o navegador constrói a página, então os rastreadores não veem nada até o JavaScript ser executado. O Google pode renderizar React via seu Web Rendering Service, mas a renderização é enfileirada, atrasada e pode expirar — Gary Illyes mostrou tempos limite de renderização deixando páginas apenas com boilerplate que são marcadas como duplicadas. Os contratos de renderização de rastreadores de IA variam por provedor, então conteúdo apenas com CSR adiciona um risco de cobertura. A solução é a estratégia de renderização: SSR ou SSG (mais facilmente com Next.js ou Remix) coloca o conteúdo no HTML inicial, hidratado com hydrateRoot (não createRoot) para que a saída do servidor e do cliente correspondam exatamente. Em seguida, use roteamento com History API, links reais <a href>, códigos de status corretos e metadados apropriados para a versão: React 19 eleva <title>/<meta>/<link> nativamente, caso contrário use react-helmet-async (nunca o original react-helmet, sem manutenção).
TL;DR — React não é ruim para SEO — mas a forma como a maioria dos apps React é construída é. Por padrão, o React constrói a página no navegador do visitante, então quando um mecanismo de busca busca sua URL pela primeira vez, ele recebe uma página quase vazia. O Google geralmente consegue preencher as lacunas executando seu JavaScript, mas isso é mais lento e arriscado do que simplesmente entregar HTML pronto. A solução é renderizar suas páginas em um servidor ou no momento da compilação — geralmente com um framework como Next.js.
Por que o React é diferente
A maioria dos sites — um blog WordPress, por exemplo — envia ao mecanismo de busca uma página completa:
o servidor constrói o HTML e o entrega, título e tudo. Um app React padrão faz o
oposto. O servidor envia um shell quase vazio (basicamente um <div> vazio),
e então o JavaScript roda no navegador para construir a página real.
Isso é ótimo para experiências elegantes, parecidas com apps. É um problema para SEO, porque a primeira coisa que um crawler baixa é esse shell vazio. Seu conteúdo ainda não está lá — ele só aparece depois que o JavaScript roda.
O Google não pode simplesmente executar o JavaScript?
Sim — o Google roda uma versão real e atualizada do Chrome nos bastidores e pode executar seu JavaScript para ver a página finalizada. Então o conteúdo React pode ser indexado. Evidence for this claim Googlebot uses an evergreen Chromium rendering engine and can execute JavaScript. Scope: Google Search; successful execution still depends on accessible resources and application behavior. Confidence: high · Verified: Google: JavaScript SEO basics
Mas há ressalvas:
- É atrasado. O Google faz a renderização depois, em uma etapa separada que fica na fila. Então seu conteúdo pode demorar mais para aparecer na busca.
- Pode falhar. Se sua página demorar para carregar o conteúdo, o renderizador do Google pode desistir antes de o conteúdo aparecer — e indexar uma página quase em branco.
- Outros crawlers variam. O Bing lida com JavaScript de forma menos confiável, e os provedores de IA não publicam um contrato de renderização compartilhado. Qualquer crawler que busque apenas o HTML inicial verá um app React padrão como vazio.
A solução simples
Coloque seu conteúdo no HTML antes de ele chegar ao navegador. Duas formas:
- Renderização no servidor (SSR) — um servidor constrói a página completa para cada requisição.
- Geração de site estático (SSG) — as páginas são construídas em HTML finalizado antecipadamente. Evidence for this claim React supports server rendering APIs and can be used by frameworks that generate HTML outside the browser. Scope: React server APIs; build-time generation is a framework/build-system capability rather than a React mode by itself. Confidence: high · Verified: React: Server APIs
O caminho mais fácil para qualquer uma delas é o Next.js, um framework construído sobre o React que faz isso por você. (O Remix é outra boa opção.) Com SSR ou SSG, seu site React entrega aos crawlers uma página completa — e é tão amigável para busca quanto qualquer site normal.
Mais algumas coisas para acertar
- Use URLs com aparência normal (
/products), não URLs com hash (/#/products) — o Google não consegue indexar as com hash de forma confiável. - Faça seus links serem links reais (
<a href>), não<div>s clicáveis. - Dê a cada página seu próprio título e descrição que atualizem quando a página mudar.
Quer a versão mais aprofundada — como o renderizador do Google realmente funciona, a armadilha do tempo limite de renderização que cria páginas duplicadas, a comparação de estratégias de renderização e como testar o que o Google vê? Mude para a aba Avançado.
TL;DR — O problema de SEO do React não é o React — é a renderização no lado do cliente por padrão. CRA e Vite + React entregam um shell vazio e constroem o DOM no navegador, então o HTML bruto que um crawler busca não tem conteúdo. O Google pode renderizá-lo via o Web Rendering Service (Chromium evergreen), mas a renderização é enfileirada separadamente, pode ser atrasada e pode expirar — Gary Illyes documentou timeouts de renderização deixando páginas apenas com boilerplate que depois são sinalizadas como duplicadas. O Bing renderiza JS de forma menos confiável; a renderização por crawlers de IA varia conforme o provedor. A solução é a estratégia de renderização: SSR ou SSG (mais facilmente Next.js ou Remix) coloca o conteúdo no HTML inicial — e se você estiver hidratando marcação renderizada no servidor, use
hydrateRoot(nãocreateRoot) e trate qualquer incompatibilidade servidor/cliente como um bug, não um aviso para suprimir. Depois use roteamento via History API (não URLs com hash) e links reais<a href>. Para metadados<head>: React 19 eleva<title>/<meta>/<link>nativamente; no React 18 ou para necessidades avançadas, use react-helmet-async (nunca o react-helmet original não mantido). Defina códigos de status HTTP corretos. Não há bônus de ranqueamento para SSR — ele apenas torna o conteúdo confiavelmente indexável. Para os mecanismos gerais de renderização, veja os tópicos de JavaScript SEO e CMS headless.
O que realmente torna o React difícil para SEO
React é uma biblioteca JavaScript baseada em componentes, e por padrão — Create React App,
Vite + React — ela roda no lado do cliente. O servidor retorna um documento quase vazio
(famosamente apenas um <div id="root"></div>) mais um bundle de JavaScript, e o navegador
executa esse JavaScript para construir o DOM. Compare isso com uma página renderizada no servidor
(WordPress, um app Rails), onde o HTML completo — conteúdo, cabeçalhos, links —
chega na primeira resposta.
Então a pergunta que decide tudo é: o que está no HTML bruto antes de qualquer JavaScript rodar? Para um app React padrão, a resposta é “quase nada.” Clique com o botão direito → Ver código-fonte em um app CRA e você verá o shell, não o conteúdo. Isso é exatamente o que um crawler recebe na primeira busca.
Para ser preciso sobre onde a responsabilidade realmente está: a biblioteca React não é
apenas CSR. O React DOM oferece renderização no cliente (createRoot), renderização no servidor (APIs de streaming
e estáticas) e APIs de hidratação — a biblioteca suporta tudo isso. O problema do shell vazio
é uma propriedade do toolchain padrão (Create React App, Vite + React sem
servidor), que configura apenas as APIs do cliente e nada que renderize para HTML no
servidor. Troque o toolchain — Next.js, Remix ou as próprias APIs de renderização no servidor do React — e
a mesma biblioteca entrega HTML completo na primeira resposta.
Esta é a aplicação específica do React do problema mais amplo de JavaScript SEO — vá para lá para os modos gerais de falha (paridade, interação, estado, tempo). Aqui vou focar no que é específico do React e como corrigir.
Como o Google realmente processa um app React
O Google lida com JavaScript em três fases: crawl → render → index. O Googlebot busca a URL, o DOM renderizado é construído depois pelo Web Rendering Service (WRS) — uma versão evergreen do Chromium, o mesmo motor do Chrome — e então a saída renderizada é indexada e seus links extraídos. Evidence for this claim Google processes JavaScript pages through crawling, rendering, and indexing using its Web Rendering Service. Scope: Google Search rendering behavior. Confidence: high · Verified: Google: JavaScript SEO basics
A nuance importante é quando a renderização acontece. A renderização é intensiva em recursos, então ela é enfileirada separadamente do crawl inicial. Martin Splitt descreveu o fluxo claramente: “we do an HTTP request, and we get something back … some barebone HTML and all it does is load the JavaScript and run the JavaScript. Then, this HTML … goes into rendering. Rendering runs JavaScript — boom!, a lot of content happens that wasn’t there before.” (tradução) «fazemos uma requisição HTTP e recebemos algo de volta … algum HTML básico e tudo o que ele faz é carregar o JavaScript e executar o JavaScript. Então, esse HTML … vai para a renderização. A renderização executa JavaScript — boom!, muito conteúdo acontece que não estava lá antes.» Para uma página React CSR, o “boom” é sua página inteira — nada dela existe até que essa etapa de renderização rode.
Uma ressalva que vale carregar: não se apegue demais ao antigo modelo de “duas ondas de indexação”. O próprio Splitt recuou, chamando a onda de “uma simplificação excessiva.” A conclusão prática não é “existe uma Onda 2 formal com cronograma definido” — é que a renderização é uma etapa distinta, adiável e falível, e o CSR coloca 100% do seu conteúdo do lado errado dela.
Mais dois fatos sobre o renderizador que afetam especificamente aplicativos React:
- Ele não tem estado. O Googlebot não retém
localStorage,sessionStorageou cookies entre carregamentos de página. Qualquer conteúdo ou roteamento que dependa de estado do lado do cliente é invisível para o rastreador. - Ele pode desistir. O renderizador impõe um tempo limite. Se o seu conteúdo principal carregar lentamente — bundles grandes, cascatas de chamadas de API — a renderização pode terminar antes que seu conteúdo chegue, e o Google indexa a página incompleta.
A armadilha do tempo limite de renderização (e por que ela cria duplicatas)
Esse modo de falha raramente é bem explicado, e é o mais prejudicial para aplicativos React. Gary Illyes descreveu isso diretamente: “I have a bunch of emails in my inbox where the issue is that the centerpiece took forever to load, so rendering timed out … and we were left with a bunch of pages that only had the boilerplate. With only the boilerplate, those pages are dups.” (tradução) «Tenho um monte de e-mails na minha caixa de entrada onde o problema é que a peça central demorou uma eternidade para carregar, então a renderização expirou … e ficamos com um monte de páginas que só tinham o boilerplate. Com apenas o boilerplate, essas páginas são duplicatas.»
Pense no que isso significa para um aplicativo React com CSR. Seu cabeçalho, navegação e rodapé são boilerplate que carrega rápido. Seu conteúdo real da página — a parte que torna cada URL única — é buscado e renderizado por JavaScript, e carrega lentamente. A renderização expira. O Google fica com cabeçalho + navegação + rodapé em cada URL. Agora cada página parece idêntica, e o Google as marca como duplicatas umas das outras no Search Console.
A própria correção do Illyes é a parte acionável: “Try to restructure the js calls such that the content (including marginal boilerplate) loads first and see if that helps.” (tradução) «Tente reestruturar as chamadas de js para que o conteúdo (incluindo boilerplate marginal) carregue primeiro e veja se isso ajuda.» Mas a resposta mais durável é não depender da etapa de renderização para o seu conteúdo principal — o que significa SSR ou SSG.
Estratégias de renderização para React
Esta é a decisão de maior impacto. As opções, aproximadamente do pior para o melhor em SEO:
- CSR (React padrão). O servidor envia o shell; o navegador constrói tudo. O conteúdo é atrasado pela fila de renderização e exposto ao tempo limite. Pior para SEO. Adequado para dashboards autenticados que você não quer indexados de qualquer forma. Evidence for this claim Client-only React rendering constructs UI in the browser; server rendering APIs produce HTML before browser hydration. Scope: React rendering mechanics; SEO impact depends on what the initial response contains. Confidence: high · Verified: React: hydrateRoot React: Server APIs
- Pré-renderização. Renderização em tempo de build sem um framework SSR completo — ferramentas como
react-snapou um serviço de pré-renderização rastreiam seu aplicativo e salvam HTML estático. Mais leve; funciona para sites mais simples e majoritariamente estáticos. - SSG (Geração de Site Estático). HTML construído uma vez no momento do deploy e servido como arquivos estáticos. Mais rápido, conteúdo sempre presente no HTML bruto. Limitado para conteúdo altamente dinâmico ou por usuário; sites grandes têm builds lentos.
- SSR (Renderização no Servidor). O servidor executa React por requisição e envia HTML completo. Conteúdo imediatamente disponível para rastreadores; sempre atualizado. Custa um servidor Node.js e um TTFB ligeiramente maior.
- Híbrido / ISR (Regeneração Estática Incremental). Um recurso do Next.js que regenera páginas estáticas em segundo plano — velocidade estática com atualização periódica.
| Estratégia | Conteúdo no HTML inicial? | Risco de SEO | Melhor para |
|---|---|---|---|
| CSR (React puro) | Não | Mais alto | Dashboards logados, aplicativos não indexados |
| Pré-renderização | Sim (tempo de build) | Baixo | Sites pequenos, majoritariamente estáticos |
| SSG | Sim (tempo de build) | Mais baixo | Blogs, documentação, marketing |
| SSR | Sim (por requisição) | Baixo | Conteúdo atualizado e dinâmico |
| ISR / híbrido | Sim | Baixo | Conteúdo que muda a cada hora/dia |
E uma estratégia para evitar em novos builds: renderização dinâmica — detectar o user-agent do crawler e servir a ele uma versão pré-renderizada enquanto os usuários recebem CSR. O Google agora chama isso de “a workaround and not a long-term solution” (tradução) «um paliativo, e não uma solução de longo prazo» que “creates additional complexities and resource requirements,” (tradução) «cria complexidades e requisitos adicionais de recursos», e recomenda renderização no servidor, renderização estática ou hidratação em vez disso. (O Bing recomendou renderização dinâmica em 2018, mas essa orientação está desatualizada — desde 2019 o Bingbot renderiza via Microsoft Edge / Chromium, e SSR/SSG é a escolha certa lá também.)
Há um mito que vale a pena eliminar aqui: SSR não é um impulso de ranqueamento. Como John Mueller disse, “there are no SEO ranking bonuses for implementing it one way or another” (tradução) «não há bônus de ranqueamento de SEO por implementar de um jeito ou de outro» — os diferentes métodos de renderização são “just different ways of making the content indexable.” (tradução) «apenas maneiras diferentes de tornar o conteúdo indexável». O valor do SSR é a indexabilidade confiável (e frequentemente melhores Core Web Vitals graças a um First Contentful Paint mais rápido), não uma alavanca mágica de ranqueamento.
A hidratação deve corresponder exatamente — isso é um limite de bug, não uma técnica de SEO
SSR e SSG ambos entregam ao navegador HTML que já contém seu conteúdo. O React então precisa anexar-se a essa marcação no cliente, e isso é uma API diferente de uma renderização simples no cliente:
createRootrenderiza o React em um nó do DOM do zero — sem marcação existente esperada. Use-o para aplicativos somente CSR.hydrateRootanexa o React ao HTML quereact-dom/serverjá gerou, e espera que a primeira renderização do cliente produza uma saída idêntica à que o servidor enviou. Se você está usando SSR/SSG, você querhydrateRoot, nãocreateRoot— chamarcreateRootem marcação renderizada no servidor significa que o React a descarta e re-renderiza do zero, jogando fora exatamente o benefício de SEO que você configurou SSR/SSG para obter.
Incompatibilidades entre a saída do servidor e do cliente são um risco real em aplicativos React que fazem correções de SEO — um Date.now() em um título, um formato dependente de localidade, um ramo if (typeof window !== 'undefined'). A própria documentação do React é direta sobre o que acontece então: ela avisa sobre incompatibilidades em desenvolvimento, mas “there are no guarantees that attribute differences will be patched up in case of mismatches.” (tradução) «não há garantias de que as diferenças de atributos serão corrigidas em caso de incompatibilidade». A orientação é tratar incompatibilidades como bugs e corrigi-las — não suprimir o aviso e assumir paridade de conteúdo. Para SEO especificamente: não assuma que seu conteúdo renderizado e metadados correspondem ao que o servidor enviou apenas porque a página parece correta no navegador. Compare o HTML do servidor com o DOM pós-hidratação diretamente (a verificação View Source vs. Inspect Element da seção de testes abaixo é a versão rápida disso) em vez de confiar em um console limpo.
React Router e estrutura de URL
O React Router lida com a navegação no navegador sem idas e voltas ao servidor, o que é aceitável para SEO se configurado corretamente:
- Use a History API, não roteamento por hash.
BrowserRouterusapushStatee produz URLs limpas e rastreáveis (/products).HashRouterproduz/#/products, e o Google não consegue resolver URLs baseadas em hash de forma confiável — o antigo esquema de crawling AJAX que as fazia funcionar está obsoleto. Use a History API. - O servidor também deve lidar com essas URLs. Com o roteamento pela History API, cada “página” precisa de uma URL real à qual o servidor possa responder — crítico para SSR, e necessário para que um acesso direto ou atualização em
/productsnão retorne 404. <Link>renderiza uma âncora real. O componente<Link>do React Router gera um<a href>, que é rastreável. Navegação construída com manipuladoresonClicksem uma âncora não é rastreável — o Google só segue links<a href>reais.
Gerenciando metadados: react-helmet, react-helmet-async e as tags nativas do React 19
Até o React 18, o React nunca atualizava o <head> do documento nativamente em mudanças de rota —
cada <title>, meta description, canonical e tags Open Graph / Twitter de cada rota
tinham que ser definidos por uma biblioteca. O React 19 mudou isso: componentes podem renderizar tags <title>,
<meta> e <link> diretamente, e o React as eleva para <head> por conta própria —
funcionando com aplicativos somente cliente, SSR com streaming e Server Components. O React 19.2 é
a versão estável atual em meados de 2026, então isso agora se aplica a qualquer aplicativo em uma versão
atual do React.
Isso significa que a resposta certa depende da sua versão do React e do que você realmente precisa:
- React 19, aplicativo autônomo, apenas tags básicas. Renderize
<title>/<meta>/<link>em seus componentes diretamente — nenhuma biblioteca necessária. - React 19, mas você precisa de
htmlAttributes/bodyAttributes, serialização decontextpara SSR,onChangeClientState,prioritizeSeoTagsoutitleTemplate. A elevação nativa não cobre isso — usereact-helmet-async. A própria documentação dele destaca isso diretamente: sem essas necessidades específicas, você pode não precisar do pacote no React 19. - React 18 ou anterior, aplicativo autônomo. A elevação nativa ainda não existe — use
react-helmet-async. Ele é mantido ativamente (versão principal 3, e detecta sua versão do React em tempo de execução) e suporta SSR. - O
react-helmetoriginal. Não use, em nenhuma versão do React. Ele não é mantido — nenhum lançamento desde 2020 — e tem bugs conhecidos sob a renderização concorrente do React 18. - Aplicativos Next.js. Use a própria Metadata API do Next (o export
metadata/generateMetadatano App Router) independentemente da versão do React — não adicione Helmet, e também não confie na elevação nativa de tags do React. O framework é dono do documento em um aplicativo Next.js.
Uma regra de confiabilidade vem do JavaScript SEO em geral e se aplica não importa qual das opções acima você use: metadados em nível de HTML superam metadados injetados por JS. Uma tag canonical injetada por JavaScript no lado do cliente é muito menos confiável do que uma presente no HTML renderizado no servidor — o que é outro argumento para SSR/SSG.
Crawlers de IA tornam isso urgente
A novidade de 2026: o comportamento de renderização para GPTBot (OpenAI), ClaudeBot (Anthropic), PerplexityBot e outros agentes é específico do provedor e da versão. Um aplicativo React CSR entrega a cada crawler o mesmo shell vazio que o primeiro fetch do Googlebot vê, e a documentação atual dos provedores não estabelece uma etapa de renderização compartilhada que o preencha. À medida que os mecanismos generativos se tornam uma superfície de descoberta maior, SSR/SSG deixa de ser uma preocupação exclusiva do Google: HTML bruto maximiza a cobertura sem assumir uma limitação universal do crawler. (O tópico de CMS headless cobre essa realidade dos crawlers de IA em mais profundidade.)
Testando o que o Google realmente vê
Não confie no seu navegador — o Inspetor do DevTools mostra o DOM renderizado (pós-JavaScript), que é exatamente o que um crawler sem JS não vê. Use as ferramentas certas:
- Ver código-fonte vs. Inspecionar elemento. Ver código-fonte é o HTML bruto (o que os crawlers recebem antes do JS). Inspecionar elemento é o DOM renderizado. Se o conteúdo está em Inspecionar, mas falta no Ver código-fonte, ele depende de JavaScript.
- Ferramenta de inspeção de URL (Search Console) — a verificação mais autoritativa. Execute um teste ao vivo e observe o HTML renderizado, a captura de tela e os recursos da página / mensagens do console para ver o que o Google realmente renderizou e o que falhou ao carregar.
- Teste de resultados avançados — uma verificação rápida do HTML renderizado sem verificar o site.
- Desative o JavaScript no DevTools e recarregue — uma simulação rápida de um crawler que não executa JS (e um bom proxy para o que os crawlers de IA veem).
- Relatório de cobertura do Search Console — “Descoberto, atualmente não indexado” pode sinalizar um acúmulo na fila de renderização; clusters de páginas duplicadas podem sinalizar a armadilha do boilerplate de timeout de renderização.
- Crawlers com renderização JS — Ahrefs Site Audit e Screaming Frog (modo de renderização JS) renderizam páginas em escala para que você possa comparar bruto vs. renderizado em todo o site.
Next.js e Remix (a resposta prática)
Se SEO importa e você está em React CSR puro, migrar para um framework que renderiza no servidor geralmente é a jogada certa. Next.js é feito para isso — SSR e SSG prontos para uso, ISR, App Router, uma Metadata API integrada, divisão automática de código e otimização de imagens. Remix é a alternativa baseada em padrões web, construída em fetch/Request/Response com SSR por padrão e uma forte história de progressive enhancement. O Next.js tem um mergulho profundo próprio — estou sendo breve aqui de propósito. O ponto para SEO em React é mais restrito: o framework existe para tirar seu conteúdo da etapa de renderização apenas no navegador e colocá-lo no HTML inicial.
React é bom para SEO quando você trata a renderização como uma decisão de arquitetura, e não como algo pensado depois. Escolha SSR ou SSG para qualquer coisa que precise ranquear, mantenha seus links e roteamento honestos, gerencie metadados por rota e deixe as próprias ferramentas do Google — não o seu navegador — dizerem o que realmente foi renderizado.
Resumo de IA
Uma visão condensada da versão Avançada:
- React não é ruim para SEO — CSR por padrão é. A biblioteca React suporta renderização
no cliente, no servidor, estática e em streaming; é o toolchain padrão do CRA/Vite (sem
servidor) que entrega um shell vazio
<div id="root">e constrói o DOM no navegador, então o HTML bruto que um crawler busca não tem conteúdo. - O Google consegue renderizar React via Web Rendering Service (Chromium evergreen), mas a renderização é enfileirada separadamente, pode ser atrasada e é stateless (sem cookies/localStorage/sessionStorage entre carregamentos).
- A armadilha do tempo limite de renderização: se o conteúdo principal carrega devagar, a renderização atinge o tempo limite e o Google indexa uma página apenas com boilerplate. Em muitas URLs, elas parecem idênticas e são sinalizadas como duplicadas (o modo de falha documentado por Gary Illyes). Correção: carregue o conteúdo primeiro — ou melhor, não dependa da etapa de renderização (SSR/SSG).
- Estratégias de renderização, da melhor para a pior em SEO: SSG (menor risco) ≈ SSR ≈ pré-renderização > ISR/híbrido > CSR (maior risco). Renderização dinâmica está obsoleta — o Google recomenda SSR, renderização estática ou hidratação.
- Sem bônus de ranqueamento para SSR — Mueller: “no SEO ranking bonuses for implementing it one way or another.” (tradução) «sem bônus de ranqueamento de SEO por implementar de um jeito ou de outro.» Isso apenas torna o conteúdo indexável de forma confiável.
- Hidratação é um limite de bugs, não uma técnica: apps SSR/SSG hidratam com
hydrateRoot(nãocreateRoot), que espera que a primeira renderização do cliente corresponda exatamente à do servidor. O React avisa sobre incompatibilidades em dev, mas não garante corrigi-las — trate incompatibilidades como bugs e verifique o DOM do servidor vs. pós-hidratação diretamente. - React Router: use a History API (
BrowserRouter), não roteamento por hash; o servidor deve lidar com essas URLs;<Link>renderiza<a href>rastreável — navegação apenas comonClicknão. - Metadados: React 19 eleva nativamente
<title>/<meta>/<link>para<head>em apps independentes que precisam apenas do básico. No React 18, ou para necessidades avançadas (contexto SSR,titleTemplate), use react-helmet-async — nunca o react-helmet original, sem manutenção desde 2020. No Next.js, use a Metadata API independentemente da versão do React. Nível de HTML é melhor que JS injetado. - A renderização por crawlers de IA é específica do provedor — CSR React depende da execução no cliente que cada crawler pode ou não suportar. SSR/SSG coloca o conteúdo no HTML inicial e maximiza a cobertura.
- Teste com View Source vs. Inspect, URL Inspection (HTML renderizado + screenshot + console), Rich Results Test, recarregamento com JS desabilitado e um crawler com renderização de JS.
- Next.js / Remix são a correção prática — eles movem o conteúdo para o HTML inicial.
Documentação oficial
Documentação de fonte primária dos mecanismos de busca.
- Entenda os fundamentos de SEO para JavaScript — o pipeline de rastreamento → renderização → indexação, SPAs, a History API, URLs canônicas com JavaScript e códigos de status HTTP significativos.
- Corrija problemas de JavaScript relacionados à pesquisa — tratamento de soft-404 em SPAs, o renderizador sem estado (sem cookies/localStorage) e testes com a Inspeção de URLs.
- Renderização dinâmica (solução alternativa obsoleta) — por que o Google a tornou obsoleta e o que usar em vez dela (SSR, renderização estática, hidratação).
- Apresentando uma nova série de vídeos sobre SEO para JavaScript — a série de Martin Splitt, cobrindo React, Angular e Vue especificamente.
- Guia aprofundado de como a Pesquisa Google funciona — onde a renderização se encaixa no fluxo de rastreamento → indexação → exibição.
Bing / Microsoft
- O novo Bingbot evergreen (Microsoft Edge) — o Bingbot renderizando JavaScript por meio da mesma plataforma Chromium do Googlebot.
- Série bingbot: JavaScript, renderização dinâmica e cloaking — a visão mais antiga (2018) do Bing; útil para a recomendação histórica de renderização dinâmica.
Referência técnica
- React v19 (notas de versão) — suporte nativo para renderizar tags
<title>,<meta>e<link>em componentes, movidas automaticamente para<head>. - createRoot / hydrateRoot (documentação do React) — a divisão da API entre renderização no cliente e hidratação, e a ressalva de que incompatibilidades não têm garantia de correção.
- react-helmet-async (npm) — o fork mantido para gerenciar
<head>em aplicativos React independentes, para necessidades do React 18 ou do React 19 avançado.
Citações da fonte
Declarações oficiais da equipe de pesquisa do Google. Cada link profundo do mecanismo de pesquisa salta para a passagem citada na página de origem; as citações da equipe abaixo estão vinculadas à cobertura que as reproduziu.
Documentação do Google — SPAs e renderização dinâmica
- “Single-page applications (SPA) are websites that load an HTML document once and fetch any additional content using JavaScript APIs.” (tradução) «Aplicativos de página única (SPA) são sites que carregam um documento HTML uma vez e buscam qualquer conteúdo adicional usando APIs de JavaScript.» — Documentação do Google Search Central. Ir para a citação
- “Dynamic rendering was a workaround and not a long-term solution for problems with JavaScript-generated content in search engines.” (tradução) «A renderização dinâmica era uma solução alternativa e não uma solução de longo prazo para problemas com conteúdo gerado por JavaScript nos mecanismos de pesquisa.» — Documentação do Google Search Central. Ir para a citação
Martin Splitt, Google — como páginas JavaScript são indexadas
- “What we do is we do an HTTP request, and we get something back, right — some HTML, maybe it’s a barebone HTML and all it does is load the JavaScript and run the JavaScript. Then, this HTML that we got from the original HTTP GET request from the crawl, goes into rendering. Rendering runs JavaScript — boom!, a lot of content happens that wasn’t there before.” (tradução) «O que fazemos é fazer uma requisição HTTP e recebemos algo de volta, certo — algum HTML, talvez seja um HTML básico e tudo o que ele faz é carregar o JavaScript e executar o JavaScript. Então, esse HTML que obtivemos da requisição HTTP GET original do rastreamento vai para a renderização. A renderização executa JavaScript — boom!, muita coisa acontece que não estava lá antes.» Leia a cobertura (Search Engine Journal)
- Sobre o modelo de duas ondas ser impreciso: “there’s no such thing as the second wave of crawling-ish. The wave is an oversimplification.” (tradução) «não existe essa coisa de segunda onda de rastreamento. A onda é uma simplificação excessiva.» Leia a cobertura (Search Engine Roundtable)
Gary Illyes, Google — a armadilha de conteúdo duplicado por timeout de renderização
- “I have a bunch of emails in my inbox where the issue is that the centerpiece took forever to load, so rendering timed out (my most likely explanation) and we were left with a bunch of pages that only had the boilerplate. With only the boilerplate, those pages are dups.” (tradução) «Tenho um monte de e-mails na minha caixa de entrada onde o problema é que a peça central demorou muito para carregar, então a renderização expirou (minha explicação mais provável) e ficamos com um monte de páginas que só tinham o boilerplate. Com apenas o boilerplate, essas páginas são duplicadas.»
- “Do you have a JavaScript-heavy site and you see lots of dups reported in Search Console? Try to restructure the js calls such that the content (including marginal boilerplate) loads first and see if that helps.” (tradução) «Você tem um site com muito JavaScript e vê muitas duplicatas relatadas no Search Console? Tente reestruturar as chamadas de js para que o conteúdo (incluindo boilerplate marginal) carregue primeiro e veja se isso ajuda.» Leia a postagem (LinkedIn)
John Mueller, Google — sem bônus de ranqueamento para a escolha de renderização
- “There are no SEO ranking bonuses for implementing it one way or another.” (tradução) «Não há bônus de ranqueamento de SEO por implementar de um jeito ou de outro.» Eles são “just different ways of making the content indexable (as is client side rendering).” (tradução) «apenas maneiras diferentes de tornar o conteúdo indexável, assim como a renderização no lado do cliente». Leia a cobertura (Search Engine Roundtable)
Checklist de SEO para React
Uma verificação para confirmar que os crawlers podem ver e indexar seu aplicativo React:
- O conteúdo importante aparece em Ver código-fonte (HTML bruto), não apenas no DOM renderizado — se estiver ausente, você está dependendo de CSR.
- As páginas que precisam ranquear usam SSR ou SSG (Next.js, Remix ou uma etapa de pré-renderização), não renderização bruta no lado do cliente.
- O conteúdo principal carrega rápido e primeiro — sem cascatas lentas de API que possam acionar o tempo limite de renderização em uma página apenas com boilerplate.
- O roteamento usa a History API (
BrowserRouter), nãoHashRouter/ URLs#/. - O servidor pode responder a cada rota do lado do cliente (sem 404 em acesso direto ou atualização).
- A navegação usa links reais
<a href>(React Router<Link>), não apenas manipuladoresonClickem<div>/<button>. - Cada rota define um
<title>único, meta description, canonical e tags OG que atualizam na navegação. - Os metadados correspondem à sua versão: React 19 com tags nativas
<title>/<meta>/<link>para o básico, react-helmet-async para React 18 ou necessidades avançadas (nunca oreact-helmetobsoleto), ou a Next.js Metadata API se estiver no Next.js. - Se renderizado no servidor, você está hidratando com
hydrateRoot(nãocreateRoot), e qualquer aviso de incompatibilidade de hidratação em modo de desenvolvimento é tratado como bug a corrigir. - Rotas de “não encontrado” no lado do cliente retornam um 404 real (ou um
noindex), não um soft-404 com status200. - JavaScript e CSS não estão bloqueados em
robots.txt(o Google não renderiza a partir de arquivos bloqueados). - Nenhum conteúdo crítico depende de cookies / localStorage / sessionStorage (o renderizador é sem estado).
- Verificado em URL Inspection: o HTML renderizado e a captura de tela mostram seu conteúdo real.
- Relatório de cobertura verificado para “Descoberto, atualmente não indexado” (fila de renderização) e clusters duplicados (armadilha de tempo limite de renderização).
Os modelos mentais
1. A única pergunta que importa: o que está no HTML bruto? Ver código-fonte antes de qualquer JavaScript executar é o que um crawler de primeira busca — e a maioria dos crawlers de IA, para sempre — vê. Se o seu conteúdo não está lá, você tem um problema de SEO com React, independentemente de quão boa a página pareça no seu navegador.
2. A renderização é uma etapa separada e sujeita a falhas. Rastrear → renderizar → indexar. CSR coloca 100% do seu conteúdo do lado distante da etapa de renderização, que é enfileirada, atrasada, sem estado e pode expirar. SSR/SSG movem seu conteúdo antes dessa etapa. Não confie demais no modelo de “duas ondas” — o próprio Splitt o chamou de simplificação excessiva.
3. O modo de falha de duplicação de boilerplate. Conteúdo lento + tempo limite de renderização = cada URL renderiza apenas cabeçalho/navegação/rodapé = o Google vê duplicatas. A correção é estrutural: carregue o conteúdo primeiro ou pare de depender da etapa de renderização.
4. A árvore de decisão de renderização.
- Conteúdo público que deve ranquear ou ser citado por IA → SSG (estático) ou SSR (fresco).
- Majoritariamente estático (blog, documentação, marketing) → SSG, ou ISR em um temporizador.
- Mudanças frequentes, deve ser fresco → SSR.
- Painel logado, não destinado a ser indexado → CSR é aceitável.
- Novo build que precisa de SEO → use Next.js / Remix, não renderização dinâmica.
5. HTML primeiro, JS segundo para cada sinal de SEO. Conteúdo, links, canonicals, títulos, dados estruturados — coloque-os no HTML renderizado no servidor. Trate sinais de SEO injetados por JS (incluindo tags canonical via JS e react-helmet em CSR) como um plano B, não o plano principal: o Google os vê tarde, e os crawlers de IA não os veem de forma alguma.
React SEO — folha de referência
Modos de renderização de relance
| Modo | Conteúdo no HTML inicial? | Risco de SEO | Use para |
|---|---|---|---|
| CSR (React bruto) | Não | Mais alto | Painéis logados, apps não indexados |
| Pré-renderização (react-snap) | Sim (no build) | Baixo | Sites pequenos, majoritariamente estáticos |
| SSG | Sim (no build) | Mais baixo | Blogs, documentação, marketing |
| SSR | Sim (por requisição) | Baixo | Conteúdo fresco e dinâmico |
| ISR / híbrido (Next.js) | Sim | Baixo | Conteúdo por hora/diário |
| Renderização dinâmica | Somente bot | Obsoleto | Não use — use SSR/SSG/hidratação |
Erros comuns de SEO com React → correções
| Erro | Correção |
|---|---|
| Conteúdo apenas no DOM renderizado (CSR) | SSR / SSG / pré-renderização |
URLs com hash (/#/path) | History API (BrowserRouter) |
Navegação via onClick, sem âncora | <a href> real / <Link> do React Router |
| Meta tags não atualizam na rota | React 19: <title>/<meta>/<link> nativos. Versões antigas/avançadas: react-helmet-async. Next.js: Metadata API |
react-helmet (original, qualquer versão do React) | Troque para react-helmet-async ou tags nativas do React 19 |
createRoot usado em HTML renderizado no servidor | Use hydrateRoot — createRoot descarta o markup do servidor |
| Aviso de incompatibilidade de hidratação suprimido | Trate como bug e corrija a diferença servidor/cliente |
| Conteúdo lento → timeout de renderização → duplicatas | Carregue o conteúdo principal primeiro; migre para SSR/SSG |
404 no cliente retorna 200 | Status 404 real ou noindex |
.js / .css bloqueados no robots.txt | Permita-os — o Google não renderiza arquivos bloqueados |
| Conteúdo restrito por cookies/localStorage | Não faça isso — o renderizador é sem estado |
Regras rápidas
- O renderizador é Chromium evergreen, em fila, sem estado e com timeout.
- Sem bônus de ranqueamento para SSR — trata-se de indexabilidade confiável (Mueller).
- A renderização por crawlers de IA varia conforme o provedor → HTML bruto é a base de cobertura mais segura.
- No Next.js, use a Metadata API — não o React Helmet.
- O Bing renderiza JS (via Edge), mas de forma menos confiável; SSR/SSG também é a opção segura lá.
Verifique o que o servidor envia antes de o React executar
Coloque rotas indexáveis representativas em urls.txt. Isso encontra shells CSR e marcação de cabeçalho ausente no HTML bruto da resposta:
while IFS= read -r url; do
html=$(mktemp)
status=$(curl -sS -o "$html" -w '%{http_code}' "$url")
bytes=$(wc -c < "$html" | tr -d ' ')
title_count=$(grep -Eio '<title>[^<]*</title>' "$html" | wc -l | tr -d ' ')
canonical_count=$(grep -Eio '<link[^>]+rel=["'"']canonical["'"'][^>]*>' "$html" | wc -l | tr -d ' ')
printf '%s\t%s\tbytes=%s\ttitles=%s\tcanonicals=%s\n' "$status" "$url" "$bytes" "$title_count" "$canonical_count"
rm -f "$html"
done < urls.txtTamanho pequeno em bytes é apenas um sinal de revisão, não um erro por si só. Compare as respostas brutas sinalizadas com o HTML renderizado e confirme se o texto principal e os links rastreáveis estão presentes.
Ferramentas para auditar SEO em React
- View Source vs. Inspect Element — a verificação inicial mais rápida. View Source é o HTML bruto (o que um crawler recebe antes do JS); Inspect Element é o DOM renderizado. Conteúdo no Inspect, mas não no View Source, depende de JavaScript.
- URL Inspection (Google Search Console) — a fonte da verdade. Execute um teste ao vivo e depois veja o HTML renderizado, a captura de tela, os recursos da página (o que carregou vs. o que foi bloqueado) e as mensagens do console para ver exatamente o que o Google renderizou.
- Rich Results Test — uma verificação rápida de HTML renderizado e dados estruturados para uma única URL sem verificar o site.
- Chrome DevTools — desative o JavaScript (Menu de Comandos → “Disable JavaScript”) e recarregue para inspecionar o que um buscador somente HTML recebe. Isso é uma verificação de cobertura, não uma prova do comportamento atual de renderização de nenhum crawler de IA específico.
- Relatório de cobertura do Search Console — observe “Discovered, currently not indexed” (fila de renderização) e clusters duplicados (a armadilha do boilerplate de timeout de renderização).
- Crawlers com renderização JS — Ahrefs Site Audit e Screaming Frog SEO Spider (modo de renderização JS) executam JavaScript para que você possa comparar HTML bruto vs. renderizado em todo o site.
Erros que equipes React realmente cometem
Padrões concretos que vejo em apps React CSR que são publicados, não hipotéticos. Cada um é uma medida preventiva — detecte antes que custe sua indexação.
Enviando CSR CRA/Vite bruto para páginas que precisam ranquear
Equipes enviam Create React App ou Vite + React direto para produção em páginas de marketing,
posts de blog ou páginas de produto — exatamente o conteúdo que precisa aparecer na busca.
Por que está errado: o servidor envia um shell quase vazio <div id="root">; seu conteúdo
real só existe após o JavaScript executar, então ele é atrasado pela fila de renderização do Google e
pode ficar invisível para qualquer crawler de IA que busque o HTML inicial sem execução no cliente.
O que fazer em vez disso: mova
tudo o que precisa ranquear ou ser citado para SSR ou SSG — Next.js ou Remix são os caminhos
mais fáceis — e reserve CSR bruto para superfícies logadas e não indexadas, como dashboards.
Roteamento em URLs com hash (HashRouter)
Recorrer ao HashRouter do React Router porque é o caminho de menor resistência —
sem necessidade de configuração de servidor, funciona em qualquer host estático. Por que está errado: o Google não
consegue resolver de forma confiável URLs do tipo /#/products; o antigo esquema de rastreamento AJAX que tornava fragmentos de hash
rastreáveis está obsoleto. O que fazer em vez disso: use BrowserRouter (a
API History) e certifique-se de que o servidor responda a cada rota que ele produz, incluindo um
acesso direto ou atualização em um link profundo.
Construindo navegação com onClick em vez de âncoras reais
Configurar a navegação com manipuladores onClick em um <div> ou <button>, muitas vezes porque era
mais fácil estilizar ou evitar o comportamento padrão do link. Por que está errado: o Google só
segue links reais <a href> — um <div> com um manipulador de clique é invisível para o rastreamento,
não importa como se comporte para um mouse. O que fazer em vez disso: use o componente
<Link> do React Router, que renderiza um <a href> real internamente, ou uma âncora simples
para navegação externa.
Carregando o conteúdo principal atrás de uma cascata lenta de APIs
Buscar o cabeçalho e a navegação rapidamente e, em seguida, encadear várias chamadas de API antes que o conteúdo real da página — a parte que torna cada URL única — apareça. Por que está errado: o serviço de renderização da Web do Google impõe um tempo limite; se o conteúdo principal carregar lentamente, a renderização termina antes que ele chegue, e o Google fica indexando apenas páginas de boilerplate que são então sinalizadas como duplicatas umas das outras — exatamente o modo de falha que Gary Illyes descreveu. O que fazer em vez disso: reestruture as solicitações para que o conteúdo principal carregue primeiro, ou remova a dependência da renderização no lado do cliente inteiramente com SSR/SSG.
Ainda usando o react-helmet original
Recorrer ao react-helmet para <title> e meta tags por rota porque é a
biblioteca que todo tutorial mais antigo recomenda. Por que está errado: o pacote original está
sem manutenção — nenhum lançamento desde 2020 — e tem problemas conhecidos com a renderização concorrente do React 18
e SSR. O que fazer em vez disso: no React 19, renderize <title>/<meta>/<link>
diretamente em seus componentes e deixe o React içá-los (nenhuma biblioteca necessária para o básico).
No React 18, ou para necessidades avançadas como serialização de contexto SSR ou titleTemplate, use
react-helmet-async, o fork mantido. No Next.js, use sua API de metadados integrada e
não adicione Helmet por cima dela.
Bloqueando JavaScript ou CSS em robots.txt
Bloquear /static/js/ ou a pasta de assets de um bundler em robots.txt, às vezes sobrando
de uma preocupação antiga com orçamento de rastreamento ou copiado da configuração de outro site. Por que está
errado: o Google não pode renderizar o que não tem permissão para buscar — um bundle bloqueado significa que o
serviço de renderização da Web constrói um DOM incompleto (ou vazio), mesmo que seu código-fonte
esteja correto. O que fazer em vez disso: permita que os rastreadores busquem seu JS e CSS, e confirme isso
com a verificação de recursos da página da ferramenta Inspeção de URL para ver se nada crítico está bloqueado.
Teste-se: SEO para React
Cinco perguntas rápidas sobre como tornar aplicativos React rastreáveis e indexáveis. Escolha uma resposta para cada, depois confira.
Recursos que valem seu tempo
Meus escritos relacionados
- SEO para React: Melhores Práticas para Torná-lo Amigável para SEO (Ahrefs) — o guia de SEO para React na Ahrefs, que revisei; este artigo é o tratamento mais profundo e com links para fontes.
- SEO para JavaScript: Um Guia Definitivo (Ahrefs) — meu guia completo sobre os mecanismos de renderização subjacentes: paridade de DOM, a regra da diretiva mais restritiva, tratamento de canônicos e meta tags, e escolhas de renderização. Leia isto para o caso geral por trás das correções específicas do React.
- O Guia do Iniciante para SEO Técnico (Ahrefs) — onde o SEO para React/JavaScript se encaixa no panorama geral.
Minhas palestras
- Como a Busca Funciona (SlideShare) — minha explicação sobre rastreamento, renderização, indexação e ranqueamento. (Minha ressalva padrão se aplica: “This is my understanding of systems… not going to be 100% complete or accurate.” (tradução) «Esta é a minha compreensão dos sistemas… não será 100% completa ou precisa.»)
Do setor
- Entenda os fundamentos de SEO para JavaScript (Google) — documentação de fonte primária sobre SPAs, a History API e o tratamento de canônicos/códigos de status.
- Renderização dinâmica (obsoleta) (Google) — por que a renderização dinâmica é um paliativo, não uma solução de longo prazo.
- Martin Splitt explica como sites em JavaScript são indexados (Search Engine Journal) — a explicação do “HTML básico … boom” do fluxo de rastreamento → renderização → indexação.
- Gary Illyes sobre sites com muito JavaScript e conteúdo duplicado (LinkedIn) — o modo de falha de timeout de renderização para duplicatas, nas próprias palavras dele.
- Como corrigir problemas técnicos de SEO em aplicativos React no lado do cliente (Search Engine Land) — um estudo de caso real sobre auditoria e correção de um aplicativo React CSR.
- SSR vs. renderização dinâmica — sem diferença de ranqueamento (Search Engine Roundtable) — a declaração de Mueller sobre “sem bônus de ranqueamento de SEO”.
- react-helmet-async (npm) — a biblioteca mantida de gerenciamento de head para React autônomo.
- O novo Bingbot evergreen (Microsoft Edge) (Bing) — o Bingbot renderizando JS via Chromium, como o Googlebot.
Vídeos
- Google Search Central — série de SEO para JavaScript (YouTube) — a série oficial de vídeos de Martin Splitt cobre SEO para React, Angular e Vue especificamente, percorrendo o processo de rastreamento → renderização → indexação e as correções comuns. Anúncio da série · Canal
Registro de alterações
Atualizado em 22 de ago. de 2026.
Resumo editorial e detalhes registrados da alteração.Detalhes da alteração
-
As notas detalhadas sobre as alterações estão disponíveis atualmente em inglês.
-
As notas detalhadas sobre as alterações estão disponíveis atualmente em inglês.
Não é possível fazer a comparação completa — nenhum instantâneo anterior foi arquivado para esta revisão.
Atualizado em 18 de jul. de 2026.
Resumo editorial e detalhes registrados da alteração.Detalhes da alteração
-
As notas detalhadas sobre as alterações estão disponíveis atualmente em inglês.
-
As notas detalhadas sobre as alterações estão disponíveis atualmente em inglês.
-
As notas detalhadas sobre as alterações estão disponíveis atualmente em inglês.
Não é possível fazer a comparação completa — nenhum instantâneo anterior foi arquivado para esta revisão.