통합된 딥링킹(UDL)

요약: 통합 딥링킹(UDL: Unified Deep Linking)을 사용하면 앱을 열자마자 앱의 특정 인앱 액티비티(예: 앱의 특정 페이지)에 새 사용자 및 기존 사용자를 보낼 수 있습니다.

📘

UDL 프라이버시 보호

For new users, the UDL method only returns parameters relevant to deferred deep linking: deep_link_value and deep_link_sub1-10. If you try to get any other parameters (media_source, campaign, af_sub1-5, etc.), they return null.

순서

19201920

UDL은 모바일 사용자를 앱의 특정 액티비티나 콘텐츠로 라우팅합니다.

순서는 다음과 같이 작동합니다.

  1. 사용자가 원링크 링크를 클릭합니다.
    • 사용자가 앱을 설치한 경우, 안드로이드 앱 링크나 URI 스킴이 앱을 엽니다.
    • 사용자가 앱을 설치하지 않은 경우, 앱 스토어로 리디렉션되고, 다운로드 후에는 사용자가 앱을 엽니다.
  2. 열린 앱이 앱스플라이어 SDK를 트리거합니다.
  3. AppsFlyer SDK는 UDL API를 실행합니다.
  4. UDL API는 AppsFlyer 서버에서 원링크 데이터를 가져옵니다.
  5. The UDL API calls back the onDeepLinking() 개발자가 DeepLinkingListener class.
  6. The onDeepLinking() method gets a DeepLinkResult object.
  7. The DeepLinkResult object includes:
    • 상태(찾음/찾을 수 없음/오류)
    • A DeepLink object that carries the deep_link_value and deep_link_sub1-10 원링의 주요 목표인 특정 앱 내 활동으로 사용자를 라우트하는 데 사용하는 파라미터의 메서드입니다.

선행 조건

  • UDL에는 AppsFlyer 안드로이드 SDK V6.1 이상이 필요합니다.

계획

원링크를 설정할 때, 마케터는 파라미터를 사용하여 링크를 생성하고, 개발자는 수신된 값을 기반으로 앱의 작동을 맞춤 설정합니다. 앱에서 파라미터를 올바르게 처리하고 인앱 라우팅 및 링크에서 데이터를 맞춤 설정하는 것은 개발자의 책임입니다.

원링크를 계획하는 방법:

  1. URL을 클릭할 때 사용자에게 바람직한 동작과 개인적 경험을 마케터로부터 얻습니다.
  2. 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 of deep_link_value can be apples.
    • 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 of deep_link_sub1 can be 10.

구현하기

선택한 파라미터 및 값을 기반으로 UDL API 로직을 구현합니다.

  1. 메서드(from)를 subscribeForDeepLink() 사용하여 AppsFlyerLib인터페이스 리스너를 DeepLinkListener 등록합니다.
  2. 객체에 딥링크 정보와 도우미 함수가 onDeepLinking().
    onDeepLinking() 포함된 인수로 허용하는 DeepLinkResult object.
  3. Use getStatus() to query whether the deep linking match is found.
  4. For when the status is an error, call getError() and run your error flow.
  5. For when the status is found, use getDeepLink() to retrieve the DeepLink object.
    The DeepLink 콜백 함수를 재정의하여 잘 알려진 원링크 키(예: nginx)에서 값을 쉽게 검색할 수 있도록 getDeepLinkValue().
  6. Use getDeepLinkValue() to retrieve the deep_link_value.
  7. Use getStringValue("deep_link_sub1") to retrieve deep_link_sub1. Do the same for deep_link_sub2-10 parameters, changing the string value as required.
  8. Once deep_link_value and deep_link_sub1-10 are retrieved, pass them to an in-app router and use them to personalize the user experience.

📘

참고

onDeepLinking 앱이 백그라운드에서 실행 중이고 애플리케이션 LaunchMode가 표준이 아니면 호출되지 않습니다.

이를 고치려면, 애플리케이션이 비표준 LaunchMode를 사용하는 경우, 대체된 메서드에서 인텐트 값을 설정하기 위해 setIntent(intent)  메서드를 호출합니다.

import android.content.Intent;
...
...
...
@Override
protected void onNewIntent(Intent intent) 
{ 
  super.onNewIntent(intent);     
  setIntent(intent);
}

Code example

appsflyer.subscribeForDeepLink(new DeepLinkListener(){
            @Override
            public void onDeepLinking(@NonNull DeepLinkResult deepLinkResult) {
                DeepLinkResult.Status dlStatus = deepLinkResult.getStatus();
                if (dlStatus == DeepLinkResult.Status.FOUND) {
                    Log.d(LOG_TAG, "Deep link found");
                } else if (dlStatus == DeepLinkResult.Status.NOT_FOUND) {
                    Log.d(LOG_TAG, "Deep link not found");
                    return;
                } else {
                    // dlStatus == DeepLinkResult.Status.ERROR
                    DeepLinkResult.Error dlError = deepLinkResult.getError();
                    Log.d(LOG_TAG, "There was an error getting Deep Link data: " + dlError.toString());
                    return;
                }
                DeepLink deepLinkObj = deepLinkResult.getDeepLink();
                try {
                    Log.d(LOG_TAG, "The DeepLink data is: " + deepLinkObj.toString());
                } catch (Exception e) {
                    Log.d(LOG_TAG, "DeepLink data came back null");
                    return;
                }
                // An example for using is_deferred
                if (deepLinkObj.isDeferred()) {
                    Log.d(LOG_TAG, "This is a deferred deep link");
                } else {
                    Log.d(LOG_TAG, "This is a direct deep link");
                }
                
                // ** Next if statement is optional **
                // Our sample app's user-invite carries the referrerID in deep_link_sub2
                // See the user-invite section in FruitActivity.java
                if (dlData.has("deep_link_sub2")){
                    referrerId = deepLinkObj.getStringValue("deep_link_sub2");
                    Log.d(LOG_TAG, "The referrerID is: " + referrerId);
                } else {
                    Log.d(LOG_TAG, "deep_link_sub2/Referrer ID not found");
                }
                // An example for using a generic getter
                String fruitName = "";
                try {
                    fruitName = deepLinkObj.getDeepLinkValue();
                    Log.d(LOG_TAG, "The DeepLink will route to: " + fruitName);
                } catch (Exception e) {
                    Log.d(LOG_TAG, "Custom param fruit_name was not found in DeepLink data");
                    return;
                }
                goToFruit(fruitName, deepLinkObj);
            }
        });
AppsFlyerLib.getInstance().subscribeForDeepLink(object : DeepLinkListener{
            override fun onDeepLinking(deepLinkResult: DeepLinkResult) {
                when (deepLinkResult.status) {
                    DeepLinkResult.Status.FOUND -> {
                        Log.d(
                            LOG_TAG,"Deep link found"
                        )
                    }
                    DeepLinkResult.Status.NOT_FOUND -> {
                        Log.d(
                            LOG_TAG,"Deep link not found"
                        )
                        return
                    }
                    else -> {
                        // dlStatus == DeepLinkResult.Status.ERROR
                        val dlError = deepLinkResult.error
                        Log.d(
                            LOG_TAG,"There was an error getting Deep Link data: $dlError"
                        )
                        return
                    }
                }
                var deepLinkObj: DeepLink = deepLinkResult.deepLink
                try {
                    Log.d(
                        LOG_TAG,"The DeepLink data is: $deepLinkObj"
                    )
                } catch (e: Exception) {
                    Log.d(
                        LOG_TAG,"DeepLink data came back null"
                    )
                    return
                }

                // An example for using is_deferred
                if (deepLinkObj.isDeferred == true) {
                    Log.d(LOG_TAG, "This is a deferred deep link");
                } else {
                    Log.d(LOG_TAG, "This is a direct deep link");
                }

                try {
                    val fruitName = deepLinkObj.deepLinkValue
                    Log.d(LOG_TAG, "The DeepLink will route to: $fruitName")
                } catch (e:Exception) {
                    Log.d(LOG_TAG, "There's been an error: $e");
                    return;
                }
            }
        })

⇲ Github 링크: Java