当已安装应用的用户点击 Adjust 链接时,直接深度链接可确保将用户直接转到应用内的特定内容。
设置
iOS 提供了多种接收直接深度链接的方法,具体取决于应用的实施方式。在这些方法中,您将使用下列其中一种方法将深度链接传递给 Adjust SDK:
处理并解析深度链接 (推荐)
使用processAndResolve(_:withCompletionHandler:)方法,该方法会执行以下操作:
- 记录深度链接点击的归因
- 将品牌化短链接解析为其等效的品牌化长链接
- 按原样透传所有其他链接
然后,应用可以通过解析已解析的链接并跳转至相应的界面来处理该链接。可以使用此方法处理所有深度链接,包括 Adjust 品牌化长链接、其他通用链接以及应用 Scheme 深度链接。
+ (void)processAndResolveDeeplink:(nonnull ADJDeeplink *)deeplink withCompletionHandler:(nonnull ADJResolvedDeeplinkBlock)completion;处理深度链接 (旧版)
如果您使用的不是短品牌化链接,那么 processDeeplink(_:) 方法就会记录来自深度链接点击的归因。
+ (void)processDeeplink:(ADJDeeplink *)deeplink;processAndResolve(_:withCompletionHandler:) 方法会取代该遗留方法。
实施
使用与应用结构相符的实施方式:
- 使用 AppDelegate 生命周期的 UIKit 应用
- 使用 SceneDelegate 生命周期的 UIKit 应用
- 使用 AppDelegate 生命周期的 SwiftUI 应用
- 使用 SceneDelegate 生命周期的 SwiftUI 应用
使用 AppDelegate 生命周期的 UIKit 应用
更新 AppDelegate 以实施 iOS 直接深度链接方法。
1// Receive universal link when app is installed2// and link opens app from "Not Running"3// or Background state.4func application(5 _ application: UIApplication,6 continue userActivity: NSUserActivity,7 restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void8) -> Bool {9 guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,10 let incomingLink = userActivity.webpageURL11 else { return true }12
13 print("[IncomingLink] application:continueUserActivity: url=\(incomingLink.absoluteString)")14
15 // Create deep link object16 guard let deeplink = ADJDeeplink(deeplink: incomingLink) else { return false }17
18 // Send deep link to Adjust's servers for attribution.19 // If short branded link, receive long link.20 // Otherwise, receive original link.21 Adjust.processAndResolve(deeplink) { resolvedLink in22 // Handle failure if resolvedLink is nil23 guard let resolvedLink = resolvedLink else { return }24
25 /*26 TODO: Handle the deep link and navigate to the appropriate screen.27
28 Possible resolvedLink formats:29
30 1. https://brandname.go.link/?adj_t=def456&31 adj_link=https%3A%2F%2Fexample.com%2Fsummer-clothes%3Fpromo%3Dbeach32 - Extract and decode the deep link from the 'adj_link' query parameter.33
34 2. https://brandname.go.link/summer-clothes?promo=beach&adj_t=def45635 - Extract the path and relevant query parameters directly from the URL.36 */37 }38
39 return true40}41
42// Receive app scheme deep link when app is installed43// and link opens app from "Not Running",44// Background, or Foreground state.45func application(46 _ application: UIApplication,47 open incomingLink: URL,48 options: [UIApplication.OpenURLOptionsKey: Any] = [:]49) -> Bool {50 print("[IncomingLink] application:openURL: url=\(incomingLink)")51
52 // Create deep link object53 guard let deeplink = ADJDeeplink(deeplink: incomingLink) else { return false }54
55 // Send deep link to Adjust's servers for attribution.56 // If short branded link, receive long link.57 // Otherwise, receive original link.58 Adjust.processAndResolve(deeplink) { resolvedLink in59 // Handle failure if resolvedLink is nil60 guard let resolvedLink = resolvedLink else { return }61
62 /*63 TODO: Handle the deep link and navigate to the appropriate screen.64
65 resolvedLink format:66
67 example://summer-clothes?promo=beach&adj_t=def45668 - Extract the path and relevant query parameters directly from the URL.69 */70 }71 return true72}1// Receive universal link when app is installed2// and link opens app from "Not Running"3// or Background state.4- (BOOL)application:(UIApplication *)application5 continueUserActivity:(NSUserActivity *)userActivity6 restorationHandler:7 (void (^)(NSArray<id<uiuseractivityrestoring>> *_Nullable))8 restorationHandler {9 // Check if it's a web browsing activity10 if (![userActivity.activityType11 isEqualToString:NSUserActivityTypeBrowsingWeb])12 return YES;13
14 // Check if there's a valid URL15 NSURL *incomingLink = userActivity.webpageURL;16 if (!incomingLink) return YES;17
18 NSLog(@"[IncomingLink] application:continueUserActivity: url=%@", incomingLink);19
20 // Create deep link object21 ADJDeeplink *deeplink = [[ADJDeeplink alloc] initWithDeeplink:incomingLink];22 if (!deeplink) return YES;23
24 // Send deep link to Adjust's servers for attribution.25 // If short branded link, receive long link.26 // Otherwise, receive original link.27 [Adjust processAndResolveDeeplink:deeplink28 withCompletionHandler:^(NSString *resolvedLink) {29 // Handle failure if resolvedLink is nil30 if (!resolvedLink) return;31
32 /*33 TODO: Handle the deep link and navigate to the appropriate screen.34
35 Possible resolvedLink formats:36
37 1. https://brandname.go.link/?adj_t=def456&38 adj_link=https%3A%2F%2Fexample.com%2Fsummer-clothes%3Fpromo%3Dbeach39 - Extract and decode the deep link from the 'adj_link' query parameter.40
41 2. https://brandname.go.link/summer-clothes?promo=beach&adj_t=def45642 - Extract the path and relevant query parameters directly from the URL.43 */44 }];45
46 return YES;47}48
49// Receive app scheme deep link when app is installed50// and link opens app from "Not Running",51// Background, or Foreground state.52- (BOOL)application:(UIApplication *)application53 openURL:(NSURL *)incomingLink54 options:55 (NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options {56 NSLog(@"[IncomingLink] application:openURL: url=%@", incomingLink);57
58 // Create deep link object59 ADJDeeplink *deeplink = [[ADJDeeplink alloc] initWithDeeplink:incomingLink];60 if (!deeplink) return YES;61
62 // Send deep link to Adjust's servers for attribution.63 // If short branded link, receive long link.64 // Otherwise, receive original link.65 [Adjust processAndResolveDeeplink:deeplink66 withCompletionHandler:^(NSString *resolvedLink) {67 // Handle failure if resolvedLink is nil68 if (!resolvedLink) return;69
70 /*71 TODO: Handle the deep link and navigate to the appropriate screen.72
73 resolvedLink format:74
75 example://summer-clothes?promo=beach&adj_t=def45676 - Extract the path and relevant query parameters directly from the URL.77 */78 }];79 return YES;80}使用 SceneDelegate 生命周期的 UIKit 应用
更新 SceneDelegate 以实施 iOS 直接深度链接方法。
1// Receive universal link or app scheme deep link when app is installed2// and link opens app from "Not Running" state.3func scene(4 _ scene: UIScene,5 willConnectTo session: UISceneSession,6 options connectionOptions: UIScene.ConnectionOptions7) {8 // Receive incoming universal link9 if let userActivity = connectionOptions.userActivities.first,10 userActivity.activityType == NSUserActivityTypeBrowsingWeb,11 let incomingLink = userActivity.webpageURL12 {13 print("[IncomingLink] scene:willConnectToSession:options: url=\(incomingLink.absoluteString)")14
15 // Create deep link object16 guard let deeplink = ADJDeeplink(deeplink: incomingLink) else { return }17
18 // Send deep link to Adjust's servers for attribution.19 // If short branded link, receive long link.20 // Otherwise, receive original link.21 Adjust.processAndResolve(deeplink) { resolvedLink in22 // Handle failure if resolvedLink is nil23 guard let resolvedLink = resolvedLink else { return }24
25 /*26 TODO: Handle the deep link and navigate to the appropriate screen.27
28 Possible resolvedLink formats:29
30 1. https://brandname.go.link/?adj_t=def456&31 adj_link=https%3A%2F%2Fexample.com%2Fsummer-clothes%3Fpromo%3Dbeach32 - Extract and decode the deep link from the 'adj_link' query parameter.33
34 2. https://brandname.go.link/summer-clothes?promo=beach&adj_t=def45635 - Extract the path and relevant query parameters directly from the URL.36 */37 }38 return39 }40
41 // Receive incoming app scheme deep link42 guard let incomingLink = connectionOptions.urlContexts.first?.url else { return }43
44 print("[IncomingLink] scene:willConnectToSession:options: url=\(incomingLink.absoluteString)")45
46 // Create deep link object47 guard let deeplink = ADJDeeplink(deeplink: incomingLink) else { return }48
49 // Send deep link to Adjust's servers for attribution.50 // If short branded link, receive long link.51 // Otherwise, receive original link.52 Adjust.processAndResolve(deeplink) { resolvedLink in53 // Handle failure if resolvedLink is nil54 guard let resolvedLink = resolvedLink else { return }55
56 /*57 TODO: Handle the deep link and navigate to the appropriate screen.58
59 resolvedLink format:60
61 example://summer-clothes?promo=beach&adj_t=def45662 - Extract the path and relevant query parameters directly from the URL.63 */64 }65}66
67// Receive universal link when app is installed68// and link opens app from Background state.69func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {70 guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,71 let incomingLink = userActivity.webpageURL72 else { return }73
74 print("[IncomingLink] scene:continueUserActivity: url=\(incomingLink.absoluteString)")75
76 // Create deep link object77 guard let deeplink = ADJDeeplink(deeplink: incomingLink) else { return }78
79 // Send deep link to Adjust's servers for attribution.80 // If short branded link, receive long link.81 // Otherwise, receive original link.82 Adjust.processAndResolve(deeplink) { resolvedLink in83 // Handle failure if resolvedLink is nil84 guard let resolvedLink = resolvedLink else { return }85
86 /*87 TODO: Handle the deep link and navigate to the appropriate screen.88
89 Possible resolvedLink formats:90
91 1. https://brandname.go.link/?adj_t=def456&92 adj_link=https%3A%2F%2Fexample.com%2Fsummer-clothes%3Fpromo%3Dbeach93 - Extract and decode the deep link from the 'adj_link' query parameter.94
95 2. https://brandname.go.link/summer-clothes?promo=beach&adj_t=def45696 - Extract the path and relevant query parameters directly from the URL.97 */98 }99}100
101// Receive app scheme deep link when app is installed102// and link opens app from Background103// or Foreground state.104func scene(105 _ scene: UIScene,106 openURLContexts URLContexts: Set<uiopenurlcontext>107) {108 guard let incomingLink = URLContexts.first?.url else { return }109
110 print("[IncomingLink] scene:openURLContexts: url=\(incomingLink.absoluteString)")111
112 // Create deep link object113 guard let deeplink = ADJDeeplink(deeplink: incomingLink) else { return }114
115 // Send deep link to Adjust's servers for attribution.116 // If short branded link, receive long link.117 // Otherwise, receive original link.118 Adjust.processAndResolve(deeplink) { resolvedLink in119 // Handle failure if resolvedLink is nil120 guard let resolvedLink = resolvedLink else { return }121
122 /*123 TODO: Handle the deep link and navigate to the appropriate screen.124
125 resolvedLink format:126
127 example://summer-clothes?promo=beach&adj_t=def456128 - Extract the path and relevant query parameters directly from the URL.129 */130 }131}1// Receive universal link or app scheme deep link when app is installed2// and link opens app from "Not Running" state.3- (void)scene:(UIScene *)scene4 willConnectToSession:(UISceneSession *)session5 options:(UISceneConnectionOptions *)connectionOptions {6 // Receive universal link7 if (connectionOptions.userActivities.count > 0) {8 NSUserActivity *userActivity =9 connectionOptions.userActivities.allObjects.firstObject;10 if ([userActivity.activityType11 isEqualToString:NSUserActivityTypeBrowsingWeb] &&12 userActivity.webpageURL) {13 NSURL *incomingLink = userActivity.webpageURL;14 NSLog(@"[IncomingLink] scene:willConnectToSession:options: url=%@", incomingLink);15
16 // Create deep link object17 ADJDeeplink *deeplink =18 [[ADJDeeplink alloc] initWithDeeplink:incomingLink];19 if (!deeplink) return;20
21 // Send deep link to Adjust's servers for attribution.22 // If short branded link, receive long link.23 // Otherwise, receive original link.24 [Adjust processAndResolveDeeplink:deeplink25 withCompletionHandler:^(NSString *resolvedLink) {26 // Handle failure if resolvedLink is nil27 if (!resolvedLink) return;28
29 /*30 TODO: Handle the deep link and navigate to the appropriate screen.31
32 Possible resolvedLink formats:33
34 1. https://brandname.go.link/?adj_t=def456&35 adj_link=https%3A%2F%2Fexample.com%2Fsummer-clothes%3Fpromo%3Dbeach36 - Extract and decode the deep link from the 'adj_link' query parameter.37
38 2. https://brandname.go.link/summer-clothes?promo=beach&adj_t=def45639 - Extract the path and relevant query parameters directly from the URL.40 */41 }];42 return;43 }44 }45
46 // Receive app scheme deep link47 if (connectionOptions.URLContexts.count == 0) return;48
49 UIOpenURLContext *urlContext =50 connectionOptions.URLContexts.allObjects.firstObject;51 NSURL *incomingLink = urlContext.URL;52 NSLog(@"[IncomingLink] scene:willConnectToSession:options: url=%@", incomingLink);53
54 // Create deep link object55 ADJDeeplink *deeplink = [[ADJDeeplink alloc] initWithDeeplink:incomingLink];56 if (!deeplink) return;57
58 // Send deep link to Adjust's servers for attribution.59 // If short branded link, receive long link.60 // Otherwise, receive original link.61 [Adjust processAndResolveDeeplink:deeplink62 withCompletionHandler:^(NSString *resolvedLink) {63 // Handle failure if resolvedLink is nil64 if (!resolvedLink) return;65
66 /*67 TODO: Handle the deep link and navigate to the appropriate screen.68
69 resolvedLink format:70
71 example://summer-clothes?promo=beach&adj_t=def45672 - Extract the path and relevant query parameters directly from the URL.73 */74 }];75}76
77// Receive universal link when app is installed78// and link opens app from Background state.79- (void)scene:(UIScene *)scene80 continueUserActivity:(NSUserActivity *)userActivity {81 // Check if it's a web browsing activity82 if (![userActivity.activityType83 isEqualToString:NSUserActivityTypeBrowsingWeb])84 return;85
86 // Check if there's a valid URL87 NSURL *incomingLink = userActivity.webpageURL;88 if (!incomingLink) return;89
90 NSLog(@"[IncomingLink] scene:continueUserActivity: url=%@", incomingLink);91
92 // Create deep link object93 ADJDeeplink *deeplink = [[ADJDeeplink alloc] initWithDeeplink:incomingLink];94 if (!deeplink) return;95
96 // Send deep link to Adjust's servers for attribution.97 // If short branded link, receive long link.98 // Otherwise, receive original link.99 [Adjust processAndResolveDeeplink:deeplink100 withCompletionHandler:^(NSString *resolvedLink) {101 // Handle failure if resolvedLink is nil102 if (!resolvedLink) return;103
104 /*105 TODO: Handle the deep link and navigate to the appropriate screen.106
107 Possible resolvedLink formats:108
109 1. https://brandname.go.link/?adj_t=def456&110 adj_link=https%3A%2F%2Fexample.com%2Fsummer-clothes%3Fpromo%3Dbeach111 - Extract and decode the deep link from the 'adj_link' query parameter.112
113 2. https://brandname.go.link/summer-clothes?promo=beach&adj_t=def456114 - Extract the path and relevant query parameters directly from the URL.115 */116 }];117}118
119// Receive app scheme deep link when app is installed120// and link opens app from Background121// or Foreground state.122- (void)scene:(UIScene *)scene123 openURLContexts:(NSSet<uiopenurlcontext *> *)URLContexts {124 // Check if we have any URL contexts125 UIOpenURLContext *urlContext = URLContexts.allObjects.firstObject;126 if (!urlContext) return;127
128 // Check if the URL is valid129 NSURL *incomingLink = urlContext.URL;130 if (!incomingLink) return;131
132 NSLog(@"[IncomingLink] scene:openURLContexts: url=%@", incomingLink);133
134 // Create deep link object135 ADJDeeplink *deeplink = [[ADJDeeplink alloc] initWithDeeplink:incomingLink];136 if (!deeplink) return;137
138 // Send deep link to Adjust's servers for attribution.139 // If short branded link, receive long link.140 // Otherwise, receive original link.141 [Adjust processAndResolveDeeplink:deeplink142 withCompletionHandler:^(NSString *resolvedLink) {143 // Handle failure if resolvedLink is nil144 if (!resolvedLink) return;145
146 /*147 TODO: Handle the deep link and navigate to the appropriate screen.148
149 resolvedLink format:150
151 example://summer-clothes?promo=beach&adj_t=def456152 - Extract the path and relevant query parameters directly from the URL.153 */154 }];155}使用 AppDelegate 生命周期的 SwiftUI 应用
如果尚未在项目的主目录中创建 AppDelegate.swift 文件,请立即执行此操作,并在主应用文件中加以引用,如以下 App.swift 示例文件所示。这是处理应用生命周期事件和 Adjust SDK 集成的必要步骤。此外,实施 onOpenURL SwiftUI 修饰符,该修饰符在应用安装时接收通用链接和应用 Scheme 深度链接。
1import AdjustSdk2import SwiftUI3
4@main5struct MyApp: App {6 @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate7
8 var body: some Scene {9 WindowGroup {10 ContentView()11 // Receive universal link or app scheme deep link when app is installed12 // and link opens app from "Not Running",13 // Background, or Foreground state.14 .onOpenURL { incomingLink in15 print("[IncomingLink] onOpenURL: url=\(incomingLink.absoluteString)")16
17 // Create deep link object18 guard let deeplink = ADJDeeplink(deeplink: incomingLink) else { return }19
20 // Send deep link to Adjust's servers for attribution.21 // If short branded link, receive long link.22 // Otherwise, receive original link.23 Adjust.processAndResolve(deeplink) { resolvedLink in24 // Handle failure if resolvedLink is nil25 guard let resolvedLink = resolvedLink else { return }26
27 /*28 TODO: Handle the deep link and navigate to the appropriate screen.29
30 Possible resolvedLink formats:31
32 1. https://brandname.go.link/?adj_t=def456&33 adj_link=https%3A%2F%2Fexample.com%2Fsummer-clothes%3Fpromo%3Dbeach34 - Extract and decode the deep link from the 'adj_link' query parameter.35
36 2. https://brandname.go.link/summer-clothes?promo=beach&adj_t=def45637 - Extract the path and relevant query parameters directly from the URL.38
39 3. example://summer-clothes?promo=beach&adj_t=def45640 - Extract the path and relevant query parameters directly from the URL.41 */42 }43 }44 }45 }46}使用 SceneDelegate 生命周期的 SwiftUI 应用
按照“使用 AppDelegate 生命周期的 SwiftUI 应用”栏中的说明进行操作。安装应用后,onOpenURL SwiftUI 修饰符会接收通用链接和应用 Scheme 深度链接,并且该链接会在后台或前台状态中打开相关应用。
此外,从“使用 SceneDelegate 生命周期的 UIKit 应用”栏实施scene(_:willConnectTo:options:)方法。此方法会在安装应用后接收通用链接和应用 Scheme 深度链接,并且该链接会在“未运行”状态中打开相关应用。
前台导航
如果您将 Adjust 深度链接放置在自己的应用中,例如促销横幅或产品推荐等,请不要对其调用 UIApplication.open(_:options:completionHandler:) 或 SwiftUI 的 openURL 。iOS 会在 Safari 中打开应用的通用链接,不会在应用内发送这些链接。请改为通过 processAndResolve 发送链接,然后使用与本页所述相同的处理路径,发送已解析的深度链接。