Presença web e SEO
Propósito
Ambas as lojas pedem URLs antes de permitir o envio: política de privacidade, suporte, exclusão de conta e, para links de aplicativos, os arquivos .well-known. Esta skill constrói um site estático pequeno e rápido que atende a esses formulários primeiro, depois o torna encontrável (mecanismos de busca, pré-visualizações de links, assistentes de IA) sem rastreadores, padrões obscuros ou números que o aplicativo não possa comprovar.
Faça isso antes dos formulários de listagem na loja e privacidade (listing-and-aso, privacy-and-declarations): eles precisam de URLs ativos.
Pré-requisitos
- Um domínio que você controla, com acesso ao DNS (Cloudflare é usado nos exemplos; qualquer host funciona se puder definir cabeçalhos e servir arquivos sem redirecionamentos).
- Os identificadores finais do aplicativo e dados de assinatura de
identity-and-signing(Team ID, bundle ID, package name, Play app signing SHA-256). - O texto da política de privacidade derivado da varredura de código/SDK (
privacy-and-declarations) e o fluxo de exclusão que realmente existe no aplicativo. - Preços lidos de volta das lojas (
subscriptions-and-payments), nunca digitados de memória. - Node.js 18+ para os scripts em scripts/.
1. Páginas exigidas pelas lojas
Checklist com cada campo da loja → URL: references/store-url-checklist.md.
| Página | Caminho (sugerido) | Regras |
|---|---|---|
| Política de privacidade | /privacy | Público, sem login, sem bloqueio geográfico, HTML (não PDF), nomeia o aplicativo, corresponde às respostas de privacidade da loja |
| Termos | /terms | Necessário se você vender assinaturas (EULA padrão da Apple ou o seu próprio; vincule-o no aplicativo e na listagem) |
| Suporte / contato | /support | Uma forma real de entrar em contato (email ou formulário), não apenas um FAQ |
| Exclusão de conta (web) | /delete-account | O Google Play exige esta URL. Nomeia o aplicativo como na listagem, permite que o usuário solicite a exclusão a partir da própria página, informa o que é excluído, o que é mantido e por quanto tempo, e que uma assinatura da loja deve ser cancelada separadamente |
- A Apple exige que a exclusão comece dentro do aplicativo (diretriz 5.1.1(v)); uma página web não substitui isso. O Play exige tanto o caminho no aplicativo quanto a URL web. Documentos: Exclusão de conta Apple, Exclusão de conta Play, Regras de URL de política de privacidade Play.
- Sem login e estável. Sem banner de cookies, sem login, sem necessidade de JavaScript para ler o texto. Não renomeie caminhos após o envio; se precisar, mantenha um 301 do caminho antigo.
- Por idioma. Uma URL por idioma (
/privacy,/de/privacy) comhreflang; o App Store Connect permite definir uma URL de privacidade por localização. Se uma página não estiver traduzida, vincule a página do idioma padrão em vez de um 404. - Mostre a data de "última atualização" nas páginas legais e mantenha versões antigas no controle de versão.
2. Hospedagem de links de aplicativos
Os modelos para os próprios arquivos estão em identity-and-signing/templates/. Esta seção trata de servi-los.
https://<domínio>/.well-known/apple-app-site-associatione/.well-known/assetlinks.json: HTTP 200,Content-Type: application/json, sem redirecionamento (não http→https, não apex→www, não barra final), sem autenticação, sem página de desafio de bot.- Decida apex vs
wwwuma vez. Sirva os arquivos em cada host listado nas entitlements / intent filters; redirecione o outro host apenas para páginas, nunca para/.well-known/. - Hosts estáticos geralmente servem o AASA sem extensão como
application/octet-stream. Roteie/.well-known/*através do Worker (veja o modelo) ou defina o cabeçalho explicitamente e verifique comscripts/check-site.mjs. - Implante os arquivos
.well-knownantes da compilação do aplicativo que reivindica o domínio. A Apple busca o AASA através de sua CDN, portanto as alterações podem levar um tempo para aparecer.
Páginas de convite / referência (/i/<código>)
- O Worker valida o código contra o alfabeto e comprimento exatos que o backend emite, depois preenche um modelo. Nada mais da URL chega ao HTML.
- Se o aplicativo estiver instalado, universal links / App Links o abrem diretamente (o caminho deve estar no
componentsdo AASA e no intent filter do Android). Se não, a página mostra ambos os botões da loja e um botão "copiar código" como fallback manual. - Android: anexe o código à URL do Play como
&referrer=<key=value codificado em URL>e leia-o no aplicativo com a API Play Install Referrer. O iOS não tem referenciador de instalação; peça ao usuário para colar o código ou preencha-o da área de transferência apenas após um toque explícito. - Cabeçalhos:
X-Robots-Tag: noindex,Cache-Control: private, no-store,Referrer-Policy: no-referrer. Mantenha/i/fora do sitemap. Não useDisallowno robots.txt: um crawler que não consegue buscar a página nunca vê onoindex.
3. Página de destino
- Mesma linguagem visual das capturas de tela da loja (cores, tipo, os mesmos cards reais da interface). Um visitante vindo do site deve reconhecer a página da loja.
- Selos da loja apenas na arte oficial, sem modificações, com o espaçamento e texto exigidos; link direto para a listagem. Regras: Diretrizes de marketing da Apple, Selos do Google Play.
- Antes do lançamento: uma linha "Em breve na App Store e Google Play", não três selos desabilitados. No lançamento (após o release estar ativo): troque para links reais de selos, adicione o meta Smart App Banner (docs), atualize
llms.txte o JSON-LD. Mantenha isso como uma única flag de configuração para que seja uma única alteração. APROVAÇÃO antes de alternar. - Preços honestos. Os preços vêm de um arquivo gerado a partir da leitura de retorno da loja. As páginas contêm placeholders (
%%PRICE_MONTHLY%%); o Worker os preenche de acordo com o país do visitante (request.cf.country) e diz "a loja mostra o preço exato na sua moeda" para países fora da tabela. O idioma da página nunca decide a moeda. Nenhum preço "era" riscado, nenhuma contagem regressiva falsa, nada pré-marcado. - Rápido e acessível. Texto em HTML (não renderizado por JS), um arquivo CSS, pouco ou nenhum JS, fontes auto-hospedadas com
font-display: swap, imagem principal dimensionada efetchpriority="high". Metas: LCP < 2,5 s, CLS < 0,1, INP < 200 ms (Web Vitals). Contraste e estados de foco conforme WCAG 2.2;prefers-reduced-motionrespeitado. - Analytics. Prefira nenhum ou contagens do lado do servidor/sem cookies (logs de borda, analytics amigáveis à privacidade sem identificadores). Se você não definir cookies e não carregar scripts de terceiros, não precisa de banner de cookies; não mostre um "por precaução". Se você adicionar qualquer rastreador, o banner de consentimento, a política de privacidade e as respostas de privacidade da loja devem ser alterados juntos.
4. Imagens de compartilhamento social
- Uma imagem Open Graph por idioma: 1200×630 PNG/JPG, com menos de ~1 MB, texto grande o suficiente para ler no tamanho de miniatura. URLs
https://absolutas emog:imageetwitter:image, maisog:image:width/height/alt,og:title,og:description,og:url,twitter:card=summary_large_image. Especificação: ogp.me, Guia de compartilhamento Meta. - Aplicativos de mensagens armazenam em cache as pré-visualizações agressivamente. Após alterar uma imagem, dê a ela um novo nome de arquivo (ou
?v=2) e re-raspe no Sharing Debugger ("Scrape Again"). O WhatsApp e outros mensageiros mantêm seus próprios caches sem ferramenta de atualização pública, portanto uma nova URL de imagem é a solução confiável; teste enviando o link em um novo chat.
5. SEO técnico
- Título (≈50–60 caracteres, marca + o que faz) e meta descrição (≈150–160 caracteres) únicos por página e idioma. Links de título, snippets.
- hreflang: cada versão de idioma lista todas as versões incluindo a si mesma, mais
x-default; os pares devem ser recíprocos. Versões localizadas. - Canonical: auto-referenciada, absoluta, na URL final (sem redirecionamento). Canonicalização.
- Sitemap com apenas URLs 200, indexáveis, canônicas e um
<lastmod>real (data da alteração do conteúdo, por exemplo, do git, não do tempo de compilação). Modelo, docs. - robots.txt: modelo, introdução. robots.txt controla o rastreamento, não a indexação; use
noindexpara páginas que devem permanecer fora dos resultados. - Dados estruturados (JSON-LD): Organization, WebSite, MobileApplication; FAQPage apenas para um FAQ visível na página. Exemplos e regras: references/structured-data.md.
- Hosts não produtivos (visualização,
*.workers.dev) enviamX-Robots-Tag: noindex.
6. Descoberta
- Google Search Console: adicione uma propriedade Domínio, adicione o registro TXT
google-site-verificationno apex, verifique, envie o sitemap, solicite indexação para as páginas iniciais. Verificar propriedade. - Bing Webmaster Tools: importe do Search Console ou verifique com o registro DNS que o Bing fornece (um CNAME), depois envie o sitemap. Adicionar e verificar.
- IndexNow (Bing, Yandex, Seznam, Naver e outros; não Google): hospede
/<chave>.txtcontendo a chave, implante, depois executenode scripts/indexnow-ping.mjs(dry run) e--send. O script verifica se o arquivo de chave está ativo primeiro. Protocolo. - Crawlers de IA e llms.txt: decida por bot se permite bots de busca/resposta e bots de treinamento (decisão do proprietário, APROVAÇÃO). Lista de bots, propósitos e links oficiais: references/ai-crawlers.md. Adicione um llms.txt curto com o resumo do produto e URLs principais, sem preços.
Registros DNS são infraestrutura compartilhada: adicione o novo registro; nunca edite ou exclua registros TXT/SPF/MX existentes. APROVAÇÃO antes de qualquer alteração de DNS.
7. Implantação (exemplo Cloudflare Worker)
Modelo: templates/worker.example.js. Ele serve arquivos .well-known com o tipo correto e sem redirecionamento, preenche placeholders de preços por país, renderiza /i/<código>, adiciona cabeçalhos de segurança e noindex em hosts não produtivos.
Duas opções de armazenamento:
- Workers Static Assets (mais simples):
"assets": { "directory": "./dist", "binding": "ASSETS", "run_worker_first": true }emwrangler.jsonc; o Worker chamaenv.ASSETS.fetch(). Docs. - KV (endereçável por conteúdo): a compilação escreve arquivos sob seu hash e um
manifest.js(caminho → hash, tipo); faça upload comwrangler kv bulk putantes de implantar o Worker, para que o novo manifesto nunca aponte para um arquivo ausente. Comandos KV.
Passos:
node build.mjs→dist/(falha em qualquer chave de tradução ausente ou placeholder não preenchido, exceto os de preço).- Testes unitários (
node --test): execute ofetchdo Worker contra assets fictícios. Cubra: AASA/assetlinks 200 +application/json+ sem redirecionamento; redirecionamentowww/httpapenas para páginas;/i/<ruim>→ 404,/i/<bom>→ noindex + no-store; toda região de preço preenche todos os placeholders (nenhum%%restante); codificação percentual malformada → 404, não 500. - Visualização:
npx wrangler deploy --dry-run, ou implante em um host de visualização e executenode scripts/check-site.mjs https://<host-de-visualizacao>. - APROVAÇÃO — implantação em produção (
npx wrangler deploy). Fixeaccount_id,namee rotas emwrangler.jsoncpara que o comando não possa atingir outro projeto em uma conta compartilhada. - Após a implantação:
node scripts/check-site.mjs https://example.com --invite <código de exemplo>, depois o ping IndexNow.
Pontos de decisão que exigem aprovação humana
- Implantações em produção e alterações de DNS.
- Redação de páginas legais (privacidade, termos, exclusão); o proprietário aprova qualquer alteração.
- Permitir/negar crawlers de treinamento de IA.
- A troca "em breve" → "baixar" e qualquer preço exibido no site.
- Adicionar analytics, formulário de lista de espera ou qualquer coisa que colete dados pessoais.
Verificação
node scripts/check-site.mjs https://example.com --paths /privacy,/terms,/support,/delete-accountsai com 0: páginas exigidas 200 sem login, AASA/assetlinks JSON sem redirecionamento, tags OG com imagens absolutas alcançáveis, hreflang recíproco, URLs do sitemap todas 200.- Cada URL no checklist de URLs da loja abre em uma janela privada em um telefone.
- Rich Results Test e Schema Markup Validator não mostram erros; PageSpeed Insights LCP móvel < 2,5 s.
- Search Console: sitemap "Sucesso"; Bing: envios IndexNow visíveis.
Armadilhas comuns
- URL de privacidade que redireciona para um login, um PDF ou uma política genérica da empresa que nunca nomeia o aplicativo.
- Página de exclusão que apenas diz "excluir no aplicativo" (o Play quer um caminho de solicitação na página) ou esquece de mencionar o cancelamento da assinatura da loja.
- AASA servido via redirecionamento apex→www, como
text/htmlou atrás de um desafio de bot. Disallow: /i/no robots.txt junto com um cabeçalhonoindexque os crawlers nunca veem.- Preços codificados por idioma (EUR na página alemã para um visitante na Suíça) ou deixados como números desatualizados após uma alteração de preço na loja.
aggregateRatinginventado para um novo aplicativo, ouofferscom um preço que só é verdadeiro em um país.- Imagem OG com menos de 600 px de largura (cortada por mensageiros), mais de 3 MB (não carregada), ou conteúdo que não corresponde à página (clicar no link abre outro idioma).
- Sitemap com URLs 302, URLs de visualização ou sem datas de
lastmod. - Implantar o Worker sem executar testes unitários primeiro.
- Pulando o
check-siteapós a implantação.