Universal Link es un mecanismo de Apple (iOS 9+) que permite abrir enlaces web directamente en la aplicación, omitiendo Safari. Si la aplicación no está instalada, el enlace se abre sin problemas en el navegador. El término fue introducido por Apple en 2015 en la WWDC como parte de Handoff y el ecosistema Continuity. Según Apple Developer, Universal Link proporciona una experiencia de usuario unificada entre la web y la aplicación nativa sin diálogos de selección.
Puntos clave
Universal Link es un enlace HTTPS estándar como https://example.com/page que, al pulsarlo desde un dispositivo iOS, abre la aplicación instalada en lugar de Safari. La principal diferencia con Custom URL Scheme: Universal Link no requiere registrar un esquema personalizado (myapp://) — se utiliza un dominio normal. Esto elimina el problema de URL Scheme hijacking, donde cualquier aplicación puede registrar el mismo esquema.
Apple presentó Universal Link en la WWDC 2015 como parte de iOS 9. El mecanismo pasó a formar parte del ecosistema Handoff y Spotlight: Universal Link funciona no solo en el navegador, sino también en los resultados de búsqueda de Spotlight, Mail, Messages y otras aplicaciones del sistema. Además, Universal Link es compatible con watchOS y macOS: el usuario puede abrir una aplicación en el iPhone a través de un enlace en el Mac.
La ventaja clave: URL única. El desarrollador no gestiona dos enlaces diferentes (uno para la web y otro para la aplicación). Universal Link es un mismo enlace https. Si la aplicación está instalada, se abre la aplicación. Si no, el mismo enlace se abre en Safari como una página web normal. Esto proporciona un fallback ideal sin pérdida de tráfico.
El mecanismo de Universal Link consta de tres etapas: verificación de asociación, procesamiento del enlace y fallback al navegador. Cada etapa es crítica para el funcionamiento correcto. Si la asociación no está configurada, iOS procesa el enlace como una redirección normal a Safari. Analicemos cada etapa en detalle.
En el primer toque en un enlace, iOS descarga el archivo apple-app-site-association del servidor en https://example.com/.well-known/apple-app-site-association. El archivo contiene JSON con el Team ID y Bundle ID de la aplicación, así como una lista de rutas que la aplicación debe abrir. iOS almacena en caché este archivo y verifica periódicamente su vigencia (al actualizar la aplicación, al reiniciar el dispositivo).
El archivo JSON apple-app-site-association debe ser accesible a través de HTTPS sin redirecciones. El servidor debe devolver Content-Type: application/json. Es importante destacar que el archivo no tiene extensión .json — iOS lo busca estrictamente en /.well-known/apple-app-site-association. Apple recomienda también añadir soporte para Universal Link en CDN y verificar que el archivo no esté bloqueado por robots.txt.
// apple-app-site-association — configuración mínima
{
"applinks": {
"apps": [],
"details": [
{
"appID": "TEAMID.com.example.app",
"paths": ["/product/*", "/profile/*", "/search"]
}
]
}
}
appID se forma como Team ID + Bundle ID (TEAMID.com.example.app). paths es una matriz de patrones de URL que la aplicación debe manejar. Se pueden utilizar *, ? y la notación NOT: ["NOT /admin/*", "/product/*"]. Las rutas se verifican en el orden de enumeración: la primera coincidencia determina el comportamiento. Si la ruta no coincide, el enlace se abre en Safari.
Después de la verificación exitosa de la asociación, iOS pasa el enlace a la aplicación. El procesamiento se realiza en AppDelegate a través del método application(_:continue:restorationHandler:) para NSUserActivity, o en SceneDelegate a través de scene(_:continue:). El desarrollador recibe un objeto NSUserActivity con el tipo NSUserActivityTypeBrowsingWeb, extrae la URL y navega a la pantalla correspondiente.
// Manejo de Universal Link en AppDelegate
func application(
_ application: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler: @escaping UIUserActivityRestorationHandler
) -> Bool {
guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
let url = userActivity.webpageURL
else { return false }
// Navegar a la pantalla según la URL
DeepLinkRouter.navigate(to: url)
return true
}
DeepLinkRouter en el ejemplo anterior es una clase personalizada que analiza la URL y llama al coordinador de navegación correspondiente. Para SwiftUI, el procesamiento se realiza a través del método onOpenURL o el modificador environment(\.openURL). Es importante manejar no solo el inicio en primer plano, sino también el caso en que la aplicación no se estaba ejecutando (cold start): Universal Link abre la aplicación a través de opciones de lanzamiento en este caso.
Si la aplicación no está instalada, iOS abre automáticamente el Universal Link en Safari. Esta es una diferencia clave con Custom URL Scheme: el usuario no ve un error. El fallback es la página web estándar del mismo dominio. El desarrollador puede colocar un enlace a App Store, información del producto o contenido alternativo en esta página.
Importante: el fallback no se puede personalizar a nivel de iOS. iOS simplemente abre la URL en Safari. Para mostrar contenido diferente para usuarios con y sin la aplicación instalada, use Smart App Banner (una metaetiqueta para Safari que ofrece abrir la aplicación) o detección de instalación mediante JavaScript. Apple también proporciona SKAdNetwork para la atribución de instalaciones a través de Universal Link.
Universal Link y el Deep Link tradicional (Custom URL Scheme) resuelven el mismo problema, pero difieren fundamentalmente en arquitectura y seguridad. Custom URL Scheme es un protocolo personalizado (myapp://) registrado en Info.plist. Cualquier aplicación puede registrar el mismo esquema (myapp://), e iOS no puede determinar cuál es la “verdadera”. Esto se llama URL Scheme hijacking.
Universal Link resuelve el problema del hijacking mediante la verificación del dominio. Solo el propietario del dominio puede colocar apple-app-site-association en su servidor, confirmando la conexión con un Bundle ID específico. Dos aplicaciones no pueden registrar el mismo Universal Link: si surge un conflicto, iOS da prioridad a la aplicación instalada más recientemente o abre Safari.
Otra diferencia: Fallback. Custom URL Scheme no tiene fallback — si la aplicación no está instalada, el navegador muestra un error. Universal Link abre el sitio web. Una URL única significa que el valor SEO del enlace se conserva (Google indexa el enlace), y un usuario con cualquier dispositivo recibe contenido relevante. Universal Link es un paso evolutivo del deep link al enlace unificado.
| Característica | Custom URL Scheme | Universal Link |
|---|---|---|
| Formato | myapp://path | https://domain/path |
| Verificación | No | apple-app-site-association |
| Seguridad | Vulnerable a hijacking | Solo el propietario del dominio |
| Fallback | Error | Sitio web en Safari |
| Versión iOS | iOS 3+ | iOS 9+ |
La configuración de Universal Link incluye la parte del servidor y la del cliente. La del servidor: colocar el archivo apple-app-site-association en https://domain/.well-known/apple-app-site-association. La del cliente: registrar el dominio en Associated Domains en Xcode (Capabilities → Associated Domains → applinks:example.com). Después de eso, la aplicación recibe automáticamente todos los Universal Links para el dominio especificado.
Pasos de configuración:
La depuración de Universal Link es un dolor de cabeza común para los desarrolladores de iOS. Las principales causas de enlaces que no funcionan: archivo apple-app-site-association no accesible por HTTPS, appID incorrecto, Content-Type diferente de application/json, redirección desde la ruta /.well-known, almacenamiento en caché de la versión anterior del archivo (restablecer mediante Settings → Developer → Associated Domains Development). Apple ofrece la herramienta Validation Checker en Apple Developer Console para probar la asociación.
Branch y otras plataformas MMP simplifican la configuración de Universal Link: generan apple-app-site-association automáticamente y lo alojan en su propio dominio. El desarrollador solo necesita añadir el dominio de Branch a Associated Domains e integrar el SDK. Esto es especialmente conveniente para startups que no tienen su propia infraestructura de servidor para alojar el archivo AASA.
Universal Link tiene varias limitaciones. Primera: el archivo apple-app-site-association debe ser accesible estrictamente a través de HTTPS (HTTP no es compatible). Segunda: el enlace debe dirigirse al mismo dominio especificado en Associated Domains. Los Universal Links entre dominios no funcionan — cada dominio requiere una entrada separada en Capabilities y un archivo AASA separado. Tercera: Universal Link no funciona en WKWebView — solo en Safari y componentes del sistema.
Compatibilidad: iOS 9.0+ (Universal Link), watchOS 6.0+ (Handoff Universal Link), macOS 10.15+ (Catalyst y aplicaciones Mac). En versiones anteriores de iOS, el enlace se abre en Safari. Esto significa que en iOS 8 (menos del 1% de los dispositivos) Universal Link no funcionará. Se recomienda admitir también Custom URL Scheme como fallback para dispositivos antiguos si su audiencia incluye usuarios con versiones obsoletas.
Cambios en iOS 16+: Apple mejoró el manejo de Universal Link para SwiftUI. Se introdujo un nuevo modificador environment(\.openURL) con capacidad de procesamiento diferido. iOS 16 también permite abrir Universal Links en la aplicación incluso a través de SFSafariViewController. Para usuarios de iOS 16, se recomienda migrar completamente al manejo de Universal Link con SwiftUI, dejando el código de AppDelegate solo para compatibilidad hacia atrás.
Preguntas frecuentes
Universal Link utiliza una URL HTTPS estándar y se verifica mediante un archivo en el servidor. Custom URL Scheme utiliza un protocolo personalizado (myapp://) sin verificación, lo que lo hace vulnerable a la interceptación por otra aplicación que haya registrado el mismo esquema.
El archivo se coloca en la raíz del servidor HTTPS en /.well-known/apple-app-site-association (sin extensión .json). El servidor debe devolver Content-Type: application/json. Importante: sin redirecciones, el archivo debe ser accesible directamente.
Principales causas: Team ID o Bundle ID incorrectos en el archivo AASA, archivo no accesible por HTTPS, redirección, Content-Type incorrecto, caché de una versión anterior. Verifique a través de Developer → Associated Domains Development y reinicie el dispositivo para limpiar la caché.
No — Universal Link requiere un servidor HTTPS que aloje apple-app-site-association. Sin un dominio, Universal Link no funciona. Alternativas: Custom URL Scheme (menos seguro) o servicios de terceros (Branch, Firebase) con su propio dominio.
No — Universal Link es una tecnología exclusiva de Apple para iOS, iPadOS, watchOS y macOS. En Android, el equivalente se llama App Link (Android 6.0+), que utiliza Digital Asset Links (assetlinks.json) en lugar de apple-app-site-association.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también