11 min de leituraRecursos

Deep Links Sem SDK: Universal Links e App Links

Abra seu app a partir de um link com dois arquivos JSON e sem SDK. Como Universal Links e App Links funcionam com um domínio de link curto.

Marius Voß
DevRel · edge infra

Um deep link é uma URL que o sistema operacional entrega a um app em vez de a um navegador. Toque nela com o app instalado e o app abre. Sem o app, o navegador carrega a página web. No iOS isso se chama Universal Links, no Android App Links, e nenhum dos dois precisa de SDK.

A configuração são dois arquivos JSON em um domínio que você controla, mais um entitlement ou um intent filter no app. A seguir: os dois arquivos, como um domínio de link curto se encaixa, a parte que a maioria dos guias pula (o app recebe a URL curta, não o destino do redirecionamento) e as três tarefas que um SDK ainda faz melhor.

Isso importa mais do que antes. O Google encerrou o Firebase Dynamic Links em 25 de agosto de 2025, e a FAQ dele agora retorna HTTP 404 para esses links (FAQ de suporte do Firebase, acesso em 2026-10-24). Essa FAQ lista um fornecedor para paridade total de recursos, e App Links mais Universal Links para apps que só precisam abrir quando instalados. Para o caso do impresso à instalação, um QR code para download de apps coloca o mesmo roteamento atrás de um código escaneável.

Resumo

  • Os App Links do Android (Android 6, API 23, e posteriores) e os Universal Links do iOS cobrem "abrir no app se estiver instalado, na página web se não" sem SDK de terceiros.
  • Cada um precisa de um domínio que você controla, servido por HTTPS, com um arquivo de associação em /.well-known/.
  • Em um domínio de link curto, o app é iniciado com a URL curta. O código do seu app precisa resolvê-la para uma tela. O 302 nunca é executado.
  • Os SDKs ainda compensam o custo para deferred deep linking, atribuição de instalações e costura de identidade. Dispense-os se você não precisa disso.

Como o SO decide abrir seu app

Os dois sistemas afirmam uma relação verificada entre um domínio e um app. A documentação do Android diz que os App Links deixam as URLs de sites verificadas "immediately open corresponding content in your Android app, without requiring the user to select your app from a disambiguation dialog", e que os usuários sem o app "go to your website instead - no 404s, no errors" (developer.android.com/training/app-links/about, acesso em 2026-10-24).

O Android verifica no momento da instalação. Quando um intent filter traz android:autoVerify="true", um dispositivo com Android 6 ou posterior confere os hosts declarados com https://hostname/.well-known/assetlinks.json enquanto o app é instalado (developer.android.com/training/app-links/verify-android-applinks, acesso em 2026-10-24). Espere pelo menos 20 segundos por essa verificação antes de testar. No Android 15 e posteriores, a reverificação também ocorre periodicamente, e as mudanças no arquivo podem levar até sete dias para se propagar. O Android 14 e anteriores só captam mudanças na instalação ou atualização.

As páginas para desenvolvedores da Apple (developer.apple.com, Supporting associated domains e Supporting universal links) não renderizaram na minha busca em 2026-10-24, então não cito comportamento da Apple além do que seus exemplos publicados mostram: o arquivo fica em /.well-known/apple-app-site-association, o app declara applinks:your-domain no entitlement Associated Domains, e um Universal Link chega ao app como uma atividade de usuário de navegação web carregando a URL. Confira a página atual da Apple antes de publicar, principalmente quanto a cache e comportamento do modo de desenvolvimento.

A consequência para links curtos vem diretamente. O SO decide com base na URL que foi tocada. Isso acontece antes de qualquer requisição ao seu servidor. Se o domínio dessa URL está verificado para o seu app, o app abre com essa URL. Nenhuma requisição HTTP ao link curto acontece, então nenhum redirecionamento é executado.

Os dois arquivos

Um arquivo por plataforma, cada um em um caminho fixo no mesmo domínio.

apple-app-site-association

O arquivo AASA deve ser servido em https://yourdomain.example/.well-known/apple-app-site-association. Sirva-o por HTTPS com uma cadeia de certificados válida, status 200 e Content-Type: application/json, e sem redirecionamento.

A referência de formato da Apple é Supporting associated domains; a página dela não renderizou para mim em 2026-10-24, então trate o exemplo abaixo como o formato comumente publicado e confira-o nessa página.

Um formato mínimo de AASA:

{
  "applinks": {
    "details": [
      {
        "appIDs": ["ABCDE12345.com.example.acme"],
        "components": [
          {
            "/": "/spring-*",
            "comment": "Match any path starting with /spring-"
          },
          {
            "/": "/campaigns/*"
          }
        ]
      }
    ]
  }
}

appIDs é a concatenação do seu Apple Team ID com o bundle identifier do app, separados por um ponto. O array components controla quais caminhos disparam o roteamento para o app; tudo o que não corresponde a um componente cai para o navegador. Você pode registrar vários apps no array details - útil se você tem uma variante para consumidores e outra corporativa do mesmo produto no mesmo domínio.

Um detalhe que vale dizer claramente: "/" com um padrão curinga como /spring-* é uma correspondência por prefixo de caminho. A sintaxe de padrões na mesma referência inclui * (qualquer substring), ? (qualquer caractere único) e objetos de exclusão. Se você quer corresponder a todos os caminhos do domínio, use "/" : "/*". Se quer excluir um caminho específico do roteamento para o app - digamos, sua página /account/delete deve sempre abrir no navegador - adicione um objeto de exclusão antes do curinga:

{
  "/": "/account/delete",
  "exclude": true
}

As regras são avaliadas da primeira à última, então ponha as exclusões antes dos curingas.

assetlinks.json

O arquivo Digital Asset Links do Android fica em https://yourdomain.example/.well-known/assetlinks.json. O Google documenta o formato em developers.google.com/digital-asset-links/v1/getting-started.

[
  {
    "relation": ["delegate_permission/common.handle_all_urls"],
    "target": {
      "namespace": "android_app",
      "package_name": "com.example.acme",
      "sha256_cert_fingerprints": [
        "AA:BB:CC:DD:EE:FF:00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33:44:55:66:77:88:99"
      ]
    }
  }
]

package_name é o ID de aplicação do seu app na Play Store. sha256_cert_fingerprints guarda as impressões digitais SHA-256 do certificado de assinatura do seu app (a página do Google diz que os alvos de apps móveis são identificados por hash do certificado e nome do pacote). Obtenha-a com keytool -list -v -keystore your.keystore, ou nas configurações de assinatura do seu Play Console se a Play assina o app por você. Liste todos os certificados com que você instala builds, inclusive o de debug.

Diferentemente do arquivo AASA, o arquivo do Android não traz regras de caminho. A correspondência de caminhos dos App Links é feita no AndroidManifest.xml por meio de <intent-filter> com android:pathPrefix, android:pathPattern. O arquivo assetlinks.json afirma a propriedade do domínio; o manifesto declara quais caminhos o app trata.

Sequência de resolução do AASA: toque no link curto, busca pelo SO na primeira instalação, acerto de cache nos toques seguintes

Um link como go.acme.example/spring-launch é apenas uma URL em um domínio. Dê a go.acme.example os dois arquivos de associação e declare-o no app, e um toque nesse link abre o app nos dispositivos onde ele está instalado. Esse é o truque, e também o problema. O app recebe https://go.acme.example/spring-launch, não a página para a qual o link redireciona.

O código do seu app tem então duas opções. Uma: corresponder o próprio caminho (/spring-launch significa a tela da promoção de primavera), o que funciona quando você controla os slugs. Duas: perguntar a um servidor para onde o link curto aponta e rotear a partir da resposta. O Elido não tem um endpoint documentado para um app resolver um slug até o seu destino. O redirecionamento público apenas responde com um 302. Hoje a primeira opção é a confiável, e essa lacuna está no nosso backlog.

Em dispositivos sem o app, ou quando o toque acontece em um lugar que não entrega links ao SO, o link curto se comporta como sempre. A borda responde com o redirecionamento (302 por padrão; um link pode ser configurado para 301 ou 307), e o navegador o segue. As regras de segmentação do Elido podem corresponder ao SO, então um link pode enviar visitantes de iOS para uma página da App Store e visitantes de Android para o Google Play quando o app não está lá.

Eis o que o Elido faz e não faz para isso hoje, conferido no código:

RecursoStatusOnde
Servir apple-app-site-association para um domínio personalizadoSimCole o JSON por domínio no painel
Servir assetlinks.json para um domínio personalizadoSimNo mesmo painel
Retornar 404 quando um domínio não tem arquivo configuradoSimDomínios sem app não expõem nada
Encaminhar visitantes de iOS e Android a URLs diferentesSimRegras de segmentação (correspondência de SO)
Deferred deep linking após a instalaçãoNãoUse o SDK de um fornecedor
Atribuição de instalação por cliqueNãoConsoles das lojas ou um fornecedor

O Elido armazena o JSON que você escreve e o serve sem modificações nos caminhos /.well-known/ do próprio domínio. O Elido não gera para você o Team ID, o bundle ID nem a impressão digital do certificado de assinatura; eles vêm da sua conta Apple Developer e da sua chave de assinatura. A configuração do domínio em si (CNAME e TLS) é a mesma de links curtos com domínio personalizado, e a página de recursos de deep links mostra o fluxo no painel. Para equipes de produto que usam links curtos no onboarding, esse padrão cobre links de convite e de indicação sem adicionar um SDK ao binário. A metade do problema em que nada está instalado ainda é a que os App Clip Codes atacam no iOS.

O Que um SDK Ainda Faz Melhor

Três coisas ficam fora do que o SO oferece.

Deferred deep linking. Um usuário toca antes de instalar. O SO não tem app para entregar a URL, então o toque vai para o navegador e a intenção se perde. Os fornecedores a recuperam com correspondência probabilística em dados da requisição ou com uma passagem pela área de transferência. O aviso de consentimento de rastreamento da Apple torna os casos extremos desagradáveis. O Elido não faz isso hoje.

Atribuição de instalações. Sem um SDK você ainda vê as instalações no App Store Connect e no Play Console, mas não consegue ligar uma delas a um toque específico em um link. Sinais relativos sobrevivem: faça experimentos com smart links e compare as instalações por campanha. A atribuição por dispositivo exige um fornecedor.

Costura de identidade. Ligar um toque a um endereço de e-mail ou a um contato do CRM é um projeto de dados. Os fornecedores mantêm um grafo de dispositivos para isso.

Se nenhuma dessas três importa, as primitivas do SO bastam. Se uma importa, contrate o fornecedor só para essa tarefa.

Matriz de recursos: as primitivas nativas do SO e um SDK pago abrem o app e recorrem à web, mas só o SDK acrescenta deferred deep linking, atribuição de instalação por clique e um grafo de identidade entre plataformas

Livro de Receitas de Configuração

Três lugares para acertar: o servidor, o projeto iOS e o manifesto do Android.

Requisitos de HTTPS e de caminho

Sirva os dois arquivos por HTTPS com um certificado que se encadeia até uma CA raiz pública. A página do Digital Asset Links do Google diz que a lista de declarações "must" ficar em /.well-known/assetlinks.json e que listas em outros lugares ou com outros nomes não são válidas (developers.google.com/digital-asset-links/v1/getting-started, acesso em 2026-10-24). Essa página não diz se redirecionamentos são seguidos, então sirva o arquivo diretamente com um 200 e não aposte nisso. O mesmo conselho vale para o arquivo da Apple.

iOS: entitlement Associated Domains

No Xcode, em Signing & Capabilities, adicione a capacidade Associated Domains com o valor applinks:go.acme.example. A Apple documenta um sufixo ?mode=developer para builds de desenvolvimento que faz o dispositivo buscar o arquivo no seu servidor em vez de passar pelo cache da Apple; não consegui conferir essa página de novo em 2026-10-24, então confirme na documentação da Apple. Trate o link recebido como uma atividade de usuário de navegação web (SwiftUI onContinueUserActivity(NSUserActivityTypeBrowsingWeb), ou o delegate continue userActivity do UIKit) e leia webpageURL.

Dentro da ativity que deve tratar os links:

<intent-filter android:autoVerify="true">
  <action android:name="android.intent.action.VIEW" />
  <category android:name="android.intent.category.DEFAULT" />
  <category android:name="android.intent.category.BROWSABLE" />
  <data
    android:scheme="https"
    android:host="go.acme.example"
    android:pathPrefix="/campaigns/" />
</intent-filter>

O Android considera para verificação automática os filtros com a ação VIEW, as duas categorias acima e um esquema http ou https. No Android 11 e anteriores, o sistema só torna seu app o tratador padrão se encontrar um arquivo Digital Asset Links para cada host do manifesto, então um host ruim derruba todos. Em um dado dispositivo, somente um app pode estar associado a um domínio por vez.

Verificando Se Funciona

No Android, dê à verificação pelo menos 20 segundos após a instalação, depois execute adb shell pm get-app-links com.example.acme (Android 12 e posteriores) e procure por verified. Você pode forçar uma nova execução com adb shell pm verify-app-links --re-verify com.example.acme. Resultados como none, denied ou legacy_failure significam que o arquivo ou a impressão digital está errado.

Para o arquivo em si, a API Digital Asset Links do Google lista as declarações que consegue ler de um site: https://digitalassetlinks.googleapis.com/v1/statements:list?source.web.site=https://go.acme.example&relation=delegate_permission/common.handle_all_urls. Uma resposta vazia significa que o Android não vai verificar o app.

Para as duas plataformas, busque o arquivo como um crawler faria:

curl -si https://go.acme.example/.well-known/assetlinks.json | head -20
curl -si https://go.acme.example/.well-known/apple-app-site-association | head -20

Você quer um 200 e um corpo JSON. O Elido envia application/json nos dois arquivos. Os erros habituais são um erro de digitação no Team ID ou no bundle ID, uma build de release cujo certificado de assinatura não está na lista de impressões digitais e um arquivo que existe só no apex enquanto os links usam um subdomínio.

O Trade-off, Dito Claramente

Abandonar o SDK de deep link remove uma dependência do binário do app e uma relação de compartilhamento de dados do seu aviso de privacidade. Não vou dar um número de tamanho; varia por fornecedor e não medi nenhum. O custo: um toque antes da instalação não pode ser ligado à instalação.

Para equipes em estágio inicial, em que o custo por instalação de cada canal ainda não guia o orçamento, comece com as primitivas do SO e adicione um fornecedor de atribuição quando os dados se tornarem acionáveis.

Relacionados no Blog

Perguntas frequentes

Posso fazer deep linking sem Firebase ou um SDK de terceiros?

Sim, para o caso em que o app já está instalado. Os Universal Links do iOS e os App Links do Android precisam de um domínio que você controla, um arquivo JSON de associação nesse domínio e algumas linhas no app. A própria FAQ do Firebase Dynamic Links, do Google, aponta esses dois mecanismos como a opção para deep linking em apps instalados. O que você abre mão é do deferred deep linking, isto é, abrir a tela certa depois de uma instalação nova.

Universal Links e App Links funcionam com um domínio de link curto?

Sim, se o domínio do link curto serve os arquivos de associação e o app declara esse domínio. O problema é que o sistema operacional abre o app com a própria URL curta tocada, então o app precisa transformar essa URL em uma tela. Ele não pode contar com o redirecionamento ter sido executado. Quando o app não está instalado, o mesmo toque carrega no navegador e o redirecionamento normal se aplica.

Onde ficam os arquivos de associação?

O Android lê https://your-domain/.well-known/assetlinks.json, e a documentação do Digital Asset Links do Google diz que esse é o único local válido. O arquivo da Apple fica em https://your-domain/.well-known/apple-app-site-association, sem extensão de arquivo. Sirva os dois por HTTPS com um certificado que se encadeia até uma CA pública.

Por que meu app Android mostra um seletor em vez de abrir diretamente?

A abertura direta exige um App Link verificado. O Android confere o domínio com o assetlinks.json quando o app é instalado, e somente quando um intent filter traz android:autoVerify="true". Se o arquivo está ausente, errado ou lista um certificado de assinatura diferente do da build instalada, o link se comporta como um deep link comum.

O que é deferred deep linking e posso dispensá-lo?

O deferred deep linking leva o destino de um link através da instalação de um app, de modo que um usuário que toca antes de instalar ainda chega à tela certa no primeiro lançamento. Universal Links e App Links não fazem nada nesse caso, porque o app não está lá para receber o toque. Você pode dispensá-lo em fluxos de onboarding em que cair na tela inicial é aceitável, e contratar um fornecedor para isso só se o roteamento no primeiro lançamento mexer nos seus números.

Quais partes disso o Elido cuida?

O Elido serve os arquivos apple-app-site-association e assetlinks.json para domínios personalizados, usando o JSON que você cola nas configurações do domínio no painel. Ele também encaminha visitantes de iOS e Android para destinos diferentes com regras de segmentação. Ele não oferece deferred deep linking nem atribuição de instalações, então use o SDK de um fornecedor se precisar disso.

Experimente Elido

Cole uma URL, obtenha um link curto

Sem cadastro. O link vive 30 dias. Cadastre-se para mantê-lo para sempre.

Sem registro. Crie uma conta grátis e obtenha 50 links por mês.

Experimente o Elido

Encurtador de URL hospedado na UE: domínios personalizados, análises profundas e API aberta. Plano gratuito - sem cartão de crédito.

Tags
mobile deep linking
universal links
app links android
deep linking without sdk
apple app site association
digital asset links

Continuar lendo