Elido
10 хв читанняМожливості

Глибокі посилання для мобільних додатків без SDK

Universal Links + Android App Links покривають 80% випадків використання диплінкінгу без платного SDK. Два файли асоціації, компроміси та інструкція

Marius Voß
DevRel · edge infra
Phone icon showing a deep-link flow from a tapped short link to an opened app with the iOS Universal Links and Android App Links logos juxtaposed

Глибоке посилання (deep link) - це просто URL-адреса, яку операційна система передає додатку замість браузера. Натисніть на посилання на пристрої, де встановлено додаток - він відкриється на потрібному екрані. Натисніть на пристрої без додатка - браузер виконає перенаправлення на веб-версію. Один URL, два результати, жодних JavaScript-заглушок, жодних сторонніх SDK для більшості випадків.

Команди часто переплачують за це. Branch.io, Adjust, AppsFlyer - їхні маркетингові матеріали починаються з deferred deep linking (відкладеного диплінкінгу): ви натискаєте на посилання до встановлення додатка, встановлюєте його, і додаток відкривається саме на тому контенті, на який ви перейшли. Ця функція дійсно складна і вимагає серверного відстеження за відбитком пальця (fingerprinting) або маніпуляцій з буфером обміну, оскільки маршрутизація посилань в ОС неактивна, поки додаток не встановлено. Але відкладений диплінкінг - це лише частина проблеми. Найпоширеніший випадок - «посилання відкривається у вже встановленому додатку» - повністю вирішується нативними примітивами ОС, які Apple і Google випустили у 2015 та 2015–16 роках відповідно, і які працюють лише з доменом, що ви контролюєте, та двома JSON-файлами.

Ця публікація саме про ці два JSON-файли.

TL;DR#

  • Apple Universal Links (iOS 9+) та Android App Links (Android 6.0+) обробляють сценарій «відкрити в додатку, якщо встановлено, інакше веб-версія» без сторонніх SDK.
  • Обидва вимагають домен під вашим контролем, що працює через HTTPS, з підтвердженим файлом асоціації в /.well-known/. ОС завантажує та кешує файл під час встановлення додатка, а не при кожному натисканні.
  • Скорочувач URL з власним доменом, наприклад go.acme.example, обслуговує обидва файли та стає посиланням, яке запускає маршрутизацію додатка - коротке посилання і є диплінком.
  • Що додає SDK, чого немає в примітивах ОС: відкладений диплінкінг, імовірнісна атрибуція встановлень та об'єднання кросплатформних ідентифікаторів. Якщо вам це потрібно, вартість SDK виправдана. Якщо ні - ви платите за функції, якими не користуєтеся.

Нативні примітиви ОС#

Apple представила Universal Links в iOS 9 (2015). Android випустила App Links в Android 6.0 Marshmallow (також 2015, реліз на пристроях протягом 2016). Обидва слідують одній концептуальній моделі: ОС підтверджує перевірений зв'язок між доменом та додатком, і коли посилання на цьому домені натискається, ОС спрямовує його до додатка, а не до браузера.

Перевірка є взаємною та працює за принципом offline-first. Під час встановлення додатка ОС завантажує файл асоціації з вашого домену та кешує його. Завантажувач Apple задокументований на developer.apple.com/ios/universal-links/ (доступ від 2026-05-12); еквівалент Google - на developer.android.com/training/app-links (доступ від 2026-05-12). Завантаження не відбувається під час кожного натискання на «гарячому» пристрої - завдяки кешуванню рішення про маршрутизацію не потребує мережевих запитів.

Саме перенаправлення - це стандартний HTTP 302. ОС перехоплює його до того, як завантажиться браузер, перевіряє свій локальний кеш і передає URL додатку, якщо знайдено збіг. Коли кеш оновлено, все рішення приймається локально. Edge-сервер, що обслуговує коротке посилання, видає редирект, а ОС бере на себе все інше.

Два файли#

apple-app-site-association#

Файл AASA має обслуговуватися за адресою https://yourdomain.example/.well-known/apple-app-site-association (Apple також перевіряє кореневий шлях https://yourdomain.example/apple-app-site-association для зворотної сумісності, але шлях .well-known є поточним стандартом). Він повинен надаватися через HTTPS з дійсним ланцюжком сертифікатів та заголовком Content-Type: application/json. CDN-завантажувач Apple відхиляє файли з неправильним заголовком Content-Type - це одна з найпоширеніших помилок конфігурації в продакшені.

Повна специфікація формату доступна за адресою developer.apple.com/documentation/xcode/supporting-associated-domains.

Мінімальна структура AASA:

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

appIDs - це поєднання вашого Apple Team ID та ідентифікатора пакета (bundle identifier) додатка, розділених крапкою. Масив components керує тим, які шляхи запускають маршрутизацію в додатку; все, що не відповідає компоненту, відкривається в браузері. Ви можете зареєструвати кілька додатків у масиві details - це корисно, якщо у вас є споживча та корпоративна версії одного продукту на одному домені.

Одна деталь, яку варто чітко зазначити: "/" з шаблоном зірочки, як-от /spring-*, - це збіг за префіксом шляху. Парсер AASA від Apple підтримує синтаксис шаблонів, визначений у документації Xcode, включаючи * (будь-який підрядок), ? (будь-який один символ) та об'єкти виключення. Якщо ви хочете зіставити кожен шлях на домені, використовуйте "/" : "/*". Якщо ви хочете виключити певний шлях із маршрутизації додатка - наприклад, сторінка /account/delete завжди повинна відкриватися в браузері - додайте об'єкт виключення перед зірочкою:

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

Правила оцінюються зверху вниз. Розміщуйте виключення перед загальними шаблонами.

assetlinks.json#

Файл Digital Asset Links від Android знаходиться за адресою https://yourdomain.example/.well-known/assetlinks.json. Специфікація підтримується Google за адресою 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 - це ідентифікатор вашого додатка в Play Store. sha256_cert_fingerprints - це відбиток SHA-256 сертифіката, що використовується для підпису APK - не SHA-1 і не MD5. Ви можете знайти відбиток у Play Console у розділі App Integrity або запустивши keytool -list -v -keystore your.keystore. Якщо ви випускаєте і налагоджувальну (debug), і робочу (production) версії, додайте обидва відбитки в масив.

На відміну від файлу AASA, файл асоціації Android не підтримує фільтрацію шляхів на рівні файлу. Зіставлення шляхів для App Links виконується в AndroidManifest.xml через <intent-filter> з android:pathPrefix, android:pathPattern або новішим android:pathAdvancedPattern (доступно з Android 12). Файл assetlinks.json підтверджує володіння доменом; маніфест оголошує, які шляхи обробляє додаток.

Послідовність розпізнавання AASA: натискання на коротке посилання, завантаження ОС під час першого встановлення, спрацювання кешу при наступних натисканнях

Як вписується скорочувач URL#

Коротке посилання на кшталт go.acme.example/spring-launch - це просто URL-адреса на домені. З точки зору ОС, якщо go.acme.example має дійсний файл AASA або assetlinks.json, будь-яке натискання на посилання в межах цього домену підлягає маршрутизації в додаток.

Це конфігурація, яку ми підтримуємо безпосередньо для власних доменів в Elido. Коли ви реєструєте go.acme.example як власний домен у своєму робочому просторі, Elido забезпечує HTTPS-редирект для кожного слага (slug) на цьому домені. Ви надаєте два файли асоціації з того самого домену - або на власному сервері за проксі-шляхом, або через HTTPS-сервер самого домену. Відбувається edge-редирект; ОС перехоплює його до завантаження браузера, звіряється з кешем AASA/App Links і відкриває додаток, якщо знайдено збіг.

Архітектура детальніше описана в публікації про власні домени для коротких посилань - налаштування видачі TLS та CNAME застосовуються тут точно так само, як описано там. Шар диплінкінгу є додатковим: той самий домен, той самий редирект, плюс два JSON-файли.

Для продуктових команд, які використовують короткі посилання для залучення мобільних користувачів - реферальні коди, посилання-запрошення, сценарії «поділитися рецептом» - цей патерн покриває майже все без додавання залежностей SDK до бінарного файлу додатка.

Що додає SDK#

Три можливості, які не надають нативні примітиви ОС:

Відкладений диплінкінг. Користувач натискає на ваше посилання перед встановленням додатка. Після першого запуску після встановлення додаток відкривається саме на тому контенті, на який він перейшов. Universal Links в iOS та App Links в Android не спрацьовують, коли додаток не встановлено - URL веде до браузера, намір втрачається. Для його відновлення потрібен серверний збіг за відбитком пальця (IP + User-Agent + мітка часу, імовірнісний метод) або трюк із буфером обміну в iOS. Branch, Adjust та AppsFlyer реалізують це; нюанси навколо запитів App Tracking Transparency та поведінки Safari роблять самостійну реалізацію нетривіальною.

Атрибуція встановлень у масштабі. Нативний шлях ОС дає вам відкриття додатка зі шляхом URL, але якщо додаток не був встановлений під час першого натискання, ланцюжок атрибуції розривається. Узгодження кліків із встановленнями через SKAN на iOS та Play Install Referrer на Android можливе без платного SDK, але вимагає інтеграційної роботи, яку постачальники атрибуції вже виконали.

Об'єднання кросплатформних ідентифікаторів. Зв'язування натискання з адресою електронної пошти, контактом у CRM або веб-сесією. Нативний шлях ОС анонімний з точки зору сервісу посилань. Постачальники SDK підтримують постійний графік пристроїв. Створення такого власноруч - це суттєвий проект інфраструктури даних.

Якщо жоден із цих трьох пунктів не є критичним, примітивів ОС буде достатньо. Якщо один з них важливий, чітко визначте обсяг - можливо, вам потрібні лише відкладені диплінки, один API-інтерфейс, а не повний SDK.

Матриця функцій: нативні примітиви ОС та платний SDK однаково відкривають додаток і повертаються до веб-версії, але лише SDK додає відкладений диплінкінг, атрибуцію встановлень за кожним кліком та кросплатформний граф ідентифікаторів

Інструкція з налаштування#

Вимоги до DNS та HTTPS#

Обидва файли повинні обслуговуватися через HTTPS з домену, посилання якого ви хочете зробити диплінками. Сертифікат повинен належати до публічного кореневого центру сертифікації (CA); самопідписані сертифікати призводять до мовчазної помилки завантажувачів Apple і Google. Сертифікати Let's Encrypt працюють чудово.

TLS домену також не повинен перенаправляти шлях /.well-known/ перед наданням файлу. Якщо ваш сервер виконує редирект на www. до того, як завантажувач Apple зможе дістатися до https://yourdomain.example/.well-known/apple-app-site-association, завантаження не вдасться. Завантажувач Apple слідує за одним редиректом, але завантажувач assetlinks від Google взагалі не слідує за редиректами - файл повинен бути за точним шляхом, без редиректів.

iOS: Associated Domains entitlement#

У Xcode, у розділі Signing & Capabilities вашої цілі (target), додайте Associated Domains entitlement зі значенням applinks:go.acme.example. Якщо ви тестуєте в налагоджувальній збірці (не розповсюдженій через TestFlight або App Store), додайте ?mode=developer до значення entitlement: applinks:go.acme.example?mode=developer. Це вказує ОС на необхідність повторного завантаження AASA при кожному запуску, а не використання кешу часу встановлення - корисно для ітерації над шаблонами шляхів без повторного встановлення зі Store кожного разу.

CDN Apple, який завантажує ваш файл AASA, - це власна інфраструктура Apple, а не сам пристрій. Apple попередньо завантажує та кешує файли AASA з вашого домену та надає їх пристроям під час встановлення додатка, що означає, що файл повинен бути доступним для сканерів Apple, а не лише для кінцевого користувача. Це також означає затримку розповсюдження - зміни у файлі AASA можуть зайняти години, щоб дійти до всіх пристроїв через кеш Apple. Для розробників, яким потрібна швидка ітерація над шаблонами шляхів, entitlement ?mode=developer обходить CDN Apple і завантажує дані безпосередньо з вашого сервера.

У AndroidManifest.xml, всередині активності, яка повинна обробляти глибокі посилання:

<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>

android:autoVerify="true" вказує Android на спробу перевірки домену через assetlinks.json. Без цього користувач бачить вікно вибору програми (disambiguation sheet) при кожному натисканні, а не пряме відкриття додатка. Перевірка відбувається під час встановлення; пристрій звертається до https://go.acme.example/.well-known/assetlinks.json і перевіряє, чи є відбиток сертифіката встановленого додатка в списку.

Валідатори та поширені помилки#

Apple надає валідатор за адресою search.developer.apple.com/appsearch-validation-tool/, який перевіряє, чи може CDN Apple завантажити та проаналізувати ваш файл AASA. Введіть свій домен, і він поверне результат аналізу або конкретну помилку. Поширені причини невдач:

  • Неправильний Content-Type. Якщо ваш сервер повертає text/plain або application/octet-stream, валідатор повідомляє, що файл неможливо прочитати, навіть якщо JSON коректний. Встановіть Content-Type: application/json явно.
  • Відсутні або невідповідні appIDs. Префікс Team ID в appIDs повинен точно відповідати Team ID у вашому обліковому записі Apple Developer, включаючи регістр. Один неправильний символ призведе до мовчазної помилки під час натискання.
  • Проблеми з ланцюжком сертифікатів. Якщо ваш домен надає сертифікат, який не пов'язаний з публічним кореневим центром (часто в середовищах тестування з локальними коренями CA), завантажувач Apple відхиляє файл.

Валідатор Google - це Digital Asset Links API: https://digitalassetlinks.googleapis.com/v1/statements:list?source.web.site=https://go.acme.example&relation=delegate_permission/common.handle_all_urls. JSON-відповідь містить усі твердження, які Google підтвердив для вашого домену. Якщо відповідь порожня або в ній відсутня назва вашого пакета, Android не зможе автоматично підтвердити додаток під час встановлення. Поширені причини невдач:

  • Редирект на шляху assetlinks. Як зазначалося: завантажувач Google не слідує редиректам.
  • Неправильний відбиток сертифіката. Debug APK та release APK підписуються різними ключами. Якщо ви вказали лише release-відбиток, налагоджувальні збірки не пройдуть перевірку. Вкажіть обидва.
  • Файл надається з CORS, але з неправильним заголовком для запиту на перевірку. Завантажувачу байдуже на CORS, але деякі конфігурації CDN повертають 403 при GET із діапазону IP-адрес Google, якщо шлях не в списку дозволених для кешування. Перевірте, що /.well-known/assetlinks.json повертає 200 із зовнішнього HTTP-клієнта, а не лише з вашого браузера.

Суть компромісу#

Відмова від SDK для диплінкінгу економить приблизно 150–250 КБ стиснутого розміру бінарного файлу та усуває виклик API під час встановлення до серверів постачальника атрибуції. Це видаляє відносини з передачі даних із вашої політики конфіденційності та може спростити записи про обробку даних згідно з GDPR. Це реальні, хоч і скромні переваги.

Вартість полягає в тому, що атрибуція під час встановлення стає приблизною або відсутня. Якщо користувач натисне на ваше посилання перед встановленням додатка, ви побачите встановлення в App Store Connect або Play Console, але не зможете пов'язати його з конкретним натисканням на посилання. Ви все ще можете проводити експерименти зі смарт-посиланнями щоб порівняти, які кампанії приносять більше встановлень - відносні сигнали зберігаються - але атрибуція для конкретного пристрою та кліку потребує шару фінгерпринтингу SDK.

Для команд на початкових етапах розвитку, де вартість встановлення за кожним каналом (CPI) ще не визначає бюджетні рішення, початок із примітивів ОС є розумним шляхом. Додайте SDK для атрибуції пізніше, коли дані стануть дійсно корисними для прийняття рішень.

До та після відмови від SDK для диплінкінгу: економія 150-250 КБ бінарного файлу та менше потоків даних праворуч, в обмін на втрату атрибуції встановлень за кожним кліком, яка стає приблизною

Для розробників посібник з налаштування диплінків Elido, повна схема процесу перевірки домену, конфігурація проксі AASA та варіанти обслуговування assetlinks.json задокументовані там. Сторінка рішень для продуктових команд охоплює ширші випадки використання смарт-посилань та мобільних посилань.


Маріус Восс - DevRel + edge infra в Elido. Він відповідає за сервіси edge-redirect та domain-manager.

Спробуйте Elido

Вставте URL - отримайте коротке посилання

Без реєстрації. Посилання живе 30 днів. Зареєструйтесь, щоб зберегти назавжди.

Безкоштовно, без реєстрації · 2 на день

Спробуйте Elido

URL-скорочувач із хостингом у ЄС: власні домени, глибока аналітика, відкритий API. Безкоштовний тариф - без кредитної картки.

Теги
mobile deep linking
universal links
app links android
deep linking without sdk
apple app site association
digital asset links

Читати далі