Deep linking allows you to show different onboarding flows based on where your users come from. This is perfect for tailoring your user experience to match the messaging from different ad campaigns, product pages, or referral sources.

How It Works

Instead of creating complex variant systems, Muta’s placement system already supports deep linking scenarios perfectly. You simply create different placements for different user sources.

Example: Multi-Channel Ad Campaign

Let’s say you’re running ads on TikTok, Instagram, and LinkedIn with different messaging for each platform. You want your onboarding to match the ad creative users clicked on.

Step 1: Create Separate Placements

In your Muta dashboard, create placements for each source:
  • onboarding-tiktok - Fun, video-focused onboarding
  • onboarding-instagram - Visual, story-driven flow
  • onboarding-linkedin - Professional, feature-focused flow
  • onboarding-default - Generic flow for organic users
import UIKit
import Muta

// In your AppDelegate or SceneDelegate
func handleDeepLink(url: URL) {
    // Parse the source from the URL
    let components = URLComponents(url: url, resolvingAgainstBaseURL: true)
    let source = components?.queryItems?.first(where: { $0.name == "source" })?.value
    
    // Map sources to placement IDs
    let placementMap = [
        "tiktok": "onboarding-tiktok",
        "instagram": "onboarding-instagram",
        "linkedin": "onboarding-linkedin"
    ]
    
    let placementId = placementMap[source ?? ""] ?? "onboarding-default"
    
    // Display the appropriate onboarding flow
    Muta.shared.displayPlacement(
        placementId: placementId,
        presentingViewController: topViewController()
    )
}

// Handle Universal Links
func application(_ application: UIApplication, 
                continue userActivity: NSUserActivity,
                restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
    if userActivity.activityType == NSUserActivityTypeBrowsingWeb,
       let url = userActivity.webpageURL {
        handleDeepLink(url: url)
        return true
    }
    return false
}

// Handle URL Schemes
func application(_ app: UIApplication, 
                open url: URL,
                options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
    handleDeepLink(url: url)
    return true
}

Step 3: Configure Your Ad Campaign URLs

Set up your ad campaign URLs to include source information:
  • TikTok: myapp://onboard?source=tiktok
  • Instagram: myapp://onboard?source=instagram
  • LinkedIn: myapp://onboard?source=linkedin

SwiftUI Integration

For SwiftUI apps:
import SwiftUI
import Muta

struct DeepLinkHandler: ViewModifier {
    @State private var showingPlacement = false
    @State private var placementId = ""
    
    func body(content: Content) -> some View {
        content
            .onOpenURL { url in
                handleDeepLink(url: url)
            }
            .mutaPlacement(
                isPresented: $showingPlacement,
                placementId: placementId
            )
    }
    
    private func handleDeepLink(url: URL) {
        let components = URLComponents(url: url, resolvingAgainstBaseURL: true)
        let source = components?.queryItems?.first(where: { $0.name == "source" })?.value
        
        let placementMap = [
            "tiktok": "onboarding-tiktok",
            "instagram": "onboarding-instagram",
            "linkedin": "onboarding-linkedin"
        ]
        
        placementId = placementMap[source ?? ""] ?? "onboarding-default"
        showingPlacement = true
    }
}

// Usage
@main
struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .modifier(DeepLinkHandler())
        }
    }
}

Best Practices

1. Naming Conventions

Use clear, consistent naming for your placements:
  • [placement-name]-[source]
  • [placement-name]-[source]-[campaign]
  • [placement-name]-[source]-[variant]

2. Always Have a Default

Always create a default placement as a fallback for:
  • Organic users
  • Unrecognized sources

URL Scheme Configuration

Don’t forget to configure your URL schemes in Info.plist:
<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>myapp</string>
        </array>
    </dict>
</array>

Next Steps