Universal links y App Links de Android: configuración del sitio web

Configura universal links y android app links: apple-app-site-association, assetlinks.json, reglas del servidor, comprobaciones y respaldos.

En este artículo

Los universal links (iOS) y los App Links de Android abren tu app en lugar de tu sitio web cuando alguien toca un enlace https:// normal, y la parte del sitio web son dos archivos JSON que alojas tú mismo: apple-app-site-association para iOS y assetlinks.json para Android. Ambos viven en /.well-known/ en cada dominio que gestiona la app, los dos deben servirse por HTTPS sin redirecciones, y cada uno indica qué app puede abrir tus URL. La app también necesita su propia configuración (un derecho en iOS, un filtro de intents en Android), que se muestra más abajo junto a cada archivo.

Los dos sistemas conectan un sitio web y una app en ambos sentidos: la app declara qué dominios gestiona, y el sitio web lo confirma. Apple describe los universal links como enlaces HTTP o HTTPS normales, de modo que una sola URL sirve para el sitio y para la app, y los usuarios sin la app reciben la página en el navegador (Apple). Los App Links de Android, en palabras de Google, se basan en el mismo sistema de intents que otros deep links, pero añaden un paso de verificación con un archivo de Digital Asset Links en tu sitio web (Android Developers).

Universal links de iOS App Links de Android
Archivo en el sitio web apple-app-site-association assetlinks.json
Ubicación https://<dominio>/.well-known/apple-app-site-association https://<dominio>/.well-known/assetlinks.json
Lo que declara la app Derecho Associated Domains, applinks:<dominio> Filtro de intents con android:autoVerify="true"
Identifica la app por Team ID más bundle ID Nombre del paquete más huella digital del certificado de firma
Cuándo se comprueba En la instalación, a través del CDN de Apple En la instalación, y en segundo plano en Android 15 y posteriores
Los universal links y los App Links necesitan ambos lados: la app declara el dominio (Associated Domains o un intent filter con autoVerify) y el sitio aloja un archivo en .well-known (apple-app-site-association o assetlinks.json)

«Deep link» es el término más amplio. Un deep link normal puede usar un esquema personalizado o un enlace https:// no verificado; los universal links y los App Links son la variante verificada.

El archivo de iOS: apple-app-site-association

Crea un archivo llamado apple-app-site-association, sin extensión, y enumera los identificadores de tu app y los patrones de URL que la app debe abrir. Esta es la estructura de ejemplo de la documentación de Apple, abreviada:

{
  "applinks": {
    "details": [
      {
        "appIDs": ["ABCDE12345.com.example.app"],
        "components": [
          { "/": "/buy/*", "comment": "Open URLs that start with /buy/ in the app." },
          { "/": "/help/website/*", "exclude": true, "comment": "Keep these in the browser." }
        ]
      }
    ]
  }
}

El valor de appIDs es el prefijo del identificador de la aplicación (tu Team ID), un punto y el bundle identifier. Cada entrada de components coincide con una parte de la URL, y "exclude": true indica al sistema que no abra en la app las URL que coincidan (Apple, Supporting associated domains). Apple también acepta un formato anterior con appID y paths; su nota de depuración dice que no se mezclen los dos (TN3155).

Publícalo en https://<nombre de dominio completo>/.well-known/apple-app-site-association con un certificado válido y sin redirecciones. Tres reglas de las páginas de Apple suelen dar problemas:

  • Cada subdominio necesita su propia entrada en la app. Un archivo en example.com sirve para applinks:example.com y applinks:*.example.com, mientras que un subdominio concreto como www.example.com necesita su propio archivo.
  • El archivo debe ser accesible desde cualquier dirección IP y para cualquier user agent. Un 403 o un 404 causado por un cortafuegos, un filtro de bots o un muro de inicio de sesión impide que los servidores de Apple lo guarden en caché.
  • Desde iOS 14, los dispositivos no descargan el archivo de tu servidor. El CDN de Apple lo descarga y lo guarda en caché, los dispositivos buscan actualizaciones aproximadamente una vez por semana, y no hay forma de invalidar esa caché directamente; reinstalar la app descarga una copia más reciente (TN3155).

Durante el desarrollo, puedes añadir ?mode=developer a la entrada del derecho (applinks:example.com?mode=developer) para que el dispositivo lea el archivo directamente de tu servidor en lugar de hacerlo desde el CDN de Apple.

El archivo de Android: assetlinks.json

assetlinks.json es una matriz de declaraciones que nombran tu paquete y la huella SHA-256 del certificado que firma la app. Este es el ejemplo de Google para una app:

[{
  "relation": ["delegate_permission/common.handle_all_urls"],
  "target": {
    "namespace": "android_app",
    "package_name": "com.example",
    "sha256_cert_fingerprints":
    ["14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"]
  }
}]

Sustituye el nombre del paquete y la huella por los tuyos. Los requisitos, según la guía de Google (actualizada el 23 de octubre de 2026):

  • Sírvelo en https://<dominio>/.well-known/assetlinks.json con el tipo de contenido application/json.
  • Usa HTTPS aunque los filtros de intents de la app declaren también http.
  • Sin redirecciones, ni 301 ni 302.
  • Publícalo en cada dominio de host que gestiona la app.
  • Un mismo archivo puede listar varias apps, y el campo sha256_cert_fingerprints admite varias huellas, por ejemplo para las compilaciones de depuración y de producción.

Si usas Play App Signing, la huella que obtienes con keytool en tu equipo normalmente no coincidirá con la de los dispositivos de los usuarios. Google indica que tomes el fragmento JSON correcto de Play Console, en Release > Setup > App signing.

El lado de la app es un filtro de intents con autoVerify. Esta es la forma de la documentación de Android:

<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="http" />
    <data android:scheme="https" />
    <data android:host="www.example.com" />
</intent-filter>

Android verifica cada nombre de host de esos filtros, y un host comodín como *.example.com necesita el archivo en el dominio raíz example.com (Android Developers). En Android 15 y posteriores, la verificación también se ejecuta periódicamente, y un cambio en el archivo puede tardar hasta siete días en propagarse; en Android 14 e inferiores, el archivo se lee solo al instalar o actualizar (Android Developers).

Lista de comprobación del servidor

Los dos archivos fallan por las mismas pocas razones, así que revisa el servidor una vez para ambos:

Comprobación Por qué Cómo probarlo
HTTPS Las dos plataformas lo exigen, y Apple pide un certificado válido Abre la URL en un navegador
Sin 301 ni 302 Las redirecciones no son compatibles con ninguno de los dos archivos curl -sI devuelve un 200
iOS: público para todas las IP y user agents El CDN de Apple descarga el archivo, y un cortafuegos o un filtro de bots lo bloquea curl -A "MyAgent-Bot/1.0" <url> devuelve el archivo
Android: Content-Type: application/json Google lo indica como requisito Cabecera de curl -sI
El mismo archivo en cada dominio y subdominio que listes Cada host se verifica por separado Ejecuta la comprobación por cada host

Para el tipo de contenido, servir los dos archivos como application/json mantiene la configuración uniforme. La documentación de Apple no indica un tipo de contenido para el archivo de iOS, así que esa parte es una elección tuya. Un ejemplo estático para nginx:

location = /.well-known/apple-app-site-association {
    default_type application/json;
}
location = /.well-known/assetlinks.json {
    default_type application/json;
}

Cómo comprobar que funciona

Comprueba el archivo desde fuera y luego el comportamiento en un dispositivo. Los pasos de depuración de Apple, de TN3155:

  1. Ejecuta curl -v https://<dominio>/.well-known/apple-app-site-association y confirma un 200 y el JSON, no un 301, 302, 403 o 404.
  2. En un Mac, sudo swcutil dl -d <dominio> comprueba que el archivo se descarga, y sudo swcutil verify -d <dominio> -j <ruta-al-JSON> -u <URL> comprueba que una URL coincide con un patrón.
  3. En un iPhone, pega el enlace en la app Notas y mantén pulsado. Si todo está configurado, aparecen las opciones de abrir en la app y de abrir en el navegador.

Para Android, la verificación manual de Google en Android 12 y posteriores (para una app que apunta a una versión anterior a Android 12, primero ejecuta adb shell am compat enable 175408749 com.example):

adb shell pm set-app-links --package com.example 0 all
adb shell pm verify-app-links --re-verify com.example
# espera unos minutos y luego:
adb shell pm get-app-links com.example

La salida enumera cada dominio con un estado como verified o legacy_failure. Google también ofrece un generador y comprobador de listas de declaraciones (herramienta de Digital Asset Links) para probar un archivo de declaraciones existente. Para una rutina de pruebas más amplia, consulta la lista de comprobación para pruebas de sitios móviles.

Cuándo los enlaces no abren la app

Escribir una URL en la barra de direcciones del navegador nunca abre la app en iOS, porque es navegación directa dentro del navegador; si el usuario ya está en tu dominio, un enlace al mismo dominio también se queda en Safari (TN3155). La solución de Apple para flujos como un botón de inicio de sesión es usar otro subdominio, con su propia entrada applinks y su propio archivo AASA, de modo que el sistema trate el toque como una salida del sitio.

Los navegadores integrados en las apps necesitan pruebas aparte. Apple indica que los enlaces tocados en una app de navegador o en un WKWebView pueden abrir tu app, pero también dice que los navegadores de terceros deciden si activan los universal links («Los universal links pueden no estar activados en todos los navegadores web», según TN3155), y que una app que abre tu enlace mediante su propia llamada open(_:) no abrirá el tuyo a cambio (Apple). Si el navegador de una app social concreta entrega el enlace a tu app no lo cubre la documentación de la plataforma, así que prueba cada una que te importe en un teléfono real.

Un banner inteligente de la app es un aviso solo para iOS en la página web: una etiqueta meta en el <head> de cada página donde lo quieras. Según Apple, abre la app si está instalada y enlaza con App Store si no lo está.

<meta name="apple-itunes-app" content="app-id=myAppStoreID, app-argument=https://example.com/buy/42">

app-id es obligatorio, y el app-argument opcional pasa una URL a la app para que abra la pantalla correspondiente. Apple indica dos límites: los banners no aparecen dentro de un frame, y no aparecen en el simulador de iOS.

Si no publicas una app nativa, no necesitas ninguno de los dos archivos; una aplicación web progresiva se instala desde el navegador.

Comprueba la página de respaldo en tamaños de móvil

Todos los que no tienen la app, y cada enlace que no se transfiere, llegan a tu página web, así que esa página tiene que funcionar en un teléfono. Mobile View Extension recarga la pestaña con el user agent, el tamaño de pantalla y la relación de píxeles de un teléfono, así que ves la versión móvil real de la página de respaldo en varios tamaños, y puedes usar junto a ella la emulación de dispositivos de Chrome. No puede probar el traspaso a la app: se ejecuta en Chrome de escritorio, no tiene eventos táctiles ni apps instaladas, así que el manejo de enlaces necesita un iPhone o un teléfono Android, o el simulador de iOS o el emulador de Android. Para iOS sin hardware, consulta probar un sitio web en un iPhone sin tener un iPhone.

Preguntas frecuentes

Los deep links son la categoría amplia; los universal links son la variante verificada de Apple, construida sobre enlaces HTTP o HTTPS estándar. Un deep link también puede usar un esquema de URL personalizado, que no está ligado a un sitio web que controles. Los App Links de Android son la forma verificada en Android, que añade la comprobación de Digital Asset Links a los deep links normales.

¿Dónde va apple-app-site-association?

Va en https://<dominio>/.well-known/apple-app-site-association, sin extensión de archivo, servido por HTTPS con un certificado válido y sin redirecciones. Cada subdominio que liste la app necesita su propia copia.

Las causas habituales son una redirección, un 403 o 404 en el archivo, una entrada de subdominio que falta o un toque en el mismo dominio. Apple las enumera en TN3155; escribir la URL en la barra de direcciones o tocar un enlace al mismo dominio mientras se navega en Safari mantiene al usuario en el navegador. Comprueba antes el archivo con curl -v.

¿Necesito los dos archivos?

Necesitas el archivo de cada plataforma cuya app publiques. Un sitio con una app para iOS y otra para Android sirve los dos, y cada uno es independiente del otro.

Mira tu próximo sitio en versión móvil.

Añade la extensión y abre vistas de dispositivos en la misma pestaña en la que ya trabajas.