AppsOnAir-AppLink

2.0.0

A self-hosted dynamic link service for app download tracking, deep linking, and engagement analytics for ios - an alternative to Firebase Dynamic Links
apps-on-air/AppsOnAir-iOS-AppLink

What's New

v2.0.0

2026-08-20T11:55:07Z

#What's New:

  • getReferralInfo() is now deprecated, use getAttributionInfo() instead.

  • Introduced getAttributionInfo() method.

    • Returns the same data as getReferralInfo() with additional isFirstLaunch, firstInstallTime, isConsumed and attributionStatus fields included in the response.
  • Introduced onAttributionListener() listener.

    • When an attribution is detected, and again every time the app returns to the foreground so the payload stays current.
  • Added appsFlyer and attributionTtl params to AppLinkParams for AppsFlyer attribution support in createAppLink method.

Deprecated:

  • onReferralLinkDetected() β€” use onAttributionListener().
  • getReferralInfo() and getReferralDetails() β€” use getAttributionInfo().

pub package

AppsOnAir-AppLink

Version License Platform

Overview

AppsOnAir-AppLink enables you to handle deep links, and in-app routing seamlessly in your IOS app. With a simple integration, you can configure, manage, and act on links from the web dashboard in real time.

πŸš€ Features

  • βœ… Deep link support (URI scheme, AppLinks)
  • βœ… Fallback behavior (e.g., open App Store)
  • βœ… Custom domain support
  • βœ… Referral tracking
  • βœ… AppsFlyer attribution params (appsFlyer) and attribution TTL (attributionTtl) on link creation
  • βœ… Seamless migration from Firebase Dynamic Links to AppLink

Note: For comprehensive instructions on migrating Firebase Dynamic Links to AppLink, refer to the documentation.

Installation

AppsOnAir-AppLink supports installation via CocoaPods and Swift Package Manager.

CocoaPods

To install via CocoaPods, simply add the following line to your Podfile:

pod 'AppsOnAir-AppLink'

Then run:

pod install

Swift Package Manager

You can add AppsOnAir-AppLink to your project using Swift Package Manager in one of the following ways:

Using Xcode

  1. Open your project in Xcode.

  2. Go to File β†’ Add Package Dependencies...

  3. Enter the package URL:

    https://github.com/apps-on-air/AppsOnAir-iOS-AppLink.git
    
  4. Select the version rule (e.g., Up to Next Major Version) and click Add Package.

  5. Choose the AppsOnAir-AppLink library and add it to your target.

Using Package.swift

If you are integrating AppsOnAir-AppLink into another Swift package, add it to the dependencies array in your Package.swift:

dependencies: [
    .package(
        url: "https://github.com/apps-on-air/AppsOnAir-iOS-AppLink.git",
        from: "2.0.0"
    )
]

Then add AppsOnAir-AppLink to the dependencies of the targets that need it:

.target(
    name: "YourTarget",
    dependencies: [
        .product(name: "AppsOnAir-AppLink", package: "AppsOnAir-iOS-AppLink")
    ]
)

Example

To run the example project, clone the repo, and run pod install from the Example directory first.

Requirements

Minimum deployment target: 13.0

USAGE

Enable the Advanced Deferred AppLink feature in your iOS app by adding the EnableAdvancedDeferredLink Boolean flag to your Info.plist file.

<key>EnableAdvancedDeferredLink</key>
<true/>

Add AppsonairAppId in your app info.plist file.

<key>AppsonairAppId</key>
<string>XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX</string>

how to get AppsonairAppId for more details check this URL

Add YOUR_PROJECT.entitlements file and add below code file for Add Associated Domain

<!-- If Using Universal Links -->
<key>com.apple.developer.associated-domains</key>
<array>
    <string>applinks:YOUR_DOMAIN</string> <!-- Replace with your actual domain -->
</array>

ℹ️ Note: After configuring the Associated Domain for Universal Links, it may take up to 24 hours for the changes to be reflected and become active. The Associated Domain setup and verification process is managed by Apple.

If you want to add Custom URL schema for add below code to the app's info.plist file for.

<!-- If Using Custom Url Schema -->
<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleURLName</key>
        <string>YOUR_URL_NAME</string>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>YOUR_CUSTOM_URL_SCHEME</string> <!-- Replace with your custom URL scheme -->
        </array>
    </dict>
</array>

1. Initialize the AppLink services

Firstly, import AppsOnAir_AppLink in appDelegate

Swift / SwiftUI

import AppsOnAir_AppLink

Objective-C

#import "AppsOnAir_AppLink/AppsOnAir_AppLink-Swift.h"

Objective-C++

#import "AppsOnAir-AppLink/AppLinkService.h"

App-Link Implement Code

When using SwiftUI, it is necessary to add the .onOpenURL modifier in ContentView.swift, directly after any layout container such as VStack, Button, or similar views.

VStack {
    // Your UI components here
}
.onOpenURL { url in
    AppLinkService.shared.handleAppLink(incomingURL: url)
}

When using Swift with a SceneDelegate, it is necessary to add the following method inside SceneDelegate.swift

func scene(_ scene: UIScene, openURLContexts URLContexts:   Set<UIOpenURLContext>) {

}

func scene(_ scene: UIScene, continue userActivity:NSUserActivity) {

}

SwiftUI

import SwiftUI
import AppsOnAir_AppLink

@main
struct appsonairApp: App {
  
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

class AppDelegate: UIResponder, UIApplicationDelegate {
  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        AppLinkService.shared.initialize { url, linkInfo in
            //Write the code for handling flow based on url
        } onAttributionListener: { attributionInfo in
            //Write the code for handling attribution flow
        }
      return true
  }
}

Swift

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Help to initialize link services
        AppLinkService.shared.initialize { url, linkInfo in
            //Write the code for handling flow based on url
        } onAttributionListener: { attributionInfo in
            //Write the code for handling attribution flow
        }
        return true
    }
}

Objective-C

#import "AppDelegate.h"
#import "AppsOnAir_AppLink/AppsOnAir_AppLink-Swift.h"

@interface AppDelegate ()
@property (nonatomic, strong) AppLinkService *appLinkServices;
@end

@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
       
    // AppLink Class instance create
    self.appLinkServices = [AppLinkService shared];
    
    // Help to initialize link services
    [self.appLinkServices initializeOnDeepLinkProcessed:^(NSURL * url, NSDictionary<NSString *,id> * linkInfo){
          //Write the code for handling flow based on url
    } onReferralLinkDetected:nil
        onAttributionListener:^(NSDictionary<NSString *,id> * attributionInfo) {
       //Write the code for handling attribution flow
    }];
    // Override point for customization after application launch.
    return YES;
}

Objective-C++

#import "AppDelegate.h"
#import "AppsOnAir-AppLink/AppLinkService.h"

@interface AppDelegate ()
@property (nonatomic, strong)  AppLinkService *appLinkServices;
@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  self.appLinkServices = [AppLinkService shared];

  [self.appLinkServices initializeOnDeepLinkProcessed:^(NSURL * _Nullable url, NSDictionary * _Nonnull linkInfo) {
      //Write the code for handling flow based on url
  } onReferralLinkDetected:nil
      onAttributionListener:^(NSDictionary * _Nonnull attributionInfo) {
      //Write the code for handling attribution flow
  }];
  
  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

initialize takes a single signature, with both listeners optional:

initialize(
    onDeepLinkProcessed: (URL?, [String: Any]) -> Void,
    onReferralLinkDetected: (([String: Any]) -> Void)? = nil,
    onAttributionListener: (([String: Any]) -> Void)? = nil
)

2. Creating the AppLink

You can also create link, such as from a button action:

Firstly, import AppsOnAir_AppLink in your ViewController file or swift code file

Swift / SwiftUI

import AppsOnAir_AppLink

Objective-C

#import "AppsOnAir_AppLink/AppsOnAir_AppLink-Swift.h"

Objective-C++

#import "AppsOnAir-AppLink/AppLinkService.h"

appsFlyer Parameters

(Optional) Pass this dictionary to createAppLink to attach AppsFlyer attribution data to the generated link.

Key Type Required Description
channel String Optional The media source / channel driving traffic to this link (e.g. "appsonair").
campaignId String Optional Unique identifier for the marketing campaign.
campaign String Optional Human-readable name of the marketing campaign.
subs [String] Optional Sub-parameters for granular tracking (e.g. ["sub1", "sub2", "sub3", "sub4", "sub5"]).
metaTitle String Optional Title used for attribution metadata.
metaDescription String Optional Description used for attribution metadata.

attributionTtl Parameter

(Optional) Int β€” time-to-live, in seconds, for attribution of the generated link (e.g. 60 for 60 seconds).

App-Link Implement Code

Swift UI

import SwiftUI
import AppsOnAir_AppLink

struct ContentView: View {
    @State private var showToast = false
    @State private var message = ""

    var body: some View {
        VStack(spacing: 20) {
            Button(action: {
                // Help to create the link

                AppLinkService.shared.createAppLink(
                    url: "https://appsonair.com",
                    name: "AppsOnAir",
                    urlPrefix: "YOUR_DOMAIN_NAME", //  <urlPrefix> shouldn't contain http or https
                    shortId: "LINK_ID",   // <shortId>  If not set, it will be auto-generated
                    socialMeta: ["title": "link title","description": "link description","imageUrl": "https://image.png"],
                    isOpenInBrowserApple: false,
                    isOpenInIosApp: true,
                    iosFallbackUrl: "https://appstore.com",
                    appsFlyer: [ // Optional: AppsFlyer attribution params
                        "channel": "appsonair",
                        "campaignId": "01",
                        "campaign": "test",
                        "subs": ["sub1", "sub2", "sub3", "sub4", "sub5"],
                        "metaTitle": "metaTitle",
                        "metaDescription": "metaDescription"
                    ],
                    attributionTtl: 60 // Optional: TTL (in seconds) for attribution
                ) { linkInfo in
                     //Write the code for handling create link
                }
            }) {
                Text("Create Link")
                    .padding()
                    .frame(maxWidth: .infinity)
                    .background(Color.green)
                    .foregroundColor(.white)
                    .cornerRadius(10)
            }
        }
        .padding()
        .toast(isPresented: $showToast, message: message)
        .onOpenURL { url in
            AppLinkService.shared.handleAppLink(incomingURL: url)
        }
    }
}

Swift

class ViewController: UIViewController {
  
    override func viewDidLoad() {
        super.viewDidLoad()
       
            
        let button = UIButton(type: .system)
                button.setTitle("Button", for: .normal)
                button.backgroundColor = .systemBlue
                button.setTitleColor(.white, for: .normal)
                button.layer.cornerRadius = 10
                
                // Set button frame (size and position)
                button.frame = CGRect(x: 100, y: 200, width: 150, height: 50)
                
                // Add target for onPressed (TouchUpInside)
                button.addTarget(self, action: #selector(buttonPressed), for: .touchUpInside)
                
                // Add the button to the view
                self.view.addSubview(button)
          }
    
          // Define the action when button is pressed
           @objc func buttonPressed() {
               // Help to create the link
               // <urlPrefix> shouldn't contain http or https
               // <shortId>  If not set, it will be auto-generated
               AppLinkService.shared.createAppLink(url: "https://appsonair.com",name: "AppsOnAir",urlPrefix: "YOUR_DOMAIN_NAME",shortId: "LINK_ID",socialMeta: ["title": "link title","description":  "link description","imageUrl": "https://image.png"],isOpenInBrowserApple: false,isOpenInIosApp: true,iosFallbackUrl: "https://appstore.com",appsFlyer: ["channel": "appsonair","campaignId": "01","campaign": "test","subs": ["sub1", "sub2", "sub3", "sub4", "sub5"],"metaTitle": "metaTitle","metaDescription": "metaDescription"],attributionTtl: 60
        ) { linkInfo  in
                    //Write the code for handling create link
                }
           }


    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}

Objective-C

#import "ViewController.h"
#import "AppsOnAir_AppLink/AppsOnAir_AppLink-Swift.h"


@interface ViewController ()
@property (nonatomic, strong) AppLinkService *appLinkService;
@end


@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.appLinkService = [AppLinkService shared];
    // Create a UIButton programmatically
       UIButton *ctaButton = [UIButton buttonWithType:UIButtonTypeSystem];
       
       // Set button title
       [ctaButton setTitle:@"Create Link" forState:UIControlStateNormal];
       
       // Set button frame (position and size)
       ctaButton.frame = CGRectMake(100, 200, 200, 50);
       
       // Add target-action for button tap
       [ctaButton addTarget:self action:@selector(openNextScreen) forControlEvents:UIControlEventTouchUpInside];
       
       // Add button to the view
       [self.view addSubview:ctaButton];
}
- (void)openNextScreen {
     // Help to create link
     // <urlPrefix> shouldn't contain http or https
     // <shortId>  If not set, it will be auto-generated
    [self.appLinkService createAppLinkWithUrl:@"https://appsonair.com" name:@"AppsOnAir" urlPrefix:@"YOUR_DOMAIN_NAME" shortId: @"LINK_ID"socialMeta:@{@"title":@"link title",@"description":@"link description",@"imageUrl":@"https://image.png"}isOpenInBrowserApple:@0 isOpenInIosApp:@1 iosFallbackUrl:@"https://appstore.com" isOpenInAndroidApp:@1 isOpenInBrowserAndroid:@0 androidFallbackUrl:@"https://play.google.com"appsFlyer:@{@"channel":@"appsonair",@"campaignId":@"01",@"campaign":@"test",@"subs":@[@"sub1",@"sub2",@"sub3",@"sub4",@"sub5"],@"metaTitle":@"metaTitle",@"metaDescription":@"metaDescription"} attributionTtl:@60 completion:^(NSDictionary<NSString *,id> * linkInfo) {
        //Write the code for handling create link
    }];
}

Objective-C++

#import "AppsOnAir-AppLink/AppLinkService.h"

@interface AppDelegate ()
@property (nonatomic, strong)  AppLinkService *appLinkServices;
@end

@implementation AppDelegate

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

  self.appLinkServices = [AppLinkService shared];

  [self.appLinkServices createAppLinkWithUrl:@"https://appsonair.com" name:@"AppsOnAir" urlPrefix:@"YOUR_DOMAIN_NAME" shortId: @"LINK_ID" socialMeta:@{@"title":@"link title",@"description":@"link description",@"imageUrl":@"https://image.png"}isOpenInBrowserApple:@0 isOpenInIosApp:@1 iosFallbackUrl:@"https://appstore.com" isOpenInAndroidApp:@1 isOpenInBrowserAndroid:@0 androidFallbackUrl:@"https://play.google.com" appsFlyer:@{@"channel":@"appsonair",@"campaignId":@"01",@"campaign":@"test",@"subs":@[@"sub1",@"sub2",@"sub3",@"sub4",@"sub5"],@"metaTitle":@"metaTitle",@"metaDescription":@"metaDescription"} attributionTtl:@60 completion:^(NSDictionary<NSString*,id> * linkInfo) {
    //Write the code for handling create link
    }];
  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

3. Retrieving the attribution info

You can also retrieve the attribution info on demand, such as from a button action:

Firstly, import AppsOnAir_AppLink in your ViewController file or swift code file

Swift / SwiftUI

import AppsOnAir_AppLink

Objective-C

#import "AppsOnAir_AppLink/AppsOnAir_AppLink-Swift.h"

Objective-C++

#import "AppsOnAir-AppLink/AppLinkService.h"

App-Link Implement Code

Swift UI

import SwiftUI
import AppsOnAir_AppLink

struct ContentView: View {
    @State private var showToast = false
    @State private var message = ""

    var body: some View {
        VStack(spacing: 20) {
            Button(action: {
                AppLinkService.shared.getAttributionInfo { attributionInfo in
                   //Write the code for handling attribution flow
                }
            }) {

                Text("Fetch Attribution Info")
                    .padding()
                    .frame(maxWidth: .infinity)
                    .background(Color.green)
                    .foregroundColor(.white)
                    .cornerRadius(10)
            }
        }
        .padding()
        .toast(isPresented: $showToast, message: message)
        .onOpenURL { url in
            AppLinkService.shared.handleAppLink(incomingURL: url)
        }
    }
}

Swift

class ViewController: UIViewController {
  
    override func viewDidLoad() {
        super.viewDidLoad()
       
            
        let button = UIButton(type: .system)
                button.setTitle("Button", for: .normal)
                button.backgroundColor = .systemBlue
                button.setTitleColor(.white, for: .normal)
                button.layer.cornerRadius = 10
                
                // Set button frame (size and position)
                button.frame = CGRect(x: 100, y: 200, width: 150, height: 50)
                
                // Add target for onPressed (TouchUpInside)
                button.addTarget(self, action: #selector(buttonPressed), for: .touchUpInside)
                
                // Add the button to the view
                self.view.addSubview(button)
          }
    
          // Define the action when button is pressed
           @objc func buttonPressed() {
                // Help to retrieving the attribution info
                AppLinkService.shared.getAttributionInfo { attributionInfo in
                   //Write the code for handling attribution info
                }
           }


    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}

Objective-C

#import "ViewController.h"
#import "AppsOnAir_AppLink/AppsOnAir_AppLink-Swift.h"


@interface ViewController ()
@property (nonatomic, strong) AppLinkService *appLinkService;
@end


@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.appLinkService = [AppLinkService shared];
    // Create a UIButton programmatically
       UIButton *ctaButton = [UIButton buttonWithType:UIButtonTypeSystem];
       
       // Set button title
       [ctaButton setTitle:@"Fetch Attribution Info" forState:UIControlStateNormal];
       
       // Set button frame (position and size)
       ctaButton.frame = CGRectMake(100, 200, 200, 50);
       
       // Add target-action for button tap
       [ctaButton addTarget:self action:@selector(openNextScreen) forControlEvents:UIControlEventTouchUpInside];
       
       // Add button to the view
       [self.view addSubview:ctaButton];
}
- (void)openNextScreen {
    // Help to retrieving the attribution info
    [self.appLinkService getAttributionInfoWithCompletion:^(NSDictionary<NSString *,id> * attributionInfo) {
         //Write the code for handling attribution info
    }];
}

Objective-C++

#import "AppsOnAir-AppLink/AppLinkService.h"

@interface AppDelegate ()
@property (nonatomic, strong)  AppLinkService *appLinkServices;
@end
@implementation AppDelegate

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

  self.appLinkServices = [AppLinkService shared];

  [self.appLinkServices getAttributionInfoWithCompletion:^(NSDictionary * _Nonnull attributionInfo) {
      //Write the code for handling attribution info
  }];

  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

Along with the referral details, getAttributionInfo() and onAttributionListener() add the following keys inside the data object of the response:

Response Key Type Description
isFirstLaunch Bool true only during the very first app launch after installation.
firstInstallTime Int64 Timestamp (epoch milliseconds) of the app's first installation.
isConsumed Bool true once a referral fetch has returned successfully for this install. Persisted.
attributionStatus String non-organic when the install happened within attributionTtl of the click, otherwise organic.
applink_click_time Int64 Timestamp (epoch milliseconds) of the click.

Deprecated APIs

The following APIs are deprecated and will be removed in a future release. Existing integrations keep working, but should migrate:

Deprecated Use instead
onReferralLinkDetected() onAttributionListener()
getReferralInfo() getAttributionInfo()
getReferralDetails() getAttributionInfo()

The deprecated getters carry the referral payload only. None of appsFlyer, isFirstLaunch, firstInstallTime, isConsumed, attributionStatus or applink_click_time appear in them β€” those belong to getAttributionInfo() and onAttributionListener(). attributionTtl expiry still applies to all three getters.

onReferralLinkDetected is still a parameter of initialize, so it no longer raises a deprecation warning at the call site the way the removed overload did. It remains detection-only: it fires when a referral fetch actually runs β€” first open, or no referral cached yet β€” and is not re-delivered on the foreground return that follows isFirstLaunch turning false.

Troubleshooting

Swift Implementation

If your app isn’t handling Universal or Deep Links as expected, make sure the relevant methods are correctly implemented in both AppDelegate and SceneDelegate.

AppDelegate.swift

class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    let appLinkService = AppLinkService.shared
  
    func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
        guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
              let url = userActivity.webpageURL else {
            return false
        }
        AppLinkService.shared.handleAppLink(incomingURL: url)
        return true
    }

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

SceneDelegate.swift

import AppsOnAir_AppLink

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

    func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
        guard let urlContext = URLContexts.first else { return }
        let url = urlContext.url
        AppLinkService.shared.handleAppLink(incomingURL: url)
    }
    func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
        guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
              let incomingURL = userActivity.webpageURL else {
            return
        }
        AppLinkService.shared.handleAppLink(incomingURL: incomingURL)
    }
}

Objective-C Implementation

AppDelegate.m

#import "AppDelegate.h"
#import "AppsOnAir_AppLink/AppsOnAir_AppLink-Swift.h"

@interface AppDelegate ()
@property (nonatomic, strong) AppLinkService *appLinkServices;
@end

@implementation AppDelegate

- (BOOL)application:(UIApplication * )application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    self.appLinkServices = [AppLinkService shared];
    return YES;
}

- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
            options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options {
    
    [self.appLinkServices handleAppLinkWithIncomingURL:url];
    
    return YES;
}

- (BOOL)application:(UIApplication *)application
continueUserActivity:(NSUserActivity *)userActivity
 restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler {

    if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) {
        NSURL *url = userActivity.webpageURL;
        [self.appLinkServices handleAppLinkWithIncomingURL:url];
    }
    return NO;
}

@end

SceneDelegate.m

#import "SceneDelegate.h"
#import "AppsOnAir_AppLink/AppsOnAir_AppLink-Swift.h"
#import "ViewController.h"

@interface SceneDelegate ()
@property (nonatomic, strong) AppLinkService *appLinkServices;
@end

@implementation SceneDelegate

- (void)scene:(UIScene *)scene
willConnectToSession:(UISceneSession *)session
     options:(UISceneConnectionOptions *)connectionOptions {
    
    // Handle URLs when app is cold started
    if (connectionOptions.URLContexts.count > 0) {
        UIOpenURLContext *urlContext = connectionOptions.URLContexts.allObjects.firstObject;
        NSURL *url = urlContext.URL;
        if (url) {
            [self.appLinkServices handleAppLinkWithIncomingURL:url];
        }
    }

    // Handle Universal Link via user activity when app is cold started
    if (connectionOptions.userActivities.count > 0) {
        NSUserActivity *userActivity = connectionOptions.userActivities.allObjects.firstObject;
        if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) {
            NSURL *url = userActivity.webpageURL;
            if (url) {
                [self.appLinkServices handleAppLinkWithIncomingURL:url];
            }
        }
    }
    self.appLinkServices = [AppLinkService shared];
    UIWindowScene *windowScene = (UIWindowScene *)scene;
    self.window = [[UIWindow alloc] initWithWindowScene:windowScene];
    
    // Set root view controller
    self.window.rootViewController = [[ViewController alloc] init];
    [self.window makeKeyAndVisible];
}

- (void)scene:(UIScene *)scene continueUserActivity:(NSUserActivity *)userActivity {
    if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) {
        NSURL *incomingURL = userActivity.webpageURL;
        if (incomingURL) {
            [self.appLinkServices handleAppLinkWithIncomingURL:incomingURL];
        }
    }
}
- (void)scene:(UIScene *)scene openURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts {
    UIOpenURLContext *urlContext = [URLContexts anyObject];
    if (urlContext) {
        NSURL *url = urlContext.URL;
        [self.appLinkServices handleAppLinkWithIncomingURL:url];
    }
}
@end

Objective-C++ Implementation

#import "AppsOnAir-AppLink/AppLinkService.h"

@interface AppDelegate ()
@property (nonatomic, strong)  AppLinkService *appLinkServices;
@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  
  self.appLinkServices = [AppLinkService shared];
  
  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
            options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options {

  [self.appLinkServices handleAppLinkWithIncomingURL:url];
  
    return YES;
}

- (BOOL)application:(UIApplication *)application
continueUserActivity:(NSUserActivity *)userActivity
 restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler {

    if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) {
        NSURL *url = userActivity.webpageURL;
        [self.appLinkServices handleAppLinkWithIncomingURL:url];
    }
    return NO;
}

Note:

For testing purposes:

  • Click the referral link, it should redirect you to the App Store.

  • To retrieve the latest referral data, you must uninstall the app, then reinstall it, and fetch the referral again.

Author

devtools-logicwind, devtools@logicwind.com

License

AppsOnAir-AppLink is available under the MIT license. See the LICENSE file for more info.

Documentation

For more detail refer this documentation.

Description

  • Swift Tools 5.9.0
View More Packages from this Author

Dependencies

Last updated: Mon Sep 14 2026 09:45:38 GMT-0900 (Hawaii-Aleutian Daylight Time)