Claude
Skills
Sign in
Back

deep-linking

Included with Lifetime
$97 forever

Universal links and deep linking skill for implementing iOS Universal Links, Android App Links, custom URL schemes, and deferred deep linking across mobile platforms.

General

What this skill does


# Deep Linking Skill

Comprehensive deep linking implementation for iOS and Android, including Universal Links, App Links, custom URL schemes, and deferred deep linking.

## Overview

This skill provides capabilities for implementing deep linking across mobile platforms, enabling users to navigate directly to specific content within your app from external sources like web links, notifications, emails, and other apps.

## Capabilities

### iOS Universal Links
- Configure apple-app-site-association (AASA) file
- Set up Associated Domains entitlement
- Implement NSUserActivity handling
- Validate Universal Links configuration
- Handle fallback to App Store

### Android App Links
- Configure assetlinks.json (Digital Asset Links)
- Set up intent filters for App Links
- Implement deep link handling
- Verify App Links configuration
- Handle fallback to Play Store

### Custom URL Schemes
- Register custom URL schemes
- Handle URL scheme callbacks
- Parse URL parameters
- Implement scheme validation
- Cross-app communication

### Deferred Deep Linking
- Configure Branch.io or Firebase Dynamic Links
- Handle first-open attribution
- Pass deep link data through install
- Track deep link conversions
- Implement fallback flows

### Deep Link Routing
- Design URL structure and routing
- Implement in-app navigation
- Handle authentication requirements
- Manage deep link state persistence
- Track deep link analytics

## Prerequisites

### iOS Development
```bash
# Enable Associated Domains capability in Xcode
# Signing & Capabilities > + Capability > Associated Domains

# Add domain: applinks:example.com
```

### Android Development
```groovy
// No additional dependencies for basic App Links
// For Firebase Dynamic Links:
dependencies {
    implementation platform('com.google.firebase:firebase-bom:32.7.0')
    implementation 'com.google.firebase:firebase-dynamic-links'
}

// For Branch.io:
dependencies {
    implementation 'io.branch.sdk.android:library:5.+'
}
```

### Web Server Requirements
```bash
# iOS: Host AASA file at
# https://example.com/.well-known/apple-app-site-association

# Android: Host assetlinks.json at
# https://example.com/.well-known/assetlinks.json
```

## Usage Patterns

### Apple App Site Association (AASA) File
```json
{
  "applinks": {
    "apps": [],
    "details": [
      {
        "appID": "TEAMID.com.example.app",
        "paths": [
          "/products/*",
          "/users/*",
          "/orders/*",
          "NOT /admin/*"
        ]
      }
    ]
  },
  "webcredentials": {
    "apps": ["TEAMID.com.example.app"]
  }
}
```

### iOS Universal Links Implementation (SwiftUI)
```swift
import SwiftUI

@main
struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .onOpenURL { url in
                    handleDeepLink(url)
                }
        }
    }

    func handleDeepLink(_ url: URL) {
        guard let components = URLComponents(url: url, resolvingAgainstBaseURL: true),
              let host = components.host else {
            return
        }

        let path = components.path
        let queryItems = components.queryItems ?? []

        // Route based on path
        switch (host, path) {
        case ("example.com", let p) where p.hasPrefix("/products/"):
            let productId = String(p.dropFirst("/products/".count))
            DeepLinkRouter.shared.navigateTo(.product(id: productId))

        case ("example.com", let p) where p.hasPrefix("/users/"):
            let userId = String(p.dropFirst("/users/".count))
            DeepLinkRouter.shared.navigateTo(.profile(userId: userId))

        case ("example.com", "/orders"):
            DeepLinkRouter.shared.navigateTo(.orders)

        default:
            DeepLinkRouter.shared.navigateTo(.home)
        }
    }
}

// Deep Link Router
class DeepLinkRouter: ObservableObject {
    static let shared = DeepLinkRouter()

    @Published var currentDestination: Destination = .home

    enum Destination: Equatable {
        case home
        case product(id: String)
        case profile(userId: String)
        case orders
    }

    func navigateTo(_ destination: Destination) {
        DispatchQueue.main.async {
            self.currentDestination = destination
        }
    }
}
```

### iOS Universal Links (UIKit)
```swift
import UIKit

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

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

        handleUniversalLink(url)
    }

    func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
        guard let url = URLContexts.first?.url else { return }
        handleCustomScheme(url)
    }

    private func handleUniversalLink(_ url: URL) {
        // Route to appropriate view controller
        let router = DeepLinkRouter.shared
        router.route(url: url)
    }

    private func handleCustomScheme(_ url: URL) {
        // Handle myapp:// scheme
        guard url.scheme == "myapp" else { return }
        let router = DeepLinkRouter.shared
        router.route(url: url)
    }
}
```

### Android assetlinks.json
```json
[
  {
    "relation": ["delegate_permission/common.handle_all_urls"],
    "target": {
      "namespace": "android_app",
      "package_name": "com.example.app",
      "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"
      ]
    }
  }
]
```

### Android App Links Implementation (Kotlin)
```kotlin
// AndroidManifest.xml
/*
<activity android:name=".MainActivity"
    android:exported="true">
    <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="example.com"
              android:pathPrefix="/products" />
        <data android:scheme="https"
              android:host="example.com"
              android:pathPrefix="/users" />
    </intent-filter>

    <!-- Custom URL scheme -->
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="myapp" />
    </intent-filter>
</activity>
*/

// MainActivity.kt
class MainActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Handle deep link on cold start
        handleIntent(intent)

        setContent {
            MyApp()
        }
    }

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        // Handle deep link when app is already running
        handleIntent(intent)
    }

    private fun handleIntent(intent: Intent?) {
        val action = intent?.action
        val data = intent?.data

        if (action == Intent.ACTION_VIEW && data != null) {
            handleDeepLink(data)
        }
    }

    private fun handleDeepLink(uri: Uri) {
        val path = uri.path ?: return
        val host = uri.host

        when {
            path.startsWith("/products/") -> {
                val productId = path.removePrefix("/products/")
                navigateToProduct(productId)
            }
            path.startsWith("/users/") -> {
                val userId = path.removePrefix("/users/")
                navigateToProfile(userId)
            }
            path == "/orders" -> {
                navigateToOrders()
            }
            else -> {
                navigateToHome()
            }
        }
    }
}
```

### Jetpack Compose Navigation with Deep Links
```kotli

Related in General