딥링킹 지원 추가
딥링크는사용자를 앱 내의 특정 콘텐츠로 연결합니다. 사용자가 앱이 설치된 기기에서 딥링크를 탭하면 앱이 제품 페이지나 특정 경험 등 의도한 콘텐츠로 바로 연결됩니다.
Singular 추적 링크는 표준 딥링킹(설치된 앱의 경우)과 디퍼드 딥링킹(신규 설치의 경우)을 모두 지원합니다. 자세한 내용은 딥링킹 FAQ및 Singular 링크 FAQ를 참조하세요.
요구 사항
전제 조건
iOS 및 Android 플랫폼에서 딥링킹을 사용하려면 Singular 링크 사전 요구 사항을완료하세요.
참고:
- 이 가이드에서는 2019년에 출시된 Singular의 추적 링크 기술인 Singular 링크를사용하고 있다고 가정합니다. 이전 고객은 레거시 트래킹 링크를 사용하고 있을 수 있습니다.
- 앱의 딥링크 대상은 Singular의 앱 페이지에서 구성해야 합니다( 딥링크 URL 구성하기 참조).
SDK 구성
Singular 링크 핸들러 구현
Singular SDK는 앱이 열릴 때 Singular 추적 링크에서 딥링크, 디퍼드 딥링크 및 패스스루 파라미터를 검색하는 델리게이트 기반 핸들러 메커니즘을 제공합니다.
사용 가능한 파라미터
- 딥링크: 링크를 클릭하는 사용자의 앱 내 대상 URL(링크 관리 페이지에서 구성)입니다.
- 패스스루: 추가 컨텍스트 또는 캠페인 메타데이터를 위해 추적 링크를 통해 전달되는 사용자 지정 데이터입니다.
- IsDeferred: 링크가 디퍼드 딥링크인지 여부를 나타냅니다(신규 인스톨의 경우 참, 기존 인스톨의 경우 거짓).
앱에 딥링크 핸들러 추가
앱이 실행될 때 수신되는 딥링크 데이터를 처리하도록 딥링크 핸들러를 구성합니다. 이 작업은 Singular SDK를 초기화하기 전에 수행해야 합니다.
구현 단계
- 클래스 헤더 파일에 필요한 Singular 포함을 추가합니다.
- OnSingularLinksResolved 콜백을 처리하는 메서드를 구현합니다.
- SDK를 초기화하기 전에 USingularDelegates 객체를 생성하고 등록합니다.
-
OnSingularLinksResolved.AddDynamic()를 사용하여 핸들러 메서드를 등록합니다. - 핸들러 메서드에서 딥링크 파라미터를 처리합니다.
// Add to the include section of your class header
#include "SingularLinkParams.h"
#include "SingularDelegates.h"
// In your class header, declare the handler method
UFUNCTION()
void OnSingularLinksResolved(const FSingularLinkParams& LinkParams);
// In your class implementation file, implement the handler method
void UYourGameInstance::OnSingularLinksResolved(const FSingularLinkParams& LinkParams)
{
// Extract parameters from the tracking link
const FString Deeplink = LinkParams.SingularLinksParams["deeplink"];
const FString Passthrough = LinkParams.SingularLinksParams["passthrough"];
const bool IsDeferred = LinkParams.SingularLinksParams["isDeferred"] == "true";
// Log the parameters
UE_LOG(LogTemp, Log, TEXT("Deep Link Resolved"));
UE_LOG(LogTemp, Log, TEXT("Deeplink: %s"), *Deeplink);
UE_LOG(LogTemp, Log, TEXT("Passthrough: %s"), *Passthrough);
UE_LOG(LogTemp, Log, TEXT("Is Deferred: %s"), IsDeferred ? TEXT("true") : TEXT("false"));
// Handle deep link routing
if (!Deeplink.IsEmpty())
{
HandleDeepLinkNavigation(Deeplink, IsDeferred);
}
}
void UYourGameInstance::HandleDeepLinkNavigation(const FString& Url, bool IsDeferred)
{
// Your deep link routing logic
UE_LOG(LogTemp, Log, TEXT("Routing to: %s (Deferred: %s)"),
*Url, IsDeferred ? TEXT("true") : TEXT("false"));
// Example: Parse the URL and navigate to appropriate content
if (Url.Contains(TEXT("product")))
{
NavigateToProduct(Url);
}
else if (Url.Contains(TEXT("promo")))
{
NavigateToPromotion(Url);
}
else
{
NavigateToHome();
}
}
// Register the delegate BEFORE initializing the Singular SDK
void UYourGameInstance::InitializeSingular()
{
// Create the delegates object
USingularDelegates* SingularDelegates =
CreateDefaultSubobject<USingularDelegates>(TEXT("SingularLinksHandler"));
// Register the deep link handler
SingularDelegates->OnSingularLinksResolved.AddDynamic(
this,
&UYourGameInstance::OnSingularLinksResolved
);
UE_LOG(LogTemp, Log, TEXT("Singular Link Handler registered"));
// Now initialize the SDK
bool Success = USingularSDKBPLibrary::Initialize(
TEXT("YOUR_SDK_KEY"),
TEXT("YOUR_SDK_SECRET"),
60, // Session timeout
TEXT(""), // Custom user ID
true, // Enable SKAdNetwork
false, // Manual SKAN management
0, // Wait for tracking authorization
false, // OAID collection
true, // Enable logging
3, // Log level
false, // Clipboard attribution
TEXT(""), // Facebook App ID
TEXT("") // Custom SDID
);
if (Success)
{
UE_LOG(LogTemp, Log, TEXT("Singular SDK initialized successfully"));
}
}
중요: USingularSDKBPLibrary::Initialize() 을 호출하기 전에 델리게이트를 등록해야 합니다. 초기화 후에 핸들러를 등록하면 딥링크 콜백을 받지 못합니다.
핸들러 동작
딥링크 해상도 이해
딥링크 핸들러는 사용자가 Singular 링크를 탭할 때 앱이 새로 설치되었는지 또는 이미 설치되었는지에 따라 다르게 동작합니다.
새로 설치(디퍼드 딥링크)
새로 설치한 경우, 앱이 실행될 때 오픈 URL이 존재하지 않습니다. Singular는 추적 링크에 딥링크 값이 포함되어 있는지 확인하기 위해 어트리뷰션을 완료합니다.
디퍼드 딥링크 흐름:
- 사용자가 딥링크 값으로 구성된 Singular 트래킹 링크를 클릭합니다.
- 사용자가 앱을 설치하고 처음으로 앱을 엽니다.
- Singular SDK가 첫 번째 세션을 Singular 서버로 전송합니다.
- 어트리뷰션이 완료되고 트래킹 링크에서 딥링크를 식별합니다.
-
딥링크 값은
IsDeferred = true로 핸들러에 반환됩니다.
디퍼드 딥링크 테스트:
- 테스트 기기에서 앱을 제거합니다(현재 설치되어 있는 경우).
- iOS: IDFA를 재설정합니다. 안드로이드:구글 광고 ID(GAID)를 재설정합니다.
- 기기에서 Singular 추적 링크를 클릭합니다(딥링크 값으로 구성되었는지 확인).
- 앱을 설치하고 엽니다.
어트리뷰션이 성공적으로 완료되고 디퍼드 딥링크 값이 핸들러에 전달됩니다.
개발 테스트 팁: 다른 패키지 이름이나 번들 ID를 사용하는 개발 빌드로 딥링크를 테스트하는 경우, 개발 앱의 식별자에 맞게 추적 링크를 구성하세요. 테스트 링크를 클릭한 후에는 앱 스토어에서 프로덕션 앱을 다운로드하지 말고 언리얼 엔진 또는 플랫폼별 툴을 통해 개발 빌드를 디바이스에 직접 설치하세요.
이미 설치됨(즉시 딥 링크)
앱이 이미 설치되어 있는 경우, Singular 링크를 클릭하면 유니버설 링크(iOS) 또는 Android 앱 링크 기술을 사용하여 앱이 즉시 열립니다.
즉시 딥링크 흐름:
- 사용자가 Singular 추적 링크를 클릭합니다.
- 운영 체제는 전체 Singular 추적 링크가 포함된 오픈 URL을 제공합니다.
- SDK 초기화 중에 Singular는 URL을 파싱합니다.
-
Singular는
deeplink및passthrough값을 추출합니다. -
값은 핸들러를 통해
IsDeferred = false로 반환됩니다.
패스스루 매개변수
캠페인 메타데이터, 사용자 세분화 또는 사용자 지정 정보에 대한 패스스루 매개변수를 사용하여 추적 링크 클릭에서 추가 데이터를 캡처합니다.
추적 링크에 passthrough (_p) 파라미터가 포함된 경우 핸들러의 Passthrough 파라미터에 해당 데이터가 포함됩니다.
void UYourGameInstance::OnSingularLinksResolved(const FSingularLinkParams& LinkParams)
{
// Extract passthrough data
const FString PassthroughData = LinkParams.SingularLinksParams["passthrough"];
if (!PassthroughData.IsEmpty())
{
// Parse JSON passthrough data
TSharedPtr<FJsonObject> JsonObject;
TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(PassthroughData);
if (FJsonSerializer::Deserialize(Reader, JsonObject) && JsonObject.IsValid())
{
// Extract campaign metadata
FString CampaignId;
if (JsonObject->TryGetStringField(TEXT("campaign_id"), CampaignId))
{
UE_LOG(LogTemp, Log, TEXT("Campaign ID: %s"), *CampaignId);
}
FString UserSegment;
if (JsonObject->TryGetStringField(TEXT("segment"), UserSegment))
{
UE_LOG(LogTemp, Log, TEXT("User Segment: %s"), *UserSegment);
}
FString PromoCode;
if (JsonObject->TryGetStringField(TEXT("promo_code"), PromoCode))
{
UE_LOG(LogTemp, Log, TEXT("Promo Code: %s"), *PromoCode);
ApplyPromoCode(PromoCode);
}
// Use the data in your app
ApplyCampaignSettings(CampaignId, UserSegment);
}
else
{
UE_LOG(LogTemp, Warning, TEXT("Failed to parse passthrough data"));
}
}
}
void UYourGameInstance::ApplyCampaignSettings(const FString& CampaignId, const FString& Segment)
{
// Your campaign-specific logic
UE_LOG(LogTemp, Log, TEXT("Applying campaign settings for: %s (Segment: %s)"),
*CampaignId, *Segment);
}
패스스루 예시 URL:
https://yourapp.sng.link/A1b2c/abc123?_dl=myapp://product/123&_p={"campaign_id":"summer2025","segment":"premium","promo_code":"SAVE20"}
핸들러는 캠페인 메타데이터가 포함된 JSON 문자열이 포함된 passthrough 파라미터를 수신합니다.
FSingularLinkParams 참조
파라미터 세부 정보
FSingularLinkParams 객체에는 딥링크 핸들러에 전달된 추적 링크 세부 정보가 포함되어 있습니다.
| 파라미터 | 유형 | 설명 |
| deeplink | FString | 링크 관리 페이지에서 Singular로 구성된 딥링크 대상 URL입니다. 이 값은 사용자를 특정 인앱 콘텐츠로 리디렉션합니다. |
| passthrough | FString | 일반적으로 앱에서 처리해야 하는 캠페인 메타데이터, 사용자 세분화 또는 사용자 지정 데이터에 사용되는 추적 링크에 추가되는 패스스루 매개변수입니다. |
| isDeferred | bool |
링크가 디퍼드 딥링크로 구성되었는지 여부를 나타냅니다. 신규 인스톨(지연)의 경우 true, 기존 인스톨(즉시)의 경우 false 을 반환합니다. |
메서드 서명
// Callback method signature for Singular Links
void OnSingularLinksResolved(const FSingularLinkParams& linkParams)
// Access parameters using the SingularLinksParams map:
const FString Deeplink = linkParams.SingularLinksParams["deeplink"];
const FString Passthrough = linkParams.SingularLinksParams["passthrough"];
const bool IsDeferred = linkParams.SingularLinksParams["isDeferred"] == "true";
딥링크 라우팅 구현
딥링크 라우터 구축
중앙 집중식 딥링크 라우팅 시스템을 구현하여 딥링크 URL 구조를 기반으로 사용자를 특정 콘텐츠로 안내합니다.
// Deep Link Router class implementation
class UDeepLinkRouter : public UObject
{
public:
void RouteDeepLink(const FString& DeepLinkUrl, bool IsDeferred)
{
UE_LOG(LogTemp, Log, TEXT("Routing deep link: %s (Deferred: %s)"),
*DeepLinkUrl, IsDeferred ? TEXT("true") : TEXT("false"));
// Parse the URL scheme
if (DeepLinkUrl.StartsWith(TEXT("myapp://product/")))
{
FString ProductId = ExtractParameter(DeepLinkUrl, TEXT("myapp://product/"));
NavigateToProduct(ProductId);
}
else if (DeepLinkUrl.StartsWith(TEXT("myapp://category/")))
{
FString CategoryName = ExtractParameter(DeepLinkUrl, TEXT("myapp://category/"));
NavigateToCategory(CategoryName);
}
else if (DeepLinkUrl.StartsWith(TEXT("myapp://promo")))
{
NavigateToPromotions();
}
else if (DeepLinkUrl.StartsWith(TEXT("myapp://profile")))
{
NavigateToUserProfile();
}
else
{
// Default fallback
UE_LOG(LogTemp, Warning, TEXT("Unknown deep link format, navigating to home"));
NavigateToHome();
}
// Track deep link usage
TrackDeepLinkEvent(DeepLinkUrl, IsDeferred);
}
private:
FString ExtractParameter(const FString& Url, const FString& Prefix)
{
FString Param;
if (Url.Split(Prefix, nullptr, &Param))
{
// Remove query parameters if present
FString CleanParam;
if (Param.Split(TEXT("?"), &CleanParam, nullptr))
{
return CleanParam;
}
return Param;
}
return FString();
}
void NavigateToProduct(const FString& ProductId)
{
UE_LOG(LogTemp, Log, TEXT("Navigating to product: %s"), *ProductId);
// Your product screen navigation logic
}
void NavigateToCategory(const FString& CategoryName)
{
UE_LOG(LogTemp, Log, TEXT("Navigating to category: %s"), *CategoryName);
// Your category screen navigation logic
}
void NavigateToPromotions()
{
UE_LOG(LogTemp, Log, TEXT("Navigating to promotions"));
// Your promotions screen navigation logic
}
void NavigateToUserProfile()
{
UE_LOG(LogTemp, Log, TEXT("Navigating to user profile"));
// Your profile screen navigation logic
}
void NavigateToHome()
{
UE_LOG(LogTemp, Log, TEXT("Navigating to home screen"));
// Your home screen navigation logic
}
void TrackDeepLinkEvent(const FString& DeepLink, bool IsDeferred)
{
// Track deep link usage with Singular
TMap<FString, FString> EventAttributes;
EventAttributes.Add(TEXT("deep_link_url"), DeepLink);
EventAttributes.Add(TEXT("is_deferred"), IsDeferred ? TEXT("true") : TEXT("false"));
USingularSDKBPLibrary::EventWithAttributes(
TEXT("deep_link_opened"),
EventAttributes
);
}
};
모범 사례: Singular에서 사용자 지정 이벤트로 딥링크 오픈을 추적하여 딥링킹 캠페인의 효과를 측정하고 어떤 콘텐츠가 가장 많은 참여를 유도하는지 파악하세요.
중요 고려 사항
구현 참고 사항
- 등록 시기: 항상 Singular SDK를 초기화하기 전에 딥링크 핸들러를 등록하세요. SDK가 추적 링크를 처리하기 전에 핸들러를 등록해야 합니다.
- 스레드 안전: 핸들러 콜백은 백그라운드 스레드에서 실행될 수 있습니다. 언리얼 엔진의 스레드 안전 메커니즘을 사용하여 UI 업데이트 또는 내비게이션 로직이 게임 스레드로 전송되도록 하세요.
-
URL 스키마: 딥링크(예:
myapp://product/,myapp://category/)에 일관된 URL 체계를 설계하여 라우팅 로직과 유지보수를 간소화하세요. - 폴백 처리: 인식되지 않거나 잘못된 딥링크에 대해 항상 폴백 탐색(일반적으로 홈 화면으로 이동)을 구현하여 앱 충돌이나 사용자 경험 저하를 방지하세요.
- 두 흐름 모두 테스트하기: 즉시 딥링크(설치된 앱)와 디퍼드 딥링크(새로 설치)를 모두 테스트하여 모든 시나리오에서 적절하게 처리되는지 확인합니다.
- 파라미터 유효성 검사: 딥링크에서 추출한 모든 파라미터를 사용하기 전에 유효성을 검사하여 악성 또는 잘못된 URL로 인한 보안 문제나 충돌을 방지합니다.
- 플랫폼 구성: Singular 링크 전제 조건 가이드에 설명된 대로 플랫폼별 구성(iOS 유니버설 링크, Android 앱 링크)을 완료합니다.
프로덕션 체크리스트: 딥링킹 캠페인을 시작하기 전에 (1) SDK 초기화 전에 핸들러 등록, (2) 플랫폼별 구성 완료, (3) Singular 대시보드에서 딥링크 구성, (4) 라우팅 로직이 모든 예상 URL 패턴 처리, (5) 즉시 및 지연 흐름 모두 성공적으로 테스트되었는지 확인합니다.