Practical guide
SEO and AI search: how a small site gets found and cited.
A walkthrough of a real setup for a small business site: the meta tags in the head, Open Graph, hreflang, JSON-LD, sitemap.xml, robots.txt for search and AI crawlers, llms.txt, noindex pages and a checklist to make a site indexable.
SEO, GEO e o exemplo usado aquiSEO, GEO and the example used here
SEO (otimização para mecanismos de busca) é tornar o site fácil de rastrear, entender e exibir no Google, Bing e similares. GEO (otimização para mecanismos generativos) é o mesmo esforço para que ChatGPT, Claude, Perplexity e Gemini consigam ler o site e citá-lo ao responder. As duas coisas se apoiam no mesmo alicerce: HTML claro, URLs estáveis, dados estruturados e permissão explícita para os rastreadores.SEO (search engine optimisation) is making a site easy to crawl, understand and display in Google, Bing and the like. GEO (generative engine optimisation) is the same effort so that ChatGPT, Claude, Perplexity and Gemini can read the site and cite it when answering. Both rest on the same foundation: clear HTML, stable URLs, structured data and explicit permission for crawlers.
O exemplo desta nota é o setup de SEO de um site fictício, a Arcada Software (landing pages e sites institucionais), em português e inglês, hospedado na Cloudflare Pages. O domínio arcada.example é reservado para exemplos e não existe de verdade; troque pelo seu. Cada seção mostra o arquivo, explica cada linha e diz o que ele não faz.The example in this note is the SEO setup of a fictional site, Arcada Software (landing pages and business websites), in Portuguese and English, hosted on Cloudflare Pages. The domain arcada.example is reserved for examples and does not really exist; swap in yours. Each section shows the file, explains each line and says what it does not do.
Como uma página chega ao índiceHow a page reaches the index
Um buscador faz quatro coisas em sequência, e cada arquivo desta nota atua em uma delas:A search engine does four things in sequence, and each file in this note acts on one of them:
| EtapaStep | O que aconteceWhat happens | O que você controlaWhat you control |
|---|---|---|
| 1. Descobrir1. Discover | O rastreador acha a URL por links, sitemap ou aviso diretoThe crawler finds the URL through links, a sitemap or a direct ping | sitemap.xml, IndexNow, links internosinternal links |
| 2. Rastrear2. Crawl | Baixa a página, se o robots.txt permitirDownloads the page, if robots.txt allows it | robots.txt, status HTTP, redirecionamentosHTTP status, redirects |
| 3. Indexar3. Index | Entende o conteúdo, escolhe a URL canônica e decide se guardaUnderstands the content, picks the canonical URL and decides whether to store it | title, description, canonical, noindex, JSON-LD, hreflang |
| 4. Exibir4. Serve | Ordena os resultados e monta o trecho exibidoRanks results and builds the displayed snippet | Conteúdo, velocidade, max-snippet, Open GraphContent, speed, max-snippet, Open Graph |
Daí sai uma regra importante: o rastreador precisa conseguir ler a página para obedecer a ela. Por isso um noindex funciona se a página for rastreável, e deixa de funcionar se o robots.txt a bloquear (veja noindex).One important rule follows: the crawler must be able to read a page in order to obey it. That is why a noindex works if the page is crawlable, and stops working if robots.txt blocks it (see noindex).
Tags do <head>Head tags
Este é o <head> da página em português. A versão em inglês (/en/) espelha tudo com lang="en", textos equivalentes (não tradução seca) e canonical /en/.This is the <head> of the Portuguese page. The English version (/en/) mirrors it with lang="en", equivalent texts (not a literal translation) and a /en/ canonical.
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Arcada Software | Landing pages e sites institucionais</title>
<meta name="description" content="A Arcada Software cria landing pages, sites institucionais e pequenos projetos web, com escopo, prazo e preço fechados antes de começar.">
<meta name="robots" content="index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1">
<link rel="canonical" href="https://arcada.example/">
<link rel="manifest" href="/manifest.webmanifest">
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
<link rel="icon" href="/favicon.ico" sizes="48x48">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
<meta name="theme-color" content="#0A0A0A">
<link rel="preload" href="/fonts/newsreader.woff2" as="font" type="font/woff2" crossorigin>
<link rel="stylesheet" href="/style.css?v=0027c125">
<script src="/site.js?v=cb853675" defer></script>
| Tag | Para que serveWhat it is for |
|---|---|
charset, viewport | Codificação correta dos acentos e layout de celular. Sem o viewport, o Google trata a página como não otimizada para mobile.Correct accent encoding and mobile layout. Without the viewport tag, Google treats the page as not mobile-friendly. |
<title> | O título azul nos resultados. Cerca de 50 a 60 caracteres, marca + proposta, único por página e por idioma. É o sinal on-page mais forte.The blue headline in results. About 50 to 60 characters, brand + proposition, unique per page and per language. It is the strongest on-page signal. |
meta description | A frase sob o título. 120 a 155 caracteres, escrita para humanos. Não é fator de ranqueamento, mas o Google a usa como trecho e ela influencia o clique.The sentence under the title. 120 to 155 characters, written for humans. Not a ranking factor, but Google uses it as the snippet and it affects the click. |
meta robots | index, follow é o padrão (explicitar não faz mal). max-snippet:-1, max-image-preview:large e max-video-preview:-1 removem o limite de trecho, para que o buscador possa mostrar e citar mais texto.index, follow is the default (spelling it out does no harm). max-snippet:-1, max-image-preview:large and max-video-preview:-1 remove the snippet limit so the engine may show and quote more text. |
canonical | A URL oficial da página, autorreferente (aponta para si mesma), absoluta e sem parâmetros. Evita que /?utm=x, /index.html e / sejam tratadas como três páginas duplicadas.The official URL of the page, self-referencing (points to itself), absolute and without parameters. It stops /?utm=x, /index.html and / being treated as three duplicate pages. |
manifest, icons, theme-color | Identidade em abas, atalhos de celular e barra do navegador. O favicon.ico na raiz também é o que o Google exibe ao lado do resultado.Identity in tabs, phone shortcuts and the browser bar. The favicon.ico is also what Google shows next to the result. |
preload da fonteof the font | Faz o navegador baixar a fonte do título cedo, acelerando a pintura do h1 (métrica LCP). crossorigin é obrigatório para fontes, mesmo do mesmo domínio.Makes the browser fetch the heading font early, speeding up the paint of the h1 (the LCP metric). crossorigin is mandatory for fonts, even from the same origin. |
?v=hash | O build troca o hash quando o CSS/JS muda, o que permite cache imutável de um ano sem servir arquivo velho.The build changes the hash when the CSS/JS changes, which allows a one-year immutable cache without serving a stale file. |
meta keywords: o Google e o Bing ignoram a tag há anos. Adicioná-la só entrega a lista de termos aos concorrentes.There is no meta keywords: Google and Bing have ignored it for years. Adding it only hands your term list to competitors.Open Graph e Twitter CardsOpen Graph and Twitter Cards
Open Graph (og:*) controla a pré-visualização quando alguém cola o link no WhatsApp, LinkedIn, Facebook, Slack ou iMessage. Os Twitter Cards fazem o mesmo no X. Não ajudam no ranking, mas decidem se o link compartilhado parece confiável.Open Graph (og:*) controls the preview when someone pastes the link into WhatsApp, LinkedIn, Facebook, Slack or iMessage. Twitter Cards do the same on X. They do not help ranking, but they decide whether a shared link looks trustworthy.
<meta property="og:type" content="website">
<meta property="og:site_name" content="Arcada Software">
<meta property="og:title" content="Arcada Software: landing pages e sites institucionais">
<meta property="og:description" content="Landing pages, sites institucionais e pequenos projetos web, com escopo, prazo e preço fechados antes de começar.">
<meta property="og:url" content="https://arcada.example/">
<meta property="og:locale" content="pt_BR">
<meta property="og:locale:alternate" content="en_US">
<meta property="og:image" content="https://arcada.example/og/arcada-pt.png">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:image:alt" content="Arcada Software: desenho de arcada sobre fundo preto">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="Arcada Software: landing pages e sites institucionais">
<meta name="twitter:description" content="Landing pages, sites institucionais e pequenos projetos web, com escopo, prazo e preço fechados antes de começar.">
<meta name="twitter:image" content="https://arcada.example/og/arcada-pt.png">
<meta name="twitter:image:alt" content="Arcada Software: desenho de arcada sobre fundo preto">
<!-- TODO(dono): twitter:site e twitter:creator só com perfil real -->
og:imageem 1200×630 px (proporção 1,91:1), URL absoluta e hospedada no próprio site (aqui em/og/), uma por idioma. Largura e altura declaradas evitam que a primeira partilha saia sem imagem enquanto a rede baixa o arquivo.og:imageat 1200×630 px (1.91:1 ratio), an absolute URL hosted on the site itself (here under/og/), one per language. Declared width and height stop the first share going out without an image while the network fetches the file.og:localeeog:locale:alternateusam o formatopt_BR(com sublinhado), diferente dohreflang, que usapt-BR(com hífen).og:localeandog:locale:alternateuse thept_BRformat (underscore), unlikehreflang, which usespt-BR(hyphen).twitter:card = summary_large_imagereaproveita a mesma imagem. O X também lêog:*quando faltam as tags próprias.twitter:card = summary_large_imagereuses the same image. X also readsog:*when its own tags are missing.twitter:siteetwitter:creatorsó entram com um perfil real. Por isso ficou umTODOno código em vez de um @ inventado.twitter:siteandtwitter:creatoronly go in with a real profile. That is why aTODOwas left in the code instead of an invented handle.- Depois de mudar a imagem, o WhatsApp e o Facebook guardam a antiga em cache; use o Facebook Sharing Debugger ou o LinkedIn Post Inspector para forçar a atualização.After changing the image, WhatsApp and Facebook keep the old one cached; use the Facebook Sharing Debugger or the LinkedIn Post Inspector to force a refresh.
Dois idiomas: hreflangTwo languages: hreflang
<link rel="alternate" hreflang="pt-BR" href="https://arcada.example/">
<link rel="alternate" hreflang="en" href="https://arcada.example/en/">
<link rel="alternate" hreflang="x-default" href="https://arcada.example/">
hreflang diz ao buscador que as duas URLs são o mesmo conteúdo em idiomas diferentes, para mostrar a versão certa a cada pessoa em vez de tratá-las como duplicatas. Regras que costumam dar erro:hreflang tells the search engine the two URLs are the same content in different languages, so it shows each person the right version instead of treating them as duplicates. Rules that commonly go wrong:
- Recíproco: a página PT lista a EN e a EN lista a PT. Sem a volta, o Google ignora o par.Reciprocal: the PT page lists the EN one and the EN lists the PT. Without the return link, Google ignores the pair.
- Inclua a própria página na lista (a PT lista
pt-BRapontando para si).Include the page itself in the list (PT listspt-BRpointing at itself). x-defaulté a versão para quem não casa com nenhum idioma listado; aqui, o português.x-defaultis the version for people who match none of the listed languages; here, Portuguese.- O canonical de cada versão aponta para ela mesma, nunca para a outra. Apontar o canonical da EN para a PT diria ao Google que a EN é cópia e a tiraria do índice.The canonical of each version points to itself, never to the other. Pointing the EN canonical at the PT page would tell Google the EN is a copy and drop it from the index.
- Os mesmos três links aparecem também no sitemap (veja abaixo); basta manter um dos dois lugares coerente com o outro.The same three links also appear in the sitemap (see below); just keep the two places consistent with each other.
Dados estruturados: JSON-LDStructured data: JSON-LD
O HTML descreve como a página aparece; o JSON-LD descreve o que ela é em um vocabulário que máquinas entendem (schema.org). Fica num bloco <script type="application/ld+json">, e como é dado, não executa nada e não precisa de exceção na CSP. Um bloco só, com @graph, liga as entidades por @id:HTML describes how the page looks; JSON-LD describes what it is in a vocabulary machines understand (schema.org). It lives in a <script type="application/ld+json"> block, and being data, it runs nothing and needs no CSP exception. A single block with @graph links the entities by @id:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@graph": [
{
"@type": "Organization",
"@id": "https://arcada.example/#org",
"name": "Arcada Software",
"url": "https://arcada.example/",
"logo": {
"@type": "ImageObject",
"url": "https://arcada.example/icon-512.png",
"width": 512,
"height": 512
},
"description": "Landing pages, sites institucionais e pequenos projetos web.",
"email": "contato@arcada.example",
"areaServed": "BR",
"availableLanguage": ["pt-BR", "en"],
"knowsAbout": ["landing pages", "sites institucionais", "desenvolvimento web", "SEO técnico"]
},
{
"@type": "WebSite",
"@id": "https://arcada.example/#site",
"url": "https://arcada.example/",
"name": "Arcada Software",
"inLanguage": "pt-BR",
"publisher": { "@id": "https://arcada.example/#org" }
},
{
"@type": "WebPage",
"@id": "https://arcada.example/#page",
"url": "https://arcada.example/",
"name": "Arcada Software | Landing pages e sites institucionais",
"inLanguage": "pt-BR",
"isPartOf": { "@id": "https://arcada.example/#site" },
"about": { "@id": "https://arcada.example/#org" },
"dateModified": "2026-10-28"
},
{
"@type": "Service",
"@id": "https://arcada.example/#landing",
"name": "Landing page",
"serviceType": "Desenvolvimento de landing page",
"description": "Uma página com um objetivo: captar contatos ou vender, responsiva, com formulário ou WhatsApp e métricas.",
"provider": { "@id": "https://arcada.example/#org" },
"areaServed": "BR",
"inLanguage": "pt-BR"
},
{
"@type": "FAQPage",
"@id": "https://arcada.example/#faq",
"inLanguage": "pt-BR",
"mainEntity": [
{
"@type": "Question",
"name": "Quanto custa uma landing page?",
"acceptedAnswer": {
"@type": "Answer",
"text": "O preço é fechado na proposta, antes de começar, e depende do número de seções, de integrações como formulário ou WhatsApp e de quanto material você já tem pronto. [...]"
}
}
]
}
]
}
</script>
O bloco acima está abreviado: o real tem três Service (Landing page, Site institucional, Pequenos projetos web) e oito perguntas no FAQPage. A versão em inglês tem a mesma estrutura, com textos e inLanguage em inglês.The block above is abridged: the real one has three Service entries (Landing page, Business website, Small web projects) and eight questions in the FAQPage. The English version has the same structure, with English texts and inLanguage.
| TipoType | O que declaraWhat it declares |
|---|---|
Organization | Quem é a empresa: nome, logo (512×512), e-mail, idiomas, temas (knowsAbout). É o que ajuda o buscador e as IAs a reconhecer a marca como uma entidade. sameAs (perfis em redes) só entra com perfis reais; hoje está omitido.Who the company is: name, logo (512×512), email, languages, topics (knowsAbout). It helps engines and AIs recognise the brand as an entity. sameAs (social profiles) only goes in with real profiles; it is omitted for now. |
WebSite, WebPage | O site e a página, com inLanguage e dateModified real (a data da última mudança de conteúdo, não a de hoje).The site and the page, with inLanguage and a real dateModified (the date the content last changed, not today's). |
Service | Cada serviço, igual à tabela visível. Sem preço, porque o dono não confirmou nenhum.Each service, matching the visible table. No price, because the owner confirmed none. |
FAQPage | Exatamente as mesmas 8 perguntas e respostas do FAQ visível (gerado da mesma fonte de dados), com 40 a 60 palavras cada: curtas o bastante para serem citadas, longas o bastante para fazerem sentido sozinhas.Exactly the same 8 questions and answers as the visible FAQ (generated from the same data source), 40 to 60 words each: short enough to be quoted, long enough to make sense alone. |
AggregateRating, Review, LocalBusiness, Product, HowTo nem Speakable se não houver esses dados na tela. Marcar avaliações que não existem viola as diretrizes do Google e pode render uma ação manual contra o site.The golden rule: JSON-LD may only mirror what is visible on the page. Do not use AggregateRating, Review, LocalBusiness, Product, HowTo or Speakable if that data is not on screen. Marking up reviews that do not exist violates Google's guidelines and can bring a manual action against the site.FAQPage não vira o acordeão nos resultados, mas continua sendo uma forma limpa e legível por máquina de entregar perguntas e respostas a buscadores e IAs. Confira o estado atual na documentação do Google antes de prometer o contrário.Realistic expectation about the FAQ: since 2023 Google only shows the FAQ rich result for well-known government and health sites. For a small site the FAQPage will not turn into the accordion in results, but it is still a clean, machine-readable way to hand questions and answers to search engines and AIs. Check Google's current documentation before promising otherwise.- Os
@idsão identificadores, não precisam abrir nada; o#orgé reaproveitado peloWebSite(publisher),WebPage(about) e cadaService(provider). Assim a empresa é descrita uma vez e referenciada.The@idvalues are identifiers; they need not resolve to anything.#orgis reused byWebSite(publisher),WebPage(about) and eachService(provider). The company is described once and referenced. - Mantenha os dados e o HTML saindo da mesma fonte (um arquivo de dados que gera as duas coisas) para que nunca divirjam.Keep the data and the HTML coming from the same source (one data file that generates both) so they never diverge.
- Valide em Rich Results Test e em validator.schema.org depois que o site estiver num domínio público (eles precisam acessar a URL, ou aceitam o código colado).Validate in the Rich Results Test and at validator.schema.org once the site is on a public domain (they need to reach the URL, or accept pasted code).
sitemap.xmlsitemap.xml
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml">
<url>
<loc>https://arcada.example/</loc>
<lastmod>2026-10-28</lastmod>
<xhtml:link rel="alternate" hreflang="pt-BR" href="https://arcada.example/"/>
<xhtml:link rel="alternate" hreflang="en" href="https://arcada.example/en/"/>
<xhtml:link rel="alternate" hreflang="x-default" href="https://arcada.example/"/>
</url>
<url>
<loc>https://arcada.example/en/</loc>
<lastmod>2026-10-28</lastmod>
<xhtml:link rel="alternate" hreflang="pt-BR" href="https://arcada.example/"/>
<xhtml:link rel="alternate" hreflang="en" href="https://arcada.example/en/"/>
<xhtml:link rel="alternate" hreflang="x-default" href="https://arcada.example/"/>
</url>
</urlset>
- É a lista de URLs que você quer indexadas, não de todas as que existem. Aqui:
/e/en/. Ficam de fora/links/,/404.html,/api/e as páginas de agradecimento. Um sitemap que lista páginasnoindexou que redirecionam envia sinais contraditórios.It is the list of URLs you want indexed, not every URL that exists. Here:/and/en/. Left out:/links/,/404.html,/api/and the thank-you pages. A sitemap that listsnoindexor redirecting pages sends contradictory signals. - Todas as URLs são absolutas, no mesmo protocolo, domínio e padrão de barra final do canonical (aqui, sempre com barra).All URLs are absolute, with the same protocol, domain and trailing-slash style as the canonical (here, always with a slash).
lastmodé a data real da última mudança de conteúdo. Atualizá-la todo dia sem mudança faz o Google desconfiar e passar a ignorar o campo.lastmodis the real date of the last content change. Bumping it daily without a change makes Google distrust it and start ignoring the field.priorityechangefreqnão são usados: o Google os ignora.priorityandchangefreqare not used: Google ignores them.- O
xhtml:linkrepete o hreflang para cada versão, incluindo ela mesma. É uma alternativa (ou reforço) às tags do<head>.Thexhtml:linkrepeats the hreflang for each version, including itself. It is an alternative (or reinforcement) to the<head>tags. - Limite de um sitemap: 50.000 URLs ou 50 MB sem compressão. Acima disso, divida e use um índice de sitemaps.Limit of one sitemap: 50,000 URLs or 50 MB uncompressed. Above that, split it and use a sitemap index.
- Anuncie o sitemap na última linha do
robots.txte envie no Google Search Console e no Bing Webmaster Tools.Announce the sitemap on the last line ofrobots.txtand submit it in Google Search Console and Bing Webmaster Tools.
robots.txt e rastreadores de IArobots.txt and AI crawlers
O robots.txt fica na raiz (/robots.txt) e diz a cada rastreador o que ele pode buscar. É um pedido de boa-fé, não uma barreira: bots de bem obedecem; bots maliciosos ignoram. Nunca use o robots.txt para esconder algo secreto (ele próprio é público) e nunca para proteger dados: para isso use autenticação.The robots.txt sits at the root (/robots.txt) and tells each crawler what it may fetch. It is a good-faith request, not a barrier: well-behaved bots obey; malicious ones ignore it. Never use robots.txt to hide something secret (the file itself is public) and never to protect data: use authentication for that.
# Rastreadores de busca comuns (Googlebot, Bingbot etc.)
User-agent: *
Allow: /
Disallow: /api/
# Busca e respostas de IA: permitidos (alimentam as recomendações; bloquear tira o site delas).
# Cada grupo repete Disallow porque um grupo específico não herda as regras de "*".
User-agent: OAI-SearchBot
User-agent: ChatGPT-User
User-agent: Claude-SearchBot
User-agent: Claude-User
User-agent: PerplexityBot
User-agent: Perplexity-User
User-agent: Applebot
Allow: /
Disallow: /api/
# Treino de modelos. Decisão do dono: permitido por padrão. Para bloquear, troque Allow por Disallow.
# Não afeta a busca comum.
User-agent: GPTBot
User-agent: ClaudeBot
User-agent: Google-Extended
User-agent: Applebot-Extended
Allow: /
Disallow: /api/
# /links/ não é bloqueado aqui: a página usa noindex e o rastreador precisa lê-la.
Sitemap: https://arcada.example/sitemap.xml
Há três famílias de bots de IA, e a decisão de liberar ou bloquear é diferente para cada uma:There are three families of AI bots, and the decision to allow or block differs for each:
| TipoType | ExemplosExamples | Para que serveWhat it is for | Decisão do exemploDecision in the example |
|---|---|---|---|
| Busca e respostaSearch and answers | OAI-SearchBot, Claude-SearchBot, PerplexityBot, Applebot | Indexa o site para o assistente poder encontrá-lo e citá-lo com linkIndexes the site so the assistant can find and cite it with a link | Liberado. Bloquear tira o site das respostasAllowed. Blocking removes the site from answers |
| Ação do usuárioUser action | ChatGPT-User, Claude-User, Perplexity-User | Busca a página na hora, porque uma pessoa pediu ao assistente para abri-laFetches the page on the spot because a person asked the assistant to open it | LiberadoAllowed |
| Treino de modelosModel training | GPTBot, ClaudeBot, Google-Extended, Applebot-Extended | Coleta texto para treinar modelos futuros. Não afeta a busca comumCollects text to train future models. Does not affect regular search | Liberado por padrão; o dono pode trocar Allow por DisallowAllowed by default; the owner may swap Allow for Disallow |
- Grupos específicos não herdam o
*. Quando um bot encontra um grupo com o seu nome, ele usa só aquele grupo e ignora oUser-agent: *. Por isso oDisallow: /api/é repetido em cada grupo; esquecer isso abriria/api/para os bots de IA.Specific groups do not inherit*. When a bot finds a group with its name, it uses only that group and ignoresUser-agent: *. That is whyDisallow: /api/is repeated in each group; forgetting it would open/api/to the AI bots. Google-ExtendedeApplebot-Extendednão são rastreadores separados: são tokens que controlam se o conteúdo já rastreado pelo Googlebot/Applebot pode ser usado para treino. Bloqueá-los não tira o site da busca.Google-ExtendedandApplebot-Extendedare not separate crawlers: they are tokens controlling whether content already crawled by Googlebot/Applebot may be used for training. Blocking them does not remove the site from search.- Liberar ou bloquear o treino é uma decisão de negócio (direitos sobre o conteúdo, visibilidade futura), não técnica. Não há resposta certa; o importante é decidir de propósito.Allowing or blocking training is a business decision (rights over the content, future visibility), not a technical one. There is no right answer; what matters is deciding on purpose.
- Os nomes dos user agents mudam e novos aparecem. Confira cada nome na documentação oficial do fornecedor antes de publicar; a lista deste exemplo não foi reconferida.User-agent names change and new ones appear. Check each name in the vendor's official documentation before publishing; the list in this example was not re-verified.
- Não bloqueie CSS, JS ou imagens que a página usa para renderizar: o Google precisa delas para entender o layout.Do not block CSS, JS or images the page uses to render: Google needs them to understand the layout.
llms.txt e llms-full.txtllms.txt and llms-full.txt
O llms.txt (proposta em llmstxt.org) é um arquivo em Markdown na raiz que resume o site para modelos de linguagem: um título, uma citação com a descrição, e seções de links com uma linha explicando cada um. A ideia é entregar a uma IA o mapa do site sem que ela precise ler HTML cheio de menus e scripts. O llms-full.txt é a versão completa, com todo o conteúdo visível em Markdown, em português e inglês.The llms.txt (a proposal at llmstxt.org) is a Markdown file at the root that summarises the site for language models: a title, a blockquote with the description, and sections of links with a line explaining each. The idea is to hand an AI the site map without making it read HTML full of menus and scripts. The llms-full.txt is the full version, with all the visible content in Markdown, in Portuguese and English.
# Arcada Software
> A Arcada Software cria landing pages, sites institucionais e pequenos projetos web para negócios que querem uma presença online clara, com escopo, prazo e preço fechados antes de começar.
## Serviços
- [Landing page](https://arcada.example/#landing): Uma página com um objetivo: captar contatos ou vender, responsiva, com formulário ou WhatsApp e métricas.
- [Site institucional](https://arcada.example/#site): Um site com página inicial e páginas internas que apresenta a empresa, os serviços e o contato.
- [Pequenos projetos web](https://arcada.example/#pequenos): Projetos web pequenos e bem delimitados, com escopo definido em conversa e publicação incluída.
## Como trabalhamos
- [Processo em cinco passos](https://arcada.example/#processo): conversa, estrutura, design e código, revisão e publicação.
## Perguntas frequentes
- [Perguntas frequentes](https://arcada.example/#faq): custo, prazo, material necessário, revisões, manutenção, edição do site, celular e pagamento.
## Contato
- [Pedir orçamento](https://arcada.example/#contato): formulário do site.
- [E-mail](mailto:contato@arcada.example): contato@arcada.example
## English
- [Arcada Software in English](https://arcada.example/en/): Landing pages, business websites and small web projects.
## Optional
- [Texto completo do site](https://arcada.example/llms-full.txt): todo o conteúdo da página em Markdown.
O llms-full.txt repete o conteúdo visível em Markdown puro: a tabela de serviços, "para quem é e para quem não é", o processo em cinco passos, as 8 perguntas e respostas, o contato e a data de atualização. Abaixo, um trecho:The llms-full.txt repeats the visible content in plain Markdown: the services table, "who it is for and who it is not for", the five-step process, the 8 questions and answers, the contact and the update date. An excerpt:
# Arcada Software (português)
> A Arcada Software cria landing pages, sites institucionais e pequenos projetos web [...]
## Serviços
| Serviço | Para quem serve | O que inclui | Prazo de referência | Preço |
|---|---|---|---|---|
| Landing page | Quem quer captar contatos ou vender uma oferta específica. | Uma página com um objetivo, design responsivo, formulário ou WhatsApp, medição de visitas e publicação. | 1 a 2 semanas | Fechado na proposta |
## Perguntas frequentes
### Quanto custa uma landing page?
O preço é fechado na proposta, antes de começar [...]
Atualizado em 28 de outubro de 2026.
---
# Arcada Software (English)
[...]
llms.txt. Não confunda com o AGENTS.md, que é outra coisa: instruções para agentes de código (Claude Code, Codex, Cursor) dentro de um repositório, e não ajuda em SEO. Para controlar quais bots de IA entram no site, o arquivo é o robots.txt. Veja a nota de agent harness para o AGENTS.md.What about "agents.llm"? That name does not exist as a standard; the file in the example is llms.txt. Do not confuse it with AGENTS.md, which is something else: instructions for coding agents (Claude Code, Codex, Cursor) inside a repository, and it does nothing for SEO. To control which AI bots enter the site, the file is robots.txt. See the agent harness note for AGENTS.md.Páginas noindexnoindex pages
<meta name="robots" content="noindex, follow"> <!-- /links/, obrigado.html, en/thanks.html -->
<meta name="robots" content="noindex"> <!-- 404.html -->
Nem toda página deve aparecer no Google. A página de bio (/links/), a de erro 404 e as de agradecimento (que só fazem sentido depois de um formulário) usam noindex. As duas primeiras ficam fora do sitemap.Not every page should appear in Google. The bio page (/links/), the 404 error page and the thank-you pages (which only make sense after a form) use noindex. The first two are kept out of the sitemap.
/links/ no robots.txt, o rastreador não baixa a página, nunca vê o noindex, e a URL ainda pode aparecer nos resultados (sem descrição) por causa de links externos. Para tirar uma página do índice: permita o rastreamento e use noindex. Use Disallow só para poupar o servidor de trechos sem valor, como /api/.noindex and Disallow cancel each other out. If you block /links/ in robots.txt, the crawler does not download the page, never sees the noindex, and the URL can still appear in results (without a description) because of external links. To remove a page from the index: allow crawling and use noindex. Use Disallow only to spare the server from valueless areas, such as /api/.followdeixa o rastreador seguir os links da página mesmo sem indexá-la.followlets the crawler follow the page's links even without indexing it.- O 404 precisa responder com o status HTTP 404 de verdade (não 200 com a mensagem "não encontrado", o chamado soft 404).The 404 page must answer with a real HTTP 404 status (not 200 with a "not found" message, the so-called soft 404).
HTML e conteúdo que a IA consegue lerHTML and content an AI can read
Meta tags e dados estruturados só ajudam se a página em si for boa de ler. As regras aplicadas no exemplo:Meta tags and structured data only help if the page itself reads well. The rules applied in the example:
- Um
h1por página, eh2comidestáveis (servicos,para-quem,processo,projetos,sobre,faq,contato). Âncoras estáveis permitem links diretos para a seção, usados nollms.txte nos resultados.Oneh1per page, andh2with stableids (servicos,para-quem,processo,projetos,sobre,faq,contato). Stable anchors allow direct links to a section, used inllms.txtand in results. - Marcos semânticos (
header,nav,main,section,footer), link "Ir para o conteúdo" e texto de link descritivo ("Pedir orçamento", não "clique aqui").Semantic landmarks (header,nav,main,section,footer), a "Skip to content" link and descriptive link text ("Request a quote", not "click here"). - A primeira frase visível define a empresa: "A Arcada Software cria landing pages, sites institucionais e pequenos projetos web para negócios que querem uma presença online clara, com escopo, prazo e preço fechados antes de começar." Um modelo que leia só o começo já sabe quem é e o que faz.The first visible sentence defines the company: "Arcada Software builds landing pages, business websites and small web projects for companies that want a clear online presence, with scope, deadline and price agreed before work begins." A model that reads only the start already knows who it is and what it does.
- Formatos fáceis de extrair: tabela HTML de serviços, "para quem é / não é", processo em
<ol>, FAQ em<details><summary>(nativo, sem JavaScript), seção de provas honesta (sem casos inventados) e "Atualizado em" no rodapé.Easy-to-extract formats: an HTML table of services, "who it is / is not for", the process in an<ol>, the FAQ in<details><summary>(native, no JavaScript), an honest proof section (no invented cases) and "Updated on" in the footer. - Todo o conteúdo existe no HTML sem JavaScript. Muitos rastreadores de IA não executam JS; se o texto só aparece depois de um script, para eles a página está vazia. Teste com
curl https://seu-site/ | lesse veja se o texto está lá.All content exists in the HTML without JavaScript. Many AI crawlers do not execute JS; if the text only appears after a script, the page is empty to them. Test withcurl https://your-site/ | lessand check the text is there. - Fontes hospedadas localmente (WOFF2), um CSS só, JS apenas para tema, formulário e eventos (
defer). Menos requisições, página mais rápida.Locally hosted fonts (WOFF2), a single CSS file, JS only for theme, form and events (defer). Fewer requests, a faster page. - Medição sem cookies (Plausible, Cloudflare Web Analytics ou PostHog), com eventos por atributo
data-evento(pedir-orcamento,enviar-formulario,whatsapp). Sem banner de cookies e sem script pesado.Cookie-free analytics (Plausible, Cloudflare Web Analytics or PostHog), with events via adata-eventoattribute (pedir-orcamento,enviar-formulario,whatsapp). No cookie banner and no heavy script.
Velocidade também conta: o Google mede Core Web Vitals (LCP, INP, CLS). O exemplo mira LCP abaixo de 2,5 s e CLS próximo de 0, o que o preload da fonte, o CSS único e a ausência de scripts bloqueantes ajudam a alcançar.Speed counts too: Google measures Core Web Vitals (LCP, INP, CLS). The example aims for LCP under 2.5 s and CLS near 0, which the font preload, the single CSS file and the absence of blocking scripts help achieve.
Redirecionamentos, cabeçalhos e cacheRedirects, headers and cache
Duas URLs para a mesma página diluem o sinal. O arquivo _redirects da Cloudflare Pages unifica tudo numa forma só (sempre com barra final, igual ao canonical e ao sitemap):Two URLs for the same page dilute the signal. Cloudflare Pages' _redirects file unifies everything into one form (always with a trailing slash, matching the canonical and the sitemap):
# Padrão do site: sempre COM barra final (canonical, sitemap e links).
https://www.arcada.example/* https://arcada.example/:splat 301
/index.html / 301
/en/index.html /en/ 301
/en /en/ 301
/links /links/ 301
O 301 é o redirecionamento permanente, e o buscador transfere o sinal para o destino. Aqui o www vai para o domínio sem www e /index.html vai para /. Escolha uma forma (com ou sem www) e mantenha-a em todos os lugares.The 301 is the permanent redirect, and the engine transfers the signal to the target. Here www goes to the bare domain and /index.html goes to /. Pick one form (with or without www) and keep it everywhere.
O arquivo _headers define segurança e cache. A segurança importa para SEO indiretamente (HTTPS é sinal de confiança e site invadido é desindexado); o cache importa para velocidade:The _headers file sets security and cache. Security matters for SEO indirectly (HTTPS is a trust signal and a hacked site gets deindexed); cache matters for speed:
/*
Content-Security-Policy: default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self'; font-src 'self'; connect-src 'self'; manifest-src 'self'; form-action 'self'; base-uri 'none'; frame-ancestors 'none'; upgrade-insecure-requests
Strict-Transport-Security: max-age=63072000; includeSubDomains
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=(), usb=()
Cross-Origin-Opener-Policy: same-origin
# HTML sempre revalidado.
/
Cache-Control: public, max-age=0, must-revalidate
/en/
Cache-Control: public, max-age=0, must-revalidate
# CSS e JS têm ?v=<hash>, por isso podem ser imutáveis.
/style.css
Cache-Control: public, max-age=31536000, immutable
/site.js
Cache-Control: public, max-age=31536000, immutable
/fonts/*
Cache-Control: public, max-age=31536000, immutable
/og/*
Cache-Control: public, max-age=86400
/api/*
Cache-Control: no-store
- CSP estrita (sem
unsafe-inline): como o JSON-LD é dado e não script executável, não precisa de exceção. Se ligar uma medição como o Plausible, acrescente o domínio do script emscript-srceconnect-src. Detalhes na nota de apps web seguros.Strict CSP (nounsafe-inline): since JSON-LD is data and not executable script, it needs no exception. If you add analytics such as Plausible, add the script's domain toscript-srcandconnect-src. Details in the secure web apps note. - HTML sempre revalidado (
max-age=0, must-revalidate): uma mudança de texto aparece na hora. CSS, JS e fontes imutáveis por um ano, porque o nome do arquivo muda (?v=hash) quando o conteúdo muda.HTML always revalidated (max-age=0, must-revalidate): a text change shows up at once. CSS, JS and fonts immutable for a year, because the file URL changes (?v=hash) when the content changes. - A compressão Brotli vem da Cloudflare e deve ser conferida no site real (
curl -I -H "Accept-Encoding: br" ...).Brotli compression comes from Cloudflare and should be checked on the live site (curl -I -H "Accept-Encoding: br" ...).
manifest, security.txt e IndexNowmanifest, security.txt and IndexNow
manifest.webmanifest
{
"name": "Arcada Software",
"short_name": "Arcada",
"lang": "pt-BR",
"start_url": "/",
"scope": "/",
"display": "standalone",
"background_color": "#0A0A0A",
"theme_color": "#0A0A0A",
"icons": [
{ "src": "/icon-192.png", "sizes": "192x192", "type": "image/png" },
{ "src": "/icon-512.png", "sizes": "512x512", "type": "image/png" },
{ "src": "/icon-512.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable" }
]
}
Nome, ícones, cores e start_url para quando alguém adiciona o site à tela inicial do celular. Não afeta o ranking, mas completa a identidade e é exigido por auditorias como o Lighthouse. O ícone maskable tem margem de segurança para o sistema recortá-lo em círculo ou quadrado arredondado.Name, icons, colours and start_url for when someone adds the site to their phone's home screen. It does not affect ranking, but it completes the identity and is required by audits like Lighthouse. The maskable icon has a safe margin so the system can crop it into a circle or rounded square.
.well-known/security.txt (RFC 9116)
Contact: mailto:contato@arcada.example
Expires: 2027-10-01T00:00:00.000Z
Preferred-Languages: pt-BR, en
Canonical: https://arcada.example/.well-known/security.txt
Diz a quem achar uma vulnerabilidade para onde reportá-la. Não é SEO, é boa prática de confiança. O campo Expires é obrigatório e precisa ser renovado antes de vencer; um arquivo vencido é tratado como obsoleto.Tells anyone who finds a vulnerability where to report it. It is not SEO, it is a trust best practice. The Expires field is mandatory and must be renewed before it lapses; an expired file is treated as stale.
IndexNow
IndexNow é um protocolo para avisar os buscadores quando uma URL muda, em vez de esperar o rastreador voltar. Funciona com Bing, Yandex, Seznam e outros; o Google não o usa. Você gera uma chave, publica um arquivo /<chave>.txt na raiz contendo a própria chave (prova de que o domínio é seu) e, depois de cada publicação, envia as URLs:IndexNow is a protocol to notify search engines when a URL changes, instead of waiting for the crawler to return. It works with Bing, Yandex, Seznam and others; Google does not use it. You generate a key, publish a file /<key>.txt at the root containing the key itself (proof the domain is yours) and, after each deploy, submit the URLs:
curl -X POST https://api.indexnow.org/indexnow \
-H "Content-Type: application/json; charset=utf-8" \
-d '{
"host": "arcada.example",
"key": "7c1e5a90b2d44f68a3e9d5c07b816f2a",
"keyLocation": "https://arcada.example/7c1e5a90b2d44f68a3e9d5c07b816f2a.txt",
"urlList": ["https://arcada.example/", "https://arcada.example/en/"]
}'
Só faz sentido depois de publicar com o domínio real. A chave do exemplo é fictícia; gere a sua.It only makes sense after publishing on the real domain. The key in the example is fictional; generate your own.
Validar e o que ficou de foraValidating, and what was left out
Um bom relatório separa o que foi verificado do que não foi. No exemplo:A good report separates what was verified from what was not. In the example:
| FeitoDone | Não feito (exige o site público)Not done (needs the public site) |
|---|---|
| W3C Nu Validator sem erros (páginas principais, 404, links, agradecimento)W3C Nu Validator with no errors (main pages, 404, links, thank-you) | Rich Results Test, validator.schema.org |
| Lighthouse mobile local: PT 96/100/100/100 e EN 99/100/100/100 (Desempenho, Acessibilidade, Boas práticas, SEO); LCP 1,8 s; CLS 0Local mobile Lighthouse: PT 96/100/100/100 and EN 99/100/100/100 (Performance, Accessibility, Best practices, SEO); LCP 1.8 s; CLS 0 | PageSpeed Insights, cabeçalhos e Brotli reais da Cloudflarereal Cloudflare headers and Brotli |
| Sem violações de CSP no console; sem rolagem horizontal em 320 pxNo CSP violations in the console; no horizontal scroll at 320 px | Facebook Debugger, LinkedIn Post Inspector |
| 5 user agents de busca/IA receberam 200 e o 404 real foi servido (servidor local); JSON-LD válido e coerente com o HTML; 31 testes automáticos passando5 search/AI user agents received 200 and the real 404 was served (local server); JSON-LD valid and consistent with the HTML; 31 automated tests passing | Painel de bots de IA da Cloudflare; nomes dos user agents na documentação oficialCloudflare AI-bot dashboard; user-agent names against official documentation |
# Teste rápido de user agents (servidor local ou site real)
curl -sI -A "Googlebot" https://arcada.example/ | head -1
curl -sI -A "ClaudeBot" https://arcada.example/ | head -1
curl -sI https://arcada.example/nao-existe | head -1 # deve ser 404
# O texto está no HTML sem JavaScript?
curl -s https://arcada.example/ | grep -c "landing pages"
# Valida o JSON-LD (extrai o bloco e confere se é JSON)
curl -s https://arcada.example/ \
| python3 -c "import sys,re,json; m=re.search(r'application/ld\+json\">(.*?)</script>', sys.stdin.read(), re.S); json.loads(m.group(1)); print('ok')"
Os primeiros testes só mostram que o servidor responde; o que o Google decide indexar só aparece no Search Console (relatório "Páginas", ferramenta "Inspeção de URL").The first tests only show that the server responds; what Google decides to index only shows up in Search Console (the "Pages" report, the "URL Inspection" tool).
Plano para tornar o site indexávelPlan to make a site indexable
Escrever os arquivos é metade do caminho; o resto é publicar com o domínio real e avisar os buscadores. Uma ordem que costuma funcionar:Writing the files is half the way; the rest is publishing on the real domain and telling the search engines. An order that usually works:
| QuandoWhen | AçãoAction |
|---|---|
| Antes de publicarBefore publishing | Definir o domínio definitivo e usá-lo em canonical, sitemap, Open Graph e JSON-LD; confirmar que o site não tem noindex esquecido de um ambiente de teste; conferir que o texto está no HTML sem JS; preencher TODOs (e-mail real, perfis para sameAs, WhatsApp)Define the final domain and use it in canonical, sitemap, Open Graph and JSON-LD; make sure no noindex is left over from a test environment; check the text is in the HTML without JS; fill in the TODOs (real email, profiles for sameAs, WhatsApp) |
| No dia da publicaçãoOn launch day | Verificar o domínio no Google Search Console e no Bing Webmaster Tools (registro DNS TXT); enviar o sitemap.xml; usar "Inspeção de URL" → "Solicitar indexação" nas páginas principais; rodar o IndexNowVerify the domain in Google Search Console and Bing Webmaster Tools (DNS TXT record); submit sitemap.xml; use "URL Inspection" → "Request indexing" on the main pages; run IndexNow |
| Primeira semanaFirst week | Rodar Rich Results Test, validator.schema.org, PageSpeed Insights e os depuradores de Open Graph; conferir cabeçalhos reais com curl -I; ver no Search Console se há erros de coberturaRun the Rich Results Test, validator.schema.org, PageSpeed Insights and the Open Graph debuggers; check real headers with curl -I; look for coverage errors in Search Console |
| Primeiro mêsFirst month | Ganhar links de fora (perfis de empresa, diretórios sérios, parceiros, clientes), o fator que mais move um site novo; criar o Google Business Profile se houver atendimento local, com o mesmo nome e descrição do site; publicar os primeiros projetos e depoimentos reais, com permissãoEarn external links (company profiles, serious directories, partners, clients), the factor that moves a new site most; create a Google Business Profile if there is local service, with the same name and description as the site; publish the first real projects and testimonials, with permission |
| ContínuoOngoing | Renovar o Expires do security.txt; atualizar lastmod e dateModified só quando o conteúdo mudar; rodar o IndexNow após cada publicação; rotina mensal: perguntar a ChatGPT, Claude, Perplexity e Gemini "quem cria landing pages?" e registrar se a marca apareceRenew the security.txt Expires; update lastmod and dateModified only when content changes; run IndexNow after each deploy; monthly routine: ask ChatGPT, Claude, Perplexity and Gemini "who builds landing pages?" and record whether the brand shows up |
noindex esquecido, bloqueio no robots.txt, canonical apontando para outra URL, conteúdo fino ou duplicado, ou a página não estar ligada a nenhuma outra. O relatório "Páginas" do Search Console diz qual delas é.How long it takes: a new site usually takes days to a few weeks to be indexed, and months to rank for competitive searches. If a page does not get in, the most common causes are: a forgotten noindex, a robots.txt block, a canonical pointing to another URL, thin or duplicate content, or the page not being linked from any other. The Search Console "Pages" report says which one it is.Atividade: auditar o seu site (30 minutos)Activity: audit your site (30 minutes)
O que fazer: escolha uma página do seu site e confira, nesta ordem: (1) curl -I devolve 200 e a URL final, sem cadeia de redirecionamentos; (2) o texto principal aparece em curl -s sem JS; (3) title e description são únicos e dentro do tamanho; (4) o canonical aponta para a própria URL; (5) a URL está no sitemap e não está bloqueada no robots.txt; (6) o JSON-LD bate com o que se vê na tela; (7) o link colado no WhatsApp mostra título e imagem. Anote cada falha e corrija na mesma ordem.What to do: pick one page of your site and check, in this order: (1) curl -I returns 200 and the final URL, with no redirect chain; (2) the main text shows up in curl -s without JS; (3) title and description are unique and within length; (4) the canonical points to its own URL; (5) the URL is in the sitemap and not blocked in robots.txt; (6) the JSON-LD matches what is on screen; (7) the link pasted into WhatsApp shows title and image. Note each failure and fix in the same order.
Resultado esperado: é comum achar no mínimo um canonical errado, um title duplicado ou um texto que só existe via JavaScript. Corrigir isso costuma pesar mais do que qualquer tag nova.Expected result: finding at least one wrong canonical, a duplicate title or text that only exists via JavaScript is common. Fixing that usually weighs more than any new tag.
Cola e revisãoCheat sheet and review
ColaCheat sheet
| Arquivo ou tagFile or tag | PapelRole | CuidadoWatch out |
|---|---|---|
| title + description | Aparência nos resultadosLook in results | Únicos por página e idiomaUnique per page and language |
| canonical | Escolhe a URL oficialPicks the official URL | Aponta para si mesmo, nunca para outro idiomaPoints to itself, never to another language |
| hreflang | Liga idiomasLinks languages | Recíproco e com x-defaultReciprocal and with x-default |
| Open Graph / Twitter | Pré-visualização ao compartilharPreview when sharing | Imagem 1200×630, URL absoluta1200×630 image, absolute URL |
| JSON-LD | Diz o que a página éSays what the page is | Só espelha o que está visívelOnly mirrors what is visible |
| sitemap.xml | Lista o que indexarLists what to index | lastmod real; sem páginas noindexReal lastmod; no noindex pages |
| robots.txt | Quem rastreia o quêWho crawls what | Pedido, não barreira; grupos não herdam *A request, not a barrier; groups do not inherit * |
| noindex | Tira uma página do índiceRemoves a page from the index | Não bloqueie a mesma URL no robots.txtDo not block the same URL in robots.txt |
| llms.txt | Resumo do site para IAsSite summary for AIs | Não é fator de ranqueamentoNot a ranking factor |
| IndexNow | Avisa mudançasAnnounces changes | Bing e outros; o Google não usaBing and others; Google does not use it |
Perguntas de revisãoReview questions
- Por que bloquear
/links/no robots.txt e ao mesmo tempo usarnoindexnela não funciona?Why does blocking/links/in robots.txt and also usingnoindexon it not work? - Qual a diferença entre um bot de busca de IA, um bot de ação do usuário e um de treino, e por que você trataria cada um diferente?What is the difference between an AI search bot, a user-action bot and a training bot, and why would you treat each differently?
- Por que o JSON-LD não deve conter avaliações ou preços que não aparecem na página?Why must JSON-LD not contain reviews or prices that do not appear on the page?
- O que acontece se o canonical da versão em inglês apontar para a versão em português?What happens if the canonical of the English version points to the Portuguese version?
- Por que um texto que só aparece depois de um script pode ser invisível para uma IA?Why can text that only appears after a script be invisible to an AI?
- Google Search Central: documentation (title links, snippets, canonicalization, localized versions/hreflang, sitemaps, robots.txt, robots meta tag, structured data, FAQ rich results)
- schema.org · JSON-LD · Schema Markup Validator
- The Open Graph protocol · sitemaps.org protocol · RFC 9309: Robots Exclusion Protocol
- llmstxt.org · IndexNow documentation · RFC 9116: security.txt
- OpenAI crawlers · Anthropic crawler documentation · Perplexity crawlers (check each vendor for the current user-agent names)
- web.dev: Core Web Vitals · Cloudflare Pages: redirects and headers