Skip to content

Deeplinking - UIKit Apps

If you have a SwiftUI app, you'll want to read the SwiftUI Setup article instead.

Under the Signing & Capabilities tab, add the Associated Domains Capability, then add the applinks that you can support. One of these should be your MovableInk domain, such as mi.example.com. If you're unaware of what your MovableInk domain is, you can check with your CX Team.

associated domains example

To learn more about Universal Links, check out the Apple documentation.

The domain must be exact and does not support wildcards. Don't use *.example.com or example.*.com.

Initialize SDK

Apps using Scenes

Note

If your app is using iOS Scenes, use the following code below, otherwise you can you can skip forward to the Apps not using Scenes section.

In your AppDelegate, import MovableInk and call the start method when your app has finished launching.

You can supply an API Key for Behavior Events; learn more here, and a list of domains you'd like the SDK to handle. You can also supply the list of domains via the plist if you wish; learn more in the Setup Domains via Plist section below.

Note: do not use schemes, such as https:// when providing the domains.

import MovableInk

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
  func application(
    _ application: UIApplication, didFinishLaunchingWithOptions
    launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    MIClient.start(deeplinkDomains: ["mi.example.com"]) { result in
      // This closure will be called when the MovableInk SDK is able to resolve a URL 
      // that opens the app into a clickthrough link, or some error if one occurred
      //
      // result is a Result<String, DeeplinkResolutionError>
    }

    return true
  }

  // MARK: UISceneSession Lifecycle

  func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
    UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
  }

  func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
  }
}
#import <MovableInk/MovableInk-Swift.h>

@interface AppDelegate ()

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  [MIClient
  startWithApiKey:nil
  deeplinkDomains:@[@"mi.example.com"]
  launchOptions:launchOptions
  result:^(NSString * _Nullable url, NSError * _Nullable error) {
    // This block will be called when the MovableInk SDK is able to resolve a URL 
    // that opens the app into a clickthrough link
    //
    // url is the clickthrough link for a given Creative Tag
  }];

  return YES;
}

@end

In your SceneDelegate, call the handleUniversalLink methods:

import MovableInk

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
  var window: UIWindow?

  func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    guard let scene = (scene as? UIWindowScene) else { return }

    ...

    MIClient.handleUniversalLink(with: connectionOptions)
  }

  func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
    MIClient.handleUniversalLink(from: userActivity)
  }
}
#import <MovableInk/MovableInk-Swift.h>

@interface SceneDelegate ()

@end

@implementation SceneDelegate

- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
  [MIClient handleUniversalLinkWith: connectionOptions];
}

- (void)scene:(UIScene *)scene continueUserActivity:(NSUserActivity *)userActivity {
  [MIClient handleUniversalLinkFrom: userActivity];
}

@end

You can skip forward to the Deeplinking section.

Apps not using Scenes

In your AppDelegate, import MovableInk and call the start method when your app has finished launching.

You can supply an API Key for Behavior Events; learn more here, and a list of domains you'd like the SDK to handle. You can also supply the list of domains via the plist if you wish; learn more in the Setup Domains via Plist section below.

Note: do not use schemes, such as https:// when providing the domains.

import MovableInk

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
  func application(
    _ application: UIApplication, didFinishLaunchingWithOptions
    launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    MIClient.start(deeplinkDomains: ["mi.example.com"]) { result in
      // This closure will be called when the MovableInk SDK is able to resolve a URL 
      // that opens the app into a clickthrough link, or some error if one occurred
      //
      // result is a Result<String, DeeplinkResolutionError>
    }

    return true
  }

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

  func application(
    _ application: UIApplication, 
    continue userActivity: NSUserActivity, 
    restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void
  ) -> Bool {
    // Handler for Universal Links
    MIClient.handleUniversalLink(from: userActivity)

    return true
  }
}
#import <MovableInk/MovableInk-Swift.h>

@interface AppDelegate ()

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

  [MIClient
  startWithApiKey:nil
  deeplinkDomains:@[@"mi.example.com"]
  launchOptions:launchOptions
  result:^(NSString * _Nullable url, NSError * _Nullable error) {
    // This block will be called when the MovableInk SDK is able to resolve a URL 
    // that opens the app into a clickthrough link
    //
    // url is the clickthrough link for a given Creative Tag
  }];

  return YES;
}

- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
  return [MIClient handleUniversalLinkWithUrl: url];
}

- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler {
  return [MIClient handleUniversalLinkFrom: userActivity];
}

@end

Setup Domains via Plist

If you wish to load in your domains via the plist, the SDK can support that too.

In your Info.plist, add the movable_ink_universal_link_domains key as an array containing all the domains that you'd like the MovableInk SDK to handle. Note: These should only be domains that are shown in your Creative Tags, such as mi.example.com:

<key>movable_ink_universal_link_domains</key>
<array>
  <string>mi.example.com</string>
</array>

Info plist example

If you already set your domains in code, you don't need to do this.

Deeplinking

That's it! Now you can update your code to capture clickthrough urls and deeplink into your content.

If you don't already have a working implementation of deeplinking into your content, you can view the sample apps as an example.

You can go to the Swift Deeplinking Solutions article to learn more as well.