iOS 통합 딥링킹
요약: 통합 딥링킹(UDL: Unified Deep Linking)을 사용하면 앱을 열자마자 앱의 특정 인앱 액티비티(예: 앱의 특정 페이지)에 새 사용자 및 기존 사용자를 보낼 수 있습니다.
UDL 프라이버시 보호
For new users, the UDL method only returns parameters relevant to deferred deep linking:
deep_link_value
anddeep_link_sub1-10
. If you try to get any other parameters (media_source
,campaign
,af_sub1-5
, 등), null 값을 반환합니다.
순서
순서는 다음과 같이 작동합니다.
- 사용자가 원링크 링크를 클릭합니다.
- 사용자가 앱을 설치한 경우, 유니버설 링크나 URI 스킴이 앱을 엽니다.
- 사용자가 앱을 설치하지 않은 경우, 앱 스토어로 리디렉션되고, 다운로드 후에는 사용자가 앱을 엽니다.
- 열린 앱이 앱스플라이어 SDK를 트리거합니다.
- AppsFlyer SDK는 UDL API를 실행합니다.
- UDL API는 AppsFlyer 서버에서 원링크 데이터를 가져옵니다.
- The UDL API calls back the
didResolveDeepLink()
in theDeepLinkDelegate
. - The
didResolveDeepLink()
method gets aDeepLinkResult
object. - The
DeepLinkResult
object includes:- 상태(찾음/찾을 수 없음/오류)
- A
DeepLink
object that carries thedeep_link_value
anddeep_link_sub1-10
parameters that the developer uses to route the user to a specific in-app activity, which is the main goal of OneLink.
계획
- UDL에는 AppsFlyer 안드로이드 SDK V6.1 이상이 필요합니다.
원링크를 설정할 때, 마케터는 파라미터를 사용하여 링크를 생성하고, 개발자는 수신된 값을 기반으로 앱의 작동을 맞춤 설정합니다. 앱에서 파라미터를 올바르게 처리하고 인앱 라우팅 및 링크에서 데이터를 맞춤 설정하는 것은 개발자의 책임입니다.
원링크를 계획하는 방법:
- URL을 클릭할 때 사용자에게 바람직한 동작과 개인적 경험을 마케터로부터 얻습니다.
- Based on the desired behavior, plan the
deep_link_value
and other parameters that are needed to give the user the desired personal experience.- The
deep_link_value
is set by the marketer in the URL and used by the developer to redirect the user to a specific place inside the app. For example, if you have a fruit store and want to direct users to apples, the value ofdeep_link_value
can beapples
. - The
deep_link_sub1-10
parameters can also be added to the URL to help personalize the user experience. For example, to give a 10% discount, the value ofdeep_link_sub1
can be10
.
- The
구현하기
Let's save you some time >>
Set Deep Linking with our SDK integration wizard
선택한 파라미터 및 값을 기반으로 UDL API 로직을 구현합니다.
- Assign the
AppDelegate
usingself
toAppsFlyerLib.shared().deepLinkDelegate
. - 다음을 허용하는 애플리케이션 기능을 구현합니다:
- 다음으로 유니버설 링크 지원
continue
. - 다음을 통한 URI 스키마 지원
handleOpen
.
- 다음으로 유니버설 링크 지원
- Create
DeepLinkDelegate
as an extension ofAppDelegate
. - Add
application
functions to support Universal Links and URI schemes. - In
DeepLinkDelegate
, make sure you override the callback function,didResolveDeepLink()
.
didResolveDeepLink()
accepts aDeepLinkResult
object as an argument. - Use
DeepLinkResult.status
to query whether the deep linking match is found. - For when the status is an error, call
DeepLinkResult.error
and run your error flow. - For when the status is found, use
DeepLinkResult.deepLink
to retrieve theDeepLink
object.
TheDeepLink
object contains the deep linking information arranged in public variables to retrieve the values from well-known OneLink keys, for example,DeepLink.deeplinkValue
fordeep_link_value
. - Use
deepLinkObj.clickEvent["deep_link_sub1"]
to retrievedeep_link_sub1
. Do the same fordeep_link_sub2-10
parameters, changing the string value as required. - Once
deep_link_value
anddeep_link_sub1-10
are retrieved, pass them to an in-app router and use them to personalize the user experience.
Supporting legacy OneLink links
레거시 OneLink 링크는 통합 딥링킹에 권장되는 파라미터를 포함하지 않는 링크입니다. deep_link_value
and deep_link_sub1-10
.
일반적으로 이러한 링크는 레거시 메소드에서 UDL로 마이그레이션할 때 필드에 이미 존재합니다.
레거시 링크를 사용하는 신규 사용자는 onConversionDataSuccess
확장된 디퍼드 딥링킹의 맥락에서.
UDL은 기존 사용자에 대한 딥링킹을 처리합니다. 레거시 파라미터에 대한 UDL 콜백 지원을 didResolveDeepLink
추가하는 것이 좋습니다.
Swift 코드 예시
Code example
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Replace 'appleAppID' and 'appsFlyerDevKey' with your Apple App ID (eg 69999999, without id prefix) and DevKey
// The App ID and the DevKey must be set prior to the calling of the deepLinkDelegate
AppsFlyerLib.shared().appleAppID = appleAppID
AppsFlyerLib.shared().appsFlyerDevKey = appsFlyerDevKey
...
AppsFlyerLib.shared().deepLinkDelegate = self
...
}
// For Swift version < 4.2 replace function signature with the commented out code
// func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void) -> Bool { // this line for Swift < 4.2
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
AppsFlyerLib.shared().continue(userActivity, restorationHandler: nil)
return true
}
// Open URI-scheme for iOS 9 and above
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
AppsFlyerLib.shared().handleOpen(url, options: options)
return true
}
extension AppDelegate: DeepLinkDelegate {
func didResolveDeepLink(_ result: DeepLinkResult) {
var fruitNameStr: String?
switch result.status {
case .notFound:
NSLog("[AFSDK] Deep link not found")
return
case .failure:
print("Error %@", result.error!)
return
case .found:
NSLog("[AFSDK] Deep link found")
}
guard let deepLinkObj:DeepLink = result.deepLink else {
NSLog("[AFSDK] Could not extract deep link object")
return
}
if deepLinkObj.clickEvent.keys.contains("deep_link_sub2") {
let ReferrerId:String = deepLinkObj.clickEvent["deep_link_sub2"] as! String
NSLog("[AFSDK] AppsFlyer: Referrer ID: \(ReferrerId)")
} else {
NSLog("[AFSDK] Could not extract referrerId")
}
let deepLinkStr:String = deepLinkObj.toString()
NSLog("[AFSDK] DeepLink data is: \(deepLinkStr)")
if( deepLinkObj.isDeferred == true) {
NSLog("[AFSDK] This is a deferred deep link")
}
else {
NSLog("[AFSDK] This is a direct deep link")
}
fruitNameStr = deepLinkObj.deeplinkValue
walkToSceneWithParams(fruitName: fruitNameStr!, deepLinkData: deepLinkObj.clickEvent)
}
}
// User logic
fileprivate func walkToSceneWithParams(deepLinkObj: DeepLink) {
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
UIApplication.shared.windows.first?.rootViewController?.dismiss(animated: true, completion: nil)
guard let fruitNameStr = deepLinkObj.clickEvent["deep_link_value"] as? String else {
print("Could not extract query params from link")
return
}
let destVC = fruitNameStr + "_vc"
if let newVC = storyBoard.instantiateVC(withIdentifier: destVC) {
print("AppsFlyer routing to section: \(destVC)")
newVC.deepLinkData = deepLinkObj
UIApplication.shared.windows.first?.rootViewController?.present(newVC, animated: true, completion: nil)
} else {
print("AppsFlyer: could not find section: \(destVC)")
}
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Set isDebug to true to see AppsFlyer debug logs
[AppsFlyerLib shared].isDebug = YES;
// Replace 'appsFlyerDevKey', `appleAppID` with your DevKey, Apple App ID
[AppsFlyerLib shared].appsFlyerDevKey = appsFlyerDevKey;
[AppsFlyerLib shared].appleAppID = appleAppID;
[AppsFlyerLib shared].deepLinkDelegate = self;
return YES;
}
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler {
[[AppsFlyerLib shared] continueUserActivity:userActivity restorationHandler:nil];
return YES;
}
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
[[AppsFlyerLib shared] handleOpenUrl:url options:options];
return YES;
}
#pragma mark - DeepLinkDelegate
- (void)didResolveDeepLink:(AppsFlyerDeepLinkResult *)result {
NSString *fruitNameStr;
NSLog(@"[AFSDK] Deep link lowkehy");
switch (result.status) {
case AFSDKDeepLinkResultStatusNotFound:
NSLog(@"[AFSDK] Deep link not found");
return;
case AFSDKDeepLinkResultStatusFailure:
NSLog(@"Error %@", result.error);
return;
case AFSDKDeepLinkResultStatusFound:
NSLog(@"[AFSDK] Deep link found");
break;
}
AppsFlyerDeepLink *deepLinkObj = result.deepLink;
if ([deepLinkObj.clickEvent.allKeys containsObject:@"deep_link_sub2"]) {
NSString *referrerId = deepLinkObj.clickEvent[@"deep_link_sub2"];
NSLog(@"[AFSDK] AppsFlyer: Referrer ID: %@", referrerId);
} else {
NSLog(@"[AFSDK] Could not extract referrerId");
}
NSString *deepLinkStr = [deepLinkObj toString];
NSLog(@"[AFSDK] DeepLink data is: %@", deepLinkStr);
if (deepLinkObj.isDeferred) {
NSLog(@"[AFSDK] This is a deferred deep link");
if (self.deferredDeepLinkProcessedFlag) {
NSLog(@"Deferred deep link was already processed by GCD. This iteration can be skipped.");
self.deferredDeepLinkProcessedFlag = NO;
return;
}
} else {
NSLog(@"[AFSDK] This is a direct deep link");
}
fruitNameStr = deepLinkObj.deeplinkValue;
// If deep_link_value doesn't exist
if (!fruitNameStr || [fruitNameStr isEqualToString:@""]) {
// Check if fruit_name exists
id fruitNameValue = deepLinkObj.clickEvent[@"fruit_name"];
if ([fruitNameValue isKindOfClass:[NSString class]]) {
fruitNameStr = (NSString *)fruitNameValue;
} else {
NSLog(@"[AFSDK] Could not extract deep_link_value or fruit_name from deep link object with unified deep linking");
return;
}
}
// This marks to GCD that UDL already processed this deep link.
// It is marked to both DL and DDL, but GCD is relevant only for DDL
self.deferredDeepLinkProcessedFlag = YES;
[self walkToSceneWithParams:fruitNameStr deepLinkData:deepLinkObj.clickEvent];
}
- (void)walkToSceneWithParams:(NSString *)fruitName deepLinkData:(NSDictionary *)deepLinkData {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
[[UIApplication sharedApplication].windows.firstObject.rootViewController dismissViewControllerAnimated:YES completion:nil];
NSString *destVC = [fruitName stringByAppendingString:@"_vc"];
DLViewController *newVC = [storyboard instantiateViewControllerWithIdentifier:destVC];
NSLog(@"[AFSDK] AppsFlyer routing to section: %@", destVC);
newVC.deepLinkData = deepLinkData;
[[UIApplication sharedApplication].windows.firstObject.rootViewController presentViewController:newVC animated:YES completion:nil];
}
⇲ Github links: Swift
⇲ Github links: Objective-C
Deferred Deep Linking after network consent
In some cases the application might require consent from the user in order to connect to the network, in a dialog similar to this one:

In order to support deferred deep linking once the network consent is given we recommend:
- Implement eDDL to allow UDL to handle the deferred deep linking
디퍼드 딥링킹 테스트
Prerequisites
- 완전한 UDL 연동.
- 테스트 기기 등록.
- 앱에서 디버그 모드 활성화를 수행합니다.
- 앱이 기기에 설치되어 있지 않은지 확인합니다.
- 마케터에게 원링크 템플릿 요청
- 다음과 유사할 것입니다.
https://onelink-basic-app.onelink.me/H5hv
. - 이 예시에서는 원링크 하위 도메인과
onelink-basic-app.onelink.me
원링크 템플릿 ID를 사용합니다H5hv
.
- 다음과 유사할 것입니다.
The test link
기존 OneLink 링크를 사용하거나 마케터에게 테스트할 새 링크를 만들도록 요청할 수 있습니다. 짧은 원링크 URL과 긴 원링크 URL을 모두 사용할 수 있습니다.
기존 링크에 임시 파라미터 추가하기
- 도메인과 링크의 원링크 템플릿만 사용하십시오. 예시:
https://onelink-basic-app.onelink.me/H5hv
. - 애플리케이션에서 예상한 대로 원링크 파라미터
deep_link_value
anddeep_link_sub1-10
애플리케이션에서 예상한 대로. 파라미터는 쿼리 파라미터로 추가해야 합니다.- 예:
https://onelink-basic-app.onelink.me/H5hv?pid=my_media_source&deep_link_value=apples&deep_link_sub1=23
- 예:
Perform the test
- 기기에서 링크를 클릭합니다.
- 원링크는 링크 설정에 따라 사용자를 앱 스토어 또는 웹사이트로 리디렉션합니다.
- 애플리케이션을 인스톨합니다.
중요 정보
- 이 애플리케이션아직 개발 중이고 아직 스토어에 업로드되지 않은 경우 다음 이미지가 표시됩니다.
- Xcode에서 애플리케이션을 설치합니다.
- 이 애플리케이션아직 개발 중이고 아직 스토어에 업로드되지 않은 경우 다음 이미지가 표시됩니다.
- UDL은 디퍼드 딥링킹을 검색하고 인스톨을 클릭과 일치시키며 원링크 파라미터를
didResolveDeepLink
검색합니다.
Expected logs results
다음 로그는 오직 디버그 모드가 활성화된 경우에만 사용할 수 있습니다.
- SDK가 초기화되었습니다.
[AppsFlyerSDK] [com.apple.main-thread] AppsFlyer SDK version 6.6.0 started build
- UDL API가 시작됩니다.
D/AppsFlyer_6.9.0: [DDL] start
- UDL은 앱스플라이어에 쿼리를 보내 이 인스톨과 매치되는 항목을 쿼리합니다.
[AppsFlyerSDK] [com.appsflyer.serial] [DDL] URL: https://dlsdk.appsflyer.com/v1.0/ios/id1512793879?sdk_version=6.6&af_sig=efcecc2bc95a0862ceaa7b62fa8e98ae1e3e022XXXXXXXXXXXXXXXX
- UDL이 응답을 받고 호출
didResolveDeepLink
콜백status=FOUND
및 OneLink 링크 데이터:[AppsFlyerSDK] [com.appsflyer.serial] [DDL] Calling didResolveDeepLink with: {"af_sub4":"","click_http_referrer":"","af_sub1":"","click_event":{"af_sub4":"","click_http_referrer":"","af_sub1":"","af_sub3":"","deep_link_value":"peaches","campaign":"","match_type":"probabilistic","af_sub5":"","campaign_id":"","media_source":"","deep_link_sub1":"23","af_sub2":""},"af_sub3":"","deep_link_value":"peaches","campaign":"","match_type":"probabilistic","af_sub5":"","media_source":"","campaign_id":"","af_sub2":""}
딥링킹 테스트(유니버설 링크)
Prerequisites
- 완전한 UDL 연동.
- 테스트 기기 등록.
- 앱에서 디버그 모드 활성화를 수행합니다.
- 앱이 기기에 이미 설치되어 있는지 확인하십시오.
- 마케터에게 원링크 템플릿을 요청하십시오.
- 다음과 유사할 것입니다.
https://onelink-basic-app.onelink.me/H5hv
. - 이 예시에서는 원링크 하위 도메인과
onelink-basic-app.onelink.me
원링크 템플릿 ID를 사용합니다H5hv
- 다음과 유사할 것입니다.
- 유니버설 링크를 설정하십시오.
Create the test link
디퍼드 딥링킹과 동일한 방법을 사용합니다.
Perform the test
- 기기에서 링크를 클릭합니다.
- UDL은 유니버설 링크를 감지하고 다음에 대한 원링크 파라미터를 검색합니다
didResolveDeepLink
검색합니다.
Expected logs results
다음 로그는 오직 디버그 모드가 활성화된 경우에만 사용할 수 있습니다.
- 링크가 원링크 단축링크인 경우(예: https://onelink-basic-app.onelink.me/H5hv/apples):
[AppsFlyerSDK] [com.apple.main-thread] NSUserActivity `webpageURL`: https://onelink-basic-app.onelink.me/H5hv/apples [AppsFlyerSDK] [com.appsflyer.serial] UniversalLink/Deeplink found: https://onelink-basic-app.onelink.me/H5hv/apples [AppsFlyerSDK] [com.appsflyer.serial] Shortlink found. Executing: https://onelink.appsflyer.com/shortlink-sdk/v2/H5hv?id=apples ... [AppsFlyerSDK] [com.appsflyer.serial] [Shortlink] OneLink:{ c = test1; campaign = test1; "deep_link_sub1" = 23; "deep_link_value" = peaches; "is_retargeting" = true; "media_source" = SMS; pid = SMS; }
- UDL는 다음을 호출
didResolveDeepLink
콜백status=FOUND
및 OneLink 링크 데이터:[AppsFlyerSDK] [com.appsflyer.serial] [DDL] Calling didResolveDeepLink with: {"af_sub4":null,"click_http_referrer":null,"af_sub1":null,"click_event":{"campaign":"test1","deep_link_sub1":"23","deep_link_value":"peaches","media_source":"SMS"},"af_sub3":null,"deep_link_value":"peaches","campaign":"test1","match_type":null,"af_sub5":null,"media_source":"SMS","campaign_id":null,"af_sub2":null}
최신 데이터 30일 전