Реалізація Deep Linking в мобільному додатку

TRUETECH займається розробкою, підтримкою та обслуговуванням мобільних додатків iOS, Android, PWA. Маємо великий досвід та експертизу для публікації мобільних додатків до популярних маркетів Google Play, App Store, Amazon, AppGallery та інші.

Розробка та підтримка будь-яких видів мобільних додатків:

Інформаційні та розважальні мобільні програми
Новинки, ігри, довідники, онлайн-каталоги, погодні, фітнес та здоров'я, туристичні, освітні, соціальні мережі та месенджери, квіз, блоги та подкасти, форуми, агрегатори
Мобільні програми електронної комерції
Інтернет-магазини, B2B-додатки, маркетплейси, онлайн-обмінники, кешбек-сервіси, біржі, дропшиппінг-платформи, програми лояльності, доставка їжі та товарів, платіжні системи
Мобільні програми для управління бізнес-процесами
CRM-системи, ERP-системи, управління проектами, інструменти для команди продажів, облік фінансів, управління виробництвом, логістика та доставка, управління персоналом, системи моніторингу даних
Мобільні програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, платформи надання електронних послуг, платформи кешбеку, відеохостинги, тематичні портали, платформи онлайн-бронювання та запису, платформи онлайн-торгівлі

Це лише деякі з типів мобільних додатків, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 1735 послуг
Реалізація Deep Linking в мобільному додатку
Середній
від 1 дня до 3 днів
Часті запитання

Наші компетенції:

Етапи розробки

Останні роботи

  • image_mobile-applications_feedme_467_0.webp
    Розробка мобільного додатка для компанії FEEDME
    792
  • image_mobile-applications_xoomer_471_0.webp
    Розробка мобільного додатку для компанії XOOMER
    671
  • image_mobile-applications_rhl_428_0.webp
    Розробка мобільного додатку для компанії RHL
    1097
  • image_mobile-applications_zippy_411_0.webp
    Розробка мобільного додатку для компанії ZIPPY
    969
  • image_mobile-applications_affhome_429_0.webp
    Розробка мобільного додатку для компанії Affhome
    914
  • image_mobile-applications_flavors_409_0.webp
    Розробка мобільного додатку для компанії FLAVORS
    495

Реалізація Deep Linking у мобільному додатку

Deep Link — це URL, який відкриває конкретний екран у мобільному додатку. Не головну сторінку, а саме потрібний контент: товар, профіль, статтю, сторінку оплати. Здавалось би просто — поки не стикнешся з різницею між Custom URL Scheme, Universal Links, App Links, Deferred Deep Links та тим, як кожен із них ломається в своєму специфічному місці.

Три типи deep links

Custom URL Scheme (myapp://product/123) — найпростіший, але найненадійніший. Якщо додаток не встановлено — браузер показує помилку, ніякого fallback. Кілька додатків можуть зареєструвати одну схему — непередбачувано, яка відкриється. Підходить тільки для внутрішніх сценаріїв: крос-апп комунікація в межах своєї екосистеми.

Universal Links (iOS) / App Links (Android) — HTTP/HTTPS посилання, які операційна система перехоплює та відкриває в додатку замість браузера. Якщо додаток не встановлено — звичайний браузер. Надійно, верифіковано, правильний fallback. Це стандарт для production.

Deferred Deep Links — посилання зберігається навіть якщо додаток не встановлено. Користувач натискає посилання → App Store → встановлює додаток → відкриває → потрапляє на потрібний екран. Реалізується через Firebase Dynamic Links (deprecated з 2025-08), Branch.io або Adjust.

Universal Links на iOS

Потребує файл apple-app-site-association на сервері:

// https://yourdomain.com/.well-known/apple-app-site-association
{
  "applinks": {
    "apps": [],
    "details": [
      {
        "appIDs": ["TEAMID.com.company.app"],
        "components": [
          { "/": "/product/*", "comment": "Сторінки товарів" },
          { "/": "/profile/*" },
          { "/": "/order/*" },
          { "/": "/promo/*", "?": { "ref": "?" } }
        ]
      }
    ]
  }
}

AASA повинен відданий з Content-Type: application/json, без редиректів, з кодом 200. Apple CDN кешує його агресивно — зміни вступають у силу з затримкою до 48 годин (Apple періодично обходить AASA у фоні). На iOS 16+ додано "mode": "developer" для прискорення оновлення AASA в debug.

У Info.plist — Associated Domains:

<key>com.apple.developer.associated-domains</key>
<array>
    <string>applinks:yourdomain.com</string>
    <string>applinks:www.yourdomain.com</string>
</array>

Обробка в SceneDelegate:

func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
    guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
          let url = userActivity.webpageURL else { return }
    DeepLinkRouter.shared.handle(url: url)
}

App Links на Android

Аналог Universal Links. Файл assetlinks.json на сервері:

// https://yourdomain.com/.well-known/assetlinks.json
[{
  "relation": ["delegate_permission/common.handle_all_urls"],
  "target": {
    "namespace": "android_app",
    "package_name": "com.company.app",
    "sha256_cert_fingerprints": ["AA:BB:CC:..."]
  }
}]

SHA256 fingerprint берется із keystore: keytool -list -v -keystore release.jks. Для debug та release — різні fingerprints, обидва потрібні в production assetlinks.json або використовуйте різні домени.

У AndroidManifest.xml:

<activity android:name=".MainActivity">
    <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="yourdomain.com"
            android:pathPrefix="/product/" />
    </intent-filter>
</activity>

android:autoVerify="true" запускає верифікацію домена при встановленні. Перевірити верифікацію: adb shell pm get-app-links com.company.app. Якщо STATE_APPROVED — App Links працюють. Якщо STATE_NO_RESPONSE або STATE_FAILED_VERIFICATION — проблема з AASA або сертифікатом.

Частої проблеми на Android 12+: навіть при успішній верифікації користувач може вибрати "Відкривати в браузері" в системних налаштуваннях. Додаток не може це контролювати програмно.

Роутер на клієнті

Централізований роутер — обов'язково. Ніяких if (url.contains("product")) розкиданих по коду.

// Android
class DeepLinkRouter {
    fun handle(intent: Intent, navController: NavController) {
        val uri = intent.data ?: return
        val path = uri.path ?: return

        val route = when {
            path.matches(Regex("/product/(\\d+)")) -> {
                val productId = uri.lastPathSegment ?: return
                Route.ProductDetail(productId)
            }
            path.matches(Regex("/order/(\\w+)")) -> {
                Route.OrderDetail(uri.lastPathSegment ?: return)
            }
            path == "/profile" -> Route.Profile
            path.startsWith("/promo/") -> {
                val ref = uri.getQueryParameter("ref")
                Route.Promo(uri.lastPathSegment ?: return, ref)
            }
            else -> {
                // Невідомий маршрут — відкрити в браузері
                openInBrowser(uri)
                return
            }
        }
        navController.navigate(route)
    }
}
// iOS
final class DeepLinkRouter {
    func handle(url: URL) {
        guard let components = URLComponents(url: url, resolvingAgainstBaseURL: false) else { return }
        let pathComponents = components.path.split(separator: "/").map(String.init)

        switch pathComponents.first {
        case "product" where pathComponents.count == 2:
            navigationManager.push(.productDetail(id: pathComponents[1]))
        case "order" where pathComponents.count == 2:
            navigationManager.push(.orderDetail(id: pathComponents[1]))
        case "profile":
            navigationManager.push(.profile)
        default:
            UIApplication.shared.open(url) // fallback в браузер
        }
    }
}

Deferred Deep Links через Branch.io

Firebase Dynamic Links офіційно deprecated з серпня 2025. Альтернативи: Branch.io, Adjust, AppsFlyer, Airbridge — всі надають SDK для iOS та Android.

Branch.io SDK відстежує клік до встановлення та відновлює параметри після першого запуску:

Branch.getInstance().initSession(
    branchReferralInitListener = { params, error ->
        if (error == null && params != null) {
            val productId = params.getString("product_id")
            val ref = params.getString("ref")
            if (productId != null) {
                deepLinkRouter.navigate(Route.ProductDetail(productId))
            }
        }
    },
    isReferrable = true,
    activity = this
)

Branch initSession викликається при кожному запуску — SDK визначає, був це organic запуск чи перехід по посиланню.

Тестування

Верифікація App Links: adb shell am start -W -a android.intent.action.VIEW -d "https://yourdomain.com/product/123" com.company.app

Верифікація Universal Links на симуляторі — неможлива. Тільки на фізичному пристрої через xcrun simctl openurl booted "https://yourdomain.com/product/123" для симулятора iOS 14+, або через Notes.app → натиск по посиланню.

Перевірка AASA: curl -I https://yourdomain.com/.well-known/apple-app-site-association — потребує 200, без редиректів.

Apple надає валідатор: https://app-site-association.cdn-apple.com/a/v1/yourdomain.com — як Apple кешує ваш AASA файл.

Типові помилки

Redirect на CDN ломає App Links. Якщо yourdomain.com редиректить на www.yourdomain.com, а AASA на одному — верифікація падає. AASA потрібен на обох доменах.

Неправильний Content-Type. AASA з Content-Type: text/html — Apple не приймає. Тільки application/json.

Deep link при cold start vs warm start. На Android Intent приходить в onCreate при cold start та в onNewIntent при warm start. Якщо обробляйте тільки в onCreate — deep link при warm start ігнорується. Обробляйте в обох місцях.

Навігація до ініціалізації. Роутер намагається навігувати до того, як NavController готовий. Потрібна черга pending deep links, яка обробляється після ініціалізації навігації.

Реалізація Universal Links + App Links + роутер + deferred deep links: 2-4 тижні. Вартість розраховується індивідуально.