SEO para Cloudflare Workers

Como fazer mudanças técnicas de SEO no Cloudflare Workers — o handler fetch, HTMLRewriter para injetar canonical/hreflang/JSON-LD, redirecionamentos com KV, Cache API versus cache de borda versus Cache-Control, a fronteira do cloaking e como o Bot Fight Mode pode bloquear o Googlebot.

Publicado pela primeira vez: 3 de jul. de 2026 · Última atualização: 2 de set. de 2026 · Avançado
1 sinal de evidência nesta página

SEO para Cloudflare Workers é fazer SEO técnico no runtime serverless da Cloudflare: um Worker só vê as solicitações que correspondem à sua rota, e cada uma entra em um único handler fetch, onde você reescreve a solicitação, os cabeçalhos da resposta e o corpo. A reescrita do corpo usa HTMLRewriter — o mecanismo real para injetar canonical, corrigir hreflang ou adicionar JSON-LD sem um deploy do CMS — e precisa ser idempotente em casos ausentes, duplicados e não HTML. Redirecionamentos em escala pertencem a KV ou D1; Bulk Redirects/Rules são mais simples para conjuntos pequenos, mas escolha um responsável por URL para evitar conflitos. Três coisas compartilham o nome cache — Workers Cache API, cache de borda da Cloudflare e Cache-Control da origem — e confundi-las faz uma tag parecer não ter sido publicada; diagnostique por chave, camada, TTL e invalidação. A regra absoluta é cloaking: aplique lógica idêntica ao Googlebot e aos usuários. O problema mais específico dos Workers é o Bot Fight Mode bloquear o Googlebot em um pipeline que as regras de permissão do WAF não alcançam. Publique toda mudança que afete SEO com metadados de versão e rollback testado, depois verifique com a Inspeção de URL do GSC e o cabeçalho CF-Cache-Status.

TL;DR — Um Cloudflare Worker só vê solicitações que correspondem à rota configurada e intercepta cada uma em um único handler fetch, onde você faz três coisas em sequência: reescreve a solicitação, os cabeçalhos da resposta e o corpo da resposta com HTMLRewriter. Esse é o mecanismo real por trás de “injetar um canonical” ou “corrigir um título” — e ele precisa ser idempotente e testado em respostas ausentes, duplicadas e não HTML, não apenas no caminho ideal. Redirecionamentos em escala ficam em KV (consulta rápida por chave) ou D1 (relacional); Bulk Redirects/Rules atendem conjuntos pequenos de modo mais simples, e em geral prefiro redirecionamentos na borda aos do servidor — mas escolha um responsável por URL, pois um redirecionamento do Worker, um Bulk Redirect e um da origem podem ser acionados no mesmo caminho. Três coisas diferentes compartilham a palavra “cache” — Workers Cache API (caches.default), cache de borda da Cloudflare e Cache-Control da origem — e confundi-las costuma causar “minha tag não apareceu”; diagnostique conteúdo desatualizado por chave, camada, TTL e invalidação, em vez de adivinhar. As orientações do Google sobre ETag / If-None-Match / 304 podem ser aplicadas diretamente por um Worker responsável pela resposta. A linha do cloaking: lógica idêntica para todos. O maior risco específico de Workers causado pela própria equipe é o Bot Fight Mode, executado fora do WAF Ruleset Engine, de modo que regras comuns de “allow” não o alcançam. Publique toda mudança de SEO com metadados de versão registrados, rollback testado e condição de interrupção — depois valide com a Inspeção de URL do GSC e CF-Cache-Status.

O que este artigo é (e o que não é)

Este é o complemento prático e voltado ao código do hub de Edge SEO. O hub reúne a definição geral, a tabela de comparação entre plataformas (Workers, Akamai, Fastly, Lambda@Edge, Vercel, Netlify), a decisão Snippets versus Workers e o tratamento completo da regra de cloaking. Não repetirei tudo aqui. Esta página desce um nível e trata especificamente do Cloudflare Workers — o runtime em que o Worker deste próprio site é executado, conectado por run_worker_first em wrangler.toml — com APIs reais, em vez de afirmações vagas de que “edge compute pode injetar tags”.

Uma observação antes do código: o Google não tem documentação específica sobre Cloudflare Workers. As orientações oficiais que regem esta implementação (política de cloaking, cache HTTP e rastreamento via CDN) são gerais e valem para qualquer implementação na borda. Prefiro dizer isso claramente a insinuar que existe um documento do Google que não existe.

Como um Worker entra no caminho da solicitação e da resposta

Um Worker é um script serverless executado em isolates V8. Toda solicitação roteada até ele entra por um handler fetch. Evidência desta afirmação A Cloudflare Worker receives HTTP requests through a fetch handler. Escopo: Cloudflare Workers handlers. Confiança: alta · Verificado: Cloudflare Workers: Fetch handler “Roteada até ele” é uma parte importante: o Worker só vê solicitações que correspondem à rota ou ao domínio personalizado configurado — tudo o mais jamais chega ao handler fetch. Quando duas rotas podem corresponder à mesma URL, o padrão mais específico tem precedência; antes de confiar no comportamento de um Worker para uma URL, confirme se a rota realmente corresponde e qual versão implantada está ativa nela (ambientes Wrangler e rollouts graduais significam que a versão que atende tráfego nem sempre é a que está no editor). Dentro do handler, você pode fazer três coisas distintas, nesta ordem:

  1. Reescrever a solicitação antes que ela siga para a origem.
  2. Reescrever os cabeçalhos da resposta no caminho de volta.
  3. Reescrever o corpo da resposta — com HTMLRewriter.

Esta é a estrutura mínima:

export default {
  async fetch(request, env, ctx) {
    // 1. (optionally) inspect/modify the request
    const response = await fetch(request);   // hit the origin

    // 2. rewrite headers
    const headers = new Headers(response.headers);
    headers.set("X-Robots-Tag", "index, follow");

    // 3. rewrite the body with HTMLRewriter (see next section)
    return new Response(response.body, { ...response, headers });
  },
};

A equipe da SALT.agency, que cunhou “edge SEO” a partir de pesquisas com Cloudflare Workers, construiu suas ferramentas como uma cadeia de filtros — um filtro de solicitação, um de resposta e um de corpo. É o mesmo padrão de três fases; apenas recebeu outros nomes. Manter essas fases separadas na cabeça mantém o Worker legível.

Reescrevendo HTML com HTMLRewriter

HTMLRewriter é o parser de streaming de HTML da Cloudflare e a API real por trás de todo truque para “injetar uma tag”. Evidência desta afirmação Cloudflare HTMLRewriter provides selector-based handlers that can transform streamed HTML elements. Escopo: Cloudflare Workers HTMLRewriter API. Confiança: alta · Verificado: Cloudflare Workers: HTMLRewriter Você registra handlers de elementos com .on(selector, handler), e o handler recebe getAttribute / setAttribute, prepend / append, setInnerContent e replace. Como trabalha por streaming, não é preciso carregar o documento inteiro na memória.

Injetando ou corrigindo uma tag canonical

class CanonicalHandler {
  constructor(url) { this.url = url; }
  element(el) { el.setAttribute("href", this.url); }
}

const rewriter = new HTMLRewriter()
  .on('link[rel="canonical"]', new CanonicalHandler("https://example.com/preferred/"));

return rewriter.transform(response);

Se a página não tiver canonical, associe um handler a head e use append para adicionar uma, em vez de editar uma tag existente. Em qualquer caso, lembre a lição da canonicalização: rel=canonical é uma sugestão, não uma ordem — um Worker permite defini-la de modo consistente em toda a plataforma, mas o Google ainda decide.

O CanonicalHandler acima presume que a tag existe e que a resposta é HTML. Nada disso é garantido em produção, e errar aqui é como você acaba com duas tags canonical na mesma página, em vez de uma. Antes de publicar uma reescrita assim, torne-a idempotente e teste-a em:

  • Nenhuma canonical existente — o handler precisa detectar a ausência e usar append em head, não simplesmente deixar de fazer algo quando link[rel="canonical"] não encontrar correspondência.
  • Uma canonical duplicada ou malformada já presente — decida se removerá a tag perdida ou deixará a reescrita adicionar uma segunda (isso é um bug real, não um caso raro — canônicos duplicados são um problema comum criado pela própria equipe).
  • Uma resposta não HTML — uma rota de API, imagem ou redirecionamento que passe pelo mesmo Worker não deve entrar no HTMLRewriter; limite a transformação às rotas e aos tipos de conteúdo efetivamente verificados.
  • Executar a transformação duas vezes na mesma resposta (nova tentativa ou fetch aninhado) — confirme que ela não adiciona uma segunda tag.

Adicionando ou corrigindo alternativas hreflang

O mecanismo é o mesmo, orientado por configuração. Adicione um link[rel="alternate"] por locale a head. Se as alternativas forem por locale e relacionais, a configuração pertence ao D1; para consulta simples, KV funciona. O ponto é que HTMLRewriter as injeta de forma idêntica para todos — sem ramificar por user agent.

Injetando dados estruturados JSON-LD

new HTMLRewriter().on("head", {
  element(head) {
    head.append(
      `<script type="application/ld+json">${JSON.stringify(schema)}</script>`,
      { html: true }
    );
  },
});

Limites de CPU que aparecem em escala

Uma afirmação concorrente que eu contestaria é “menos de um milissegundo, sem restrições”. O teto real é o tempo de CPU: 10 ms no plano gratuito, 30 ms nos pagos (tempo de relógio esperando por fetch não conta — tempo de CPU conta). Em reescritas comuns, você nunca perceberá. Em passagens pesadas de HTMLRewriter por páginas muito grandes, é uma restrição real a considerar no projeto, não alarmismo.

Redirecionamentos na borda: KV versus D1 versus Rules

Em geral, prefiro redirecionamentos na borda (no nível da CDN) aos do servidor — isso tira trabalho da origem e é aplicado antes mesmo de a página ser gerada. Na Cloudflare, meu guia da Ahrefs sobre redirecionamentos para SEO mostra várias opções: redirecionamentos individuais ou em massa, Redirect Rules, Page Rules, Workers com pares chave-valor ou um Worker que altera cabeçalhos para adicionar um redirecionamento.

Para uma tabela orientada por Worker, KV é o lugar natural: uma consulta rápida e com consistência eventual, cuja chave é a URL.

export default {
  async fetch(request, env) {
    const url = new URL(request.url);
    const target = await env.REDIRECTS.get(url.pathname);   // KV namespace
    if (target) return Response.redirect(target, 301);
    return fetch(request);
  },
};

Use D1 quando os redirecionamentos forem relacionais (por locale, por segmento, com SQL que você quer consultar). E saiba quando um Worker é exagero: para um conjunto pequeno e estático, Bulk Redirects ou Redirect Rules da Cloudflare são mais simples e dispensam código. Não crie um Worker KV manualmente para cinquenta redirecionamentos.

Escolha um responsável por URL e não permita que um redirecionamento do Worker, um Bulk Redirect, uma Redirect Rule e um redirecionamento da origem sejam aplicados ao mesmo caminho — são sistemas separados que podem ser acionados na mesma solicitação; quando mais de um corresponde, você depura precedência em vez de um redirecionamento limpo. Antes de adicionar qualquer redirecionamento, verifique se ele já existe nos outros sistemas e escolha a camada conforme a complexidade da correspondência (simples 1:1 ou padrão), escala e quem precisa observá-lo ou revertê-lo — um redirecionamento do Worker fica no código e nos logs; um Bulk Redirect ou Rule fica no painel e é mais fácil para alguém sem conhecimento de desenvolvimento auditar ou reverter.

Cache: três coisas diferentes, um nome confuso

Esta é a seção que páginas concorrentes ignoram e que gera mais confusão do tipo “por que minha mudança não apareceu?”. Três camadas distintas compartilham a palavra cache:

  • Workers Cache API — caches.default e caches.open(). É um cache programável e específico do Worker, lido e gravado por código.
  • Cache de borda da Cloudflare — o cache da CDN que serve seus ativos. É distinto da Cache API.
  • Cache-Control da origem — os cabeçalhos definidos pela origem (ou pelo Worker), que influenciam as duas opções acima e o comportamento do Googlebot.

Misture os três e você terá certeza de que uma mudança não foi publicada, quando ela apenas está sendo servida por uma camada que você não limpou.

Quando uma mudança realmente não aparecer, não adivinhe — diagnostique camada por camada:

  1. Chave do cache. Quais atributos da solicitação determinam se duas solicitações encontram a mesma entrada em cache (URL e, às vezes, cabeçalhos ou cookies, caso façam parte da chave)? Uma reescrita que varie por algo ausente da chave pode servir a variante errada.
  2. Qual camada serviu a resposta. Verifique CF-Cache-Status (HIT/MISS/EXPIRED/DYNAMIC) para saber se o cache de borda respondeu ou se a solicitação chegou ao Worker.
  3. Local/estado. O cache da Cloudflare é distribuído por data centers — uma limpeza ou um deploy novo não invalida necessariamente todos os pontos de borda no mesmo instante.
  4. TTL e a regra que o definiu. Confirme se o TTL é controlado por Cache Rule, cabeçalho Cache-Control da origem ou cabeçalho definido pelo próprio Worker.
  5. Invalidação. Você limpou uma URL, limpou tudo ou esperou o TTL expirar? Uma entrada da Cache API controlada pelo Worker (caches.default) exige seu próprio delete() explícito — limpar o cache da CDN não a afeta.

O que o Googlebot faz com ETag / If-None-Match / 304

Se o Worker gera ou reescreve a resposta, ele controla os cabeçalhos de cache — por isso, as orientações do Google de dezembro de 2024 podem ser aplicadas diretamente. O Google aceita cache HTTP heurístico com ETag/If-None-Match e Last-Modified/If-Modified-Since, recomenda fortemente ETag porque tende a provocar menos erros e informa que, quando o ETag do crawler corresponder, o servidor deve retornar 304 Not Modified sem corpo. Um Worker que gera a resposta pode implementar isso: calcular ETag, compará-lo a If-None-Match e devolver 304 diretamente — poupando processamento e oferecendo ao Googlebot um sinal rápido e armazenável em cache.

A contrapartida de max-age para novo rastreamento

O Google também recomenda considerar Cache-Control: max-age para ajudar crawlers a decidir quando rastrear novamente. O problema para um Worker que reescreve HTML: um max-age agressivo em uma página cujas tags injetadas acabaram de mudar pode adiar a descoberta da atualização pelo Googlebot. Não aplique uma duração longa a HTML reescrito e esqueça o assunto.

A fronteira do cloaking aplicada a Workers

A regra absoluta, em termos de Workers, é executar a mesma lógica para todos. A política antispam do Google define cloaking como apresentar conteúdo diferente a usuários e mecanismos de busca para manipular rankings e cita especificamente inserir texto ou palavras-chave apenas quando quem solicita é um mecanismo de busca.

Alguns esclarecimentos, porque é comum exagerar na correção:

  • Inspecionar o User-Agent não é cloaking automaticamente. Registrar tráfego de bots ou servir uma resposta em cache mais rápido a qualquer cliente não tem problema. A linha é uma diferença de conteúdo por identidade de quem solicita, feita para manipular rankings.
  • Testes A/B com divisão de páginas em Workers são permitidos. Dividir usuários por URL e tratar todos da mesma forma é legítimo. Dividir conforme quem pede — bot versus pessoa — não é.

Um exemplo prático do padrão seguro: o gate de preview deste site é um Worker que retorna 404 para qualquer caminho /preview/, a menos que um cookie corresponda a um segredo. Ele retorna esse 404 a todos sem o cookie — inclusive ao Googlebot. Esse é exatamente o formato seguro: ele não esconde uma coisa de bots e mostra outra a usuários; aplica uma única regra uniformemente.

E não dependa de uma etapa de pré-renderização exclusiva para bots, mesmo que seja implementada corretamente em Workers. O Google chamou a renderização dinâmica de solução alternativa, não solução de longo prazo; um Worker que pré-renderiza apenas para bots herda essa descontinuação.

Como um Worker pode bloquear ou desacelerar o Googlebot por acidente

Esta é a forma mais específica de Workers de causar o próprio problema, e geralmente não está no código do Worker.

O Bot Fight Mode é executado fora do Ruleset Engine

Bot Fight Mode (e Super Bot Fight Mode) pode gerar falsos positivos contra crawlers legítimos, inclusive o Googlebot. A armadilha: o Bot Fight Mode é avaliado em um pipeline separado do WAF Ruleset Engine; portanto, regras comuns de “allow” ou “skip” do WAF não o substituem. Se o Bot Fight Mode desafiar o Googlebot, uma regra de permissão não resolve — é preciso alterar ou desativar o próprio modo. (Confirme a mecânica atual na documentação de Bot Fight Mode e Super Bot Fight Mode da Cloudflare antes de depender dela — produtos de bots mudam.)

O padrão de regra personalizada para bots verificados

A Cloudflare expõe o campo cf.client.bot e um padrão de permissão de bots verificados para autorizar crawlers conhecidos em regras personalizadas — útil do lado do WAF, embora, como explicado acima, não alcance o Bot Fight Mode.

A CDN em si é neutra ou positiva

Para desfazer o mito: a Cloudflare como CDN não prejudica o SEO. A série de 2024 do Google Crawling December observa que o Google aumenta a taxa de rastreamento quando detecta uma CDN — mas que uma CDN também pode bloquear o Googlebot por engano com regras de WAF/bots e que um 503 é melhor do que um intersticial de verificação de bot. O risco é um Worker ou configuração de bots mal configurado, não a infraestrutura.

Verificando o que o Googlebot realmente recebeu

Depois de qualquer deploy do Worker, confirme o que o crawler realmente recebeu — não presuma:

  • Inspeção de URL do GSC → Testar URL publicada. Busca a página como o Google e mostra o HTML renderizado, permitindo confirmar que canonical/hreflang/JSON-LD injetado realmente aparece.
  • Verifique CF-Cache-Status junto com o HTML. HIT / MISS / EXPIRED mostra se você está vendo uma resposta nova do Worker ou uma versão em cache — o modo mais rápido de encontrar uma “mudança que não apareceu” por causa da camada de cache.
  • Busque diretamente como Googlebot. Faça a solicitação com o user agent do Googlebot e compare — mas lembre que a string não comprova identidade; verifique o Googlebot real com DNS reverso + direto nos intervalos publicados pelo Google (veja a aba Scripts).

Higiene de implantação específica para Workers

Um wrangler deploy bem-sucedido informa que o script foi publicado — não que o Googlebot recebeu a saída renderizada correta. Trate toda mudança do Worker que afete SEO como um lançamento documentado, não apenas um push:

  • Limite suas rotas. Não execute o Worker em /* por padrão. Faça-o corresponder aos caminhos necessários nos padrões de rota de wrangler.toml, para que um bug não derrube o site inteiro.
  • Confira os limites atuais antes de prometer escala. Tempo de CPU, número de subrequests e tamanho do script variam por plano e ao longo do tempo — confirme na página atual de limites da Cloudflare antes de projetar uma reescrita com base em um teto específico, em vez de confiar em um número lembrado.
  • Registre metadados de versão do lançamento. O modelo de versões e implantações da Cloudflare acompanha versão-fonte, data de compatibilidade, bindings e rotas de cada deploy — registre qual versão está ativa em qual rota, para que a afirmação “o Worker faz X” possa ser comparada ao que está implantado, e não ao editor.
  • Versione e faça rollback com ambientes Wrangler. Publique em staging, faça rollout gradual por porcentagem e preserve a capacidade de retornar imediatamente à versão anterior.
  • Use logs com escopo para acompanhar o rollout — considerando seus limites. Os Workers Logs e o tail de logs ajudam a depurar rollouts graduais, mas os logs são amostrados e retidos por pouco tempo — trate-os como evidência das solicitações capturadas, não como registro completo de toda visita de crawler.
  • Defina uma condição de interrupção e teste o rollback antes de precisar dele. Decida de antemão qual comportamento observado (taxa de erros, resposta incorreta em uma verificação ou queda da taxa de rastreamento) interrompe o rollout e confirme que o rollback funciona, em vez de presumir.
  • Limpe o cache como parte do deploy. Como há três camadas, torne a limpeza ou invalidação uma etapa explícita da publicação, não uma reflexão tardia.

Uma observação sobre o Bing e algo para o futuro

O Bing também não tem orientação específica para Cloudflare/borda. Porém, como um deploy do Worker é instantâneo e o rastreamento não, IndexNow é o par natural — acione-o assim que uma tabela de redirecionamentos ou mudança de tag do Worker for publicada, para que o Bing (e outros mecanismos participantes) rastreie novamente sem demora. Também vale observar que a Cloudflare lançou canonicalização aplicada na borda como recurso do produto (“Redirects for AI Training”) — crawlers verificados de treinamento de IA recebem um 301 para sua URL canônica com um botão. É um contraste útil com implementar a lógica canônica manualmente em seu Worker e um lembrete de que “servir algo diferente a crawlers e usuários” é um padrão sobre o qual a Microsoft expressou ceticismo público em outros recursos da Cloudflare para crawlers de IA — uma boa verificação intuitiva para qualquer Worker condicional por bot.

Para a visão mais ampla — comparação de plataformas, Snippets versus Workers, fila de desenvolvimento e governança — volte ao hub de Edge SEO.

Adicionar uma nota de especialista

Fixar uma citação de especialista

É uma pessoa nova? Crie o perfil não reivindicado dela em /admin/experts/ → Fixar uma citação de especialista primeiro.