Voltar ao Blog
Angular Development11 de novembro de 20268 min de leitura

Seu Site JavaScript É Invisível para a Busca com IA? Como Verificar e Corrigir

DR

Doug Ribeiro

8 min de leitura

Um app Angular renderizado no cliente parece completo no navegador e quase vazio para qualquer bot que não roda JavaScript. Antes de migrar meu portfólio para pré-renderização estática, medi essa baseline do jeito que um crawler desses mediria. Um post do blog com pouco mais de mil palavras voltou como um app-root vazio, com o mesmo título genérico que todas as páginas compartilhavam. O artigo só existia depois que o Angular subia num navegador.

Depois da migração, a mesma URL retorna cerca de 1.300 palavras no HTML inicial, com título próprio. Essa contagem inclui o header e o footer, mas a diferença é o artigo inteiro. O conteúdo em si não mudou.

O Que os Crawlers Realmente Fazem

O Google é a exceção famosa, e enganou uma geração inteira de nós. A documentação dele descreve três fases: crawl, render, index. As páginas esperam numa fila até que um Chromium headless consiga executar o JavaScript. Então um app renderizado no cliente consegue ranquear no Google, e isso nos ensinou que crawlers rodam JavaScript. O mesmo guia ainda diz que renderização no servidor ou pré-renderização vale a pena, porque nem todos os bots conseguem rodar JavaScript.

A medição que mais vejo citada para os outros é a da Vercel, de dezembro de 2024. Ela concluiu que os crawlers da OpenAI, o ClaudeBot da Anthropic e os crawlers da Meta, da ByteDance e da Perplexity não renderizavam JavaScript. Os crawlers do ChatGPT e do Claude baixavam arquivos JavaScript, mas não os executavam. O Gemini, na infraestrutura do Google, e o AppleBot renderizavam. Esses dados têm quase dois anos, e não encontrei um estudo mais novo da mesma qualidade. Crawlers mudam, então verifique no seu próprio site e nos seus próprios logs.

O Teste de Um Minuto

Escolha uma página real de conteúdo e uma frase curta do meio dela, sem pontuação, porque entidades HTML causam zeros falsos. Depois peça a página do jeito que um crawler simples pediria. O grep conta as linhas que batem, então zero significa que a frase não está no HTML que foi servido. Um acerto pode vir de um blob de estado em JSON e não do markup, então abra a saída e olhe se a contagem te surpreender.

bash
# Is the content in the HTML the server sends?
curl -sL https://example.com/some-article | grep -c "a short phrase from the middle"

# Is your host or CDN treating a bot differently?
curl -sL -o /dev/null -w '%{http_code}\n' -A "GPTBot" https://example.com/some-article

# Does a page that does not exist return a real 404?
curl -sL -o /dev/null -w '%{http_code}\n' https://example.com/this-page-does-not-exist

Na baseline renderizada no cliente, o primeiro retornou 0 e o terceiro retornou 200. Esse último é um soft 404. Hospedagem de single-page app normalmente reescreve toda URL desconhecida para o index.html, então os bots recebem um status de sucesso e uma casca vazia para cada link morto. É a falha que as pessoas deixam passar, porque a página parece certa no navegador, onde o app renderiza uma tela bonita de não encontrado.

Saiba Qual Bot É Qual Antes de Mexer no robots.txt

Bloquear bots de IA costuma ser uma única decisão tomada sobre três coisas diferentes. Os fornecedores separam essas coisas, e a distinção decide o que você perde.

  • Treinamento: GPTBot e ClaudeBot. Bloquear esses diz que seu conteúdo não deve ser usado para treinar modelos.
  • Índice de busca: OAI-SearchBot e Claude-SearchBot. Bloqueie o OAI-SearchBot e a OpenAI diz que seu site não vai aparecer nas respostas de busca do ChatGPT, embora ainda possa aparecer como link de navegação. A Anthropic avisa que bloquear o Claude-SearchBot pode reduzir sua visibilidade nos resultados de busca dela.
  • Acesso disparado pelo usuário: ChatGPT-User e Claude-User. Esses buscam uma página porque uma pessoa pediu. A Anthropic diz que bloquear o Claude-User pode reduzir a visibilidade em buscas direcionadas pelo usuário. A OpenAI diz que o ChatGPT-User não é o que determina se o conteúdo aparece na busca, e que as regras do robots.txt podem não se aplicar a ele.

Então você pode recusar o treinamento e continuar encontrável. Veja como isso fica. Meu próprio site libera tudo, porque um portfólio quer ser lido, mas este é o arquivo do qual eu partiria se não quisesse alimentar treinamento:

text
User-agent: GPTBot
Disallow: /

User-agent: ClaudeBot
Disallow: /

User-agent: *
Allow: /

Sitemap: https://example.com/sitemap.xml

Vá ler seu robots.txt atual agora. Se alguém adicionou um bloqueio geral de IA alguns anos atrás, confira se ele também pega os bots de busca. Confira também qualquer configuração de proteção contra bots no seu CDN, que pode bloquear crawlers que o robots.txt libera. O segundo curl acima consegue pegar um bloqueio baseado em user agent, mas não um baseado em IP.

Deixei o llms.txt de Lado, e as Evidências Sustentam Isso

O llms.txt é uma proposta de setembro de 2024 do Jeremy Howard para um arquivo Markdown que aponta os modelos de linguagem para o seu conteúdo principal. Não é um padrão ratificado. É barato, então as pessoas adicionam esperando citações em IA. As evidências não estão do lado delas.

  • A Ahrefs analisou logs de servidor de 137.000 domínios, todos clientes do próprio analytics dela, então trata os 28% que publicam o arquivo como um limite superior. 97% desses arquivos receberam zero requisições em maio de 2026.
  • A SE Ranking estudou cerca de 300.000 domínios e não encontrou ligação mensurável entre ter o arquivo e ser citado.
  • A orientação do Google diz que você não precisa de novos arquivos legíveis por máquina nem de arquivos de texto para IA para aparecer nos AI Overviews ou no AI Mode. O John Mueller também disse que sistemas de LLM não podem confiar no arquivo como forma de diferenciar sites.

Um contraponto honesto. A Ahrefs encontrou o GPTBot e o Claude Code perto do topo dos agentes de IA que buscam esses arquivos, embora o GPTBot tenha sido só cerca de 4,5% dos acessos, e o Chrome adicionou uma checagem de llms.txt às auditorias agênticas experimentais do Lighthouse. Se você mantém um site de documentação que agentes de código leem, o arquivo pode valer os poucos minutos de trabalho. Para um site de marketing, um blog ou um portfólio, eu gastaria esses minutos no HTML. Meu site não tem um.

O Que a Correção Exigiu numa Hospedagem Estática

Você não precisa de um servidor Node para isso. Meu site fica em hospedagem estática, e a pré-renderização custa tempo de build mais uma restrição real: mudar conteúdo agora significa um rebuild e um deploy. O Angular tem isso embutido: adicione o @angular/ssr, defina o outputMode como static no angular.json e dê a cada rota pública o modo Prerender. Rotas com parâmetros precisam declarar seus valores em tempo de build, e essa é a parte que exige reflexão:

typescript
// app.routes.server.ts (simplified)
export const serverRoutes: ServerRoute[] = [
  {
    path: 'blog/:slug',
    renderMode: RenderMode.Prerender,
    getPrerenderParams: async () => postSlugs().map(slug => ({ slug })),
  },
  { path: '**', renderMode: RenderMode.Client }, // the shell I publish as 404.html
];

No React, a mesma decisão cai num framework: Astro, Next.js ou React Router em framework mode. O static export do Next.js abre mão da renderização por requisição, então confira antes de escolhê-lo. A ferramenta não importa. Decida por rota: conteúdo que qualquer um pode ler recebe HTML em tempo de build, conteúdo que muda por requisição recebe renderização no servidor, e qualquer coisa atrás de login pode continuar renderizada no cliente, porque nenhum crawler chega lá mesmo.

O build gera cerca de 300 páginas em quatro idiomas. A renderização foi a metade fácil. Aqui está o resto:

  • Um title específico da página e uma description e um canonical únicos em cada página, no HTML inicial.
  • Hreflang só entre traduções reais. Uma página que cai no fallback para o inglês recebe um canonical para a URL em inglês e nenhum alternate.
  • Um sitemap gerado em tempo de build a partir dos dados dos posts, e um build que falha se as contagens de posts não baterem.
  • Uma URL por página. Escolha com barra no final ou sem barra no final e redirecione a outra. O Apache adiciona o próprio redirect de diretório, então desliguei isso com DirectorySlash Off, adicionei um rewrite para o index.html de cada pasta e mantive a listagem de diretórios desligada.
  • Um status 404 de verdade. Um 404.html via ErrorDocument, não um rewrite para o index.html.
  • Hidratação que não briga com o HTML estático. No Angular, olhe o provideClientHydration e o transfer cache dele. Qualquer coisa que dependa da página finalizada, como rolar até uma âncora, precisa esperar o ApplicationRef.whenStable. O sintoma típico é um link que rola antes de a seção ter carregado.

O Que a Pré-renderização Não Promete

HTML legível faz você ser considerado. É só isso que ele te dá. Nada aqui garante que uma resposta de IA vai te citar. O que posso dizer é que a falha é binária: conteúdo que um bot não consegue ler não pode ser citado a partir daquele acesso. Corrija isso primeiro, porque é a única parte da discussão sobre busca com IA que você controla por completo.

Depois do deploy, leia seus logs de acesso em vez de adivinhar. Um grep por GPTBot, OAI-SearchBot, ChatGPT-User, ClaudeBot, Claude-SearchBot, Claude-User e PerplexityBot mostra quem visita e qual status recebe. User agents podem ser falsificados, então trate isso como um sinal aproximado.

Abra seu site com o JavaScript desativado, ou rode um curl nele. O que você vê é o que uma grande parte dos bots que importam para você vê.

Referências

SEOAngularPrerenderingAIWeb Performance