연동 시 발생하는 이슈에 대해서는 FAQ를 참고하세요.
시작 전 단계: SDK 전제 조건 확인
Singular SDK 연동: 계획과 전제조건의 단계를 따르세요.
다음은 모든 Singular SDK 연동의 전제 조건들에 대한 단계입니다.
1. SDK 설치
CocoaPods, Swift Package Manager, 또는 Static Library를 사용하여 Singular SDK를 설치할 수 있습니다.
- 가장 최신 CocoaPods 버전을 다운로드하여 설치하세요.
-
podfile 생성을 위해, Terminal과 type 내 프로젝트 루트 폴더로 이동하세요.
pod init
-
Singular SDK 디펜던시 추가를 위해, 프로젝트의 Podfile에 다음을 추가하세요:
pod 'Singular-SDK'
예시:
-
Terminal의, 프로젝트 루트 폴더에 가서 실행하세요.
pod install
- 이 시점 이후, .xcodeproj 파일이 아닌, Xcode 워크 스페이스 파일 .xcworkspace 를 통해 프로젝트를 오픈하세요.
- 하단의 설명에 따라 Swift bridging header를 생성하세요.
-
Xcode의 File > Add Packages 로 가서 Singular SDK GitHub repository를 입력하세요:
https://github.com/singular-labs/Singular-iOS-SDK
-
Singular SDK 버전을 업데이트하세요:
- Add Package 버튼을 클릭하세요.
-
Build Phases > Link Binary with Libraries에 가서 AdServices.framework 라이브러리를 추가하세요. 이는 iOS 14.3 이상의 디바이스에서만 작동할 수 있기 때문에 반드시 Optional로 선택하세요.
-
Build Settings > Linking > Other Linker Flags로 가서 Other Linker Flags에 다음 항목을 업데이트하세요:
- 하단의 설명에 따라 Swift bridging header를 생성하세요.
-
SDK를 다운로드하여 압축파일을 푼 후, 압축 해제된 폴더를 Xcode 프로젝트 폴더에 추가하세요:
-
Xcode에서, Your App Name에 마우스 오른쪽을 클릭하여 > [Your Project Name]에 파일을 추가하세요. 오픈되는 다이얼로그에, Options > Create Groups를 선택하여 SDK를 압축 해제한 폴더를 추가하세요.
해당 작업 후, 다음 파일들이 프로젝트에 존재해야 합니다: libSingular.a, Singular.h, SingularLinkParams.h, and Singular.js.
-
필수 라이브러리를 추가하기 위해서는 다음을 따르세요.
- Xcode에서 Build Phases > Link Binary With Libraries를 선택하세요.
-
+ 를 클릭하고 다음 라이브러리를 추가하세요.
Libsqlite3.0.tbd SystemConfiguration.framework Security.framework Libz.tbd AdSupport.framework iAd.framework WebKit.framework StoreKit.framework AdServices.framework (mark as Optional since it's only
available for devices with iOS 14.3 and higher).
참고: "Library Search Paths" 프로젝트 내 libSingular.a가 명시적으로 위치한 디렉토리를 확인하세요 (Build Settings > Search Paths > Library Search Paths).
CocoaPods 또는 Swift Package Manager를 통해 SDK를 설치했다면, Swift에 Singular SDK에서 Obj-C 라이브러리를 사용하여 Bridging Header를 반드시 생성해야 합니다.
-
프로젝트에서, Header 유형에 신규 파일을 생성하여, YourProjectName-Bridging-Header로 명명하세요.
-
파일을 오픈하여 다음을 추가하세요.
#import <Singular/Singular.h>
예시:
-
Build Settings > Objective-C Bridging Header로 가서 파일의 관련 패스를 추가하세요.
2. 기본 SDK 연동 설정
중요 사항:
- Swift를 사용하려면, Bridging Header가 있어야 합니다. (상단의 가이드를 참고).
- Swift Package Manager를 통해 Singular SDK를 추가했다면, 상단처럼 Build Settings > Other Linker Flags를 업데이트했는지 확인하세요.
2.1. Singular 라이브러리를 가져오기
SceneDelegate, AppDelegate, 또는 Singular가 사용될 모든 파일에, Singular 클래스 라이브러리를 가져와서 Singular SDK를 사용하세요.
// If installed with Cocoapods or Swift Package Manager
#import Singular
// If installed manually in Objective-C
#import "Singular.h"
2.2. 구성 오브젝트 생성
코드에서 Singular 기능을 초기화하기 전에, Singular 구성 오브젝트를 반드시 생성하고 구성 옵션을 설정하세요. 이 코드 블록은 SceneDelegate에 추가해야합니다. (SceneDelegate를 사용하지 않는다면, AppDelegate에 추가하세요).
다음 코드 예시는 구성 오브젝트를 생성하고, SKAdNetwork의 Managed Mode를 활성화하거나 ATT응답을 대기하는 타임아웃 설정과 같은 공통적인 구성 옵션을 설정합니다.
다음은 각 옵션과 커스텀 방법에 대한 자세한 설명입니다.
예시: 오브젝트 구성과 특정 공통 옵션 생성
func getConfig() -> SingularConfig? {
print(Date(), "-- Scene Delegate getConfig")
// Create the config object with the SDK Key and SDK Secret
guard let config = SingularConfig(apiKey: Constants.APIKEY, andSecret:
Constants.SECRET) else {
return nil
}
// Enable SKAdNetwork in Managed Mode
config.skAdNetworkEnabled = true
// Set a 300 sec delay before initialization to wait for the user's ATT response
// Remove this if you are not displaying an ATT prompt!
config.waitForTrackingAuthorizationWithTimeoutInterval = 300
// Support non-Singular Universal Links
config.supportedDomains = ["www.your-website-domain.com"]
// Support custom ESP domains
config.espDomains = ["links.your-website-domain.com"]
// Set a handler method for deep links
config.singularLinksHandler = { params in
self.processDeeplink(params: params)
}
return config
}
- (SingularConfig *)getConfig {
NSLog(@"-- Scene Delegate getConfig");
// Create the config object with the SDK Key and SDK Secret
SingularConfig* config = [[SingularConfig alloc] initWithApiKey:APIKEY andSecret:SECRET];
// Enable SKAdNetwork in Managed Mode
config.skAdNetworkEnabled = YES;
// Set a 300 sec delay before initialization to wait for the user's ATT response
// Remove this if you are not displaying an ATT prompt!
config.waitForTrackingAuthorizationWithTimeoutInterval = 300;
// Support non-Singular Universal Links
config.supportedDomains = @[@"www.your-website-domain.com"];
// Support custom ESP domains
config.espDomains = @[@"links.your-website-domain.com"];
// Set a handler method for deep links
config.singularLinksHandler = ^(SingularLinkParams * params) {[self processDeeplink:params];};
return config;
}
2.3. SKAdNetwork 옵션 커스텀
SKAdNetwork는 유저 프라이버시를 저해하지 않고 모바일 인스톨 어트리뷰션을 알아내는 Apple의 신규 프레임워크입니다. SKAdNetwork는 유저 개인의 신원을 확인할 수 있는 정보를 공유하지 않고 앱의 마케팅 캠페인에 대한 성과를 측정할 수 있게 합니다.
Singular의 신규 iOS SDK 버전을 사용하면 최소한의 엔지니어 도움으로 완벽히 SKAdNetwork를 구현할 수 있습니다. 자세한 내용은, Singular SKAdNetwork 솔루션 소개를 참고하세요.
SKAdNetwork 활성화
SKAdNetwork 추적을 앱에서 활성화하려면, 2.2. 구성 오브젝트 생성에 보여지는 대로 Singular Config에 skAdNetworkEnabled 플래그를 추가하세요.
Managed Mode에서 SKAdNetwork 사용 (권장)
기본적으로, SKAdNetwork는 Managed Mode에서 활성화되며, 이는 서버 측으로부터 Singular에 의해 컨버전 값이 직접 관리되는 것을 의미합니다. Managed Mode를 사용하면, 앱이 SKAdNetwork를 다루는 데 있어 다른 코드를 추가하지 않아도 됩니다.
이를 통해 고객 측 코드를 변경하지 않고도 Singular 웹 앱을 통해 컨버전 값들을 설정 및 변경할 수 있는 최대한의 유연성을 갖게 됩니다.
서버 측 managed mode는 또한 SKAdNetwork 타이머를 다루는 데 도움이 됩니다. SKAdNetwork는 SKAdNetwork를 등록한 시간으로부터 24시간 이내 컨버전 값을 업데이트하도록 허용합니다. 컨버전 값을 업데이트하는 모든 호출은 타이머를 24시간 더 연장합니다. 그러므로, 컨버전 이벤트를 선택할 때, 이벤트들이 해당 업데이트 윈도우 내 발생하는 이벤트인지 확인해야 합니다. Managed mode에서 앱의 신규 버전을 출시하지 않고도 언제든 컨버전 이벤트 설정을 변경할 수 있습니다.
Manual Mode에서 SKAdNetwork 사용 (고급)
자신의 고유한 앱 코드를 사용하여 컨버전 값을 업데이트 하려면, 우선 Singular Config 내 manualSkanConversionManagement 플래그를 설정해야 합니다. 이 플래그는 여러 SDK 메서드를 사용할 수 있게 하고 컨버전 값을 수동으로 업데이트할 수 있게 합니다.
Manual Mode를 활성화 하려면:
func getConfig() -> SingularConfig? {
// Singular Config Options
guard let config = SingularConfig(apiKey: Constants.APIKEY,
andSecret: Constants.SECRET) else {
return nil
}
...
config.skAdNetworkEnabled = true
config.manualSkanConversionManagement = true
...
return config
}
- (SingularConfig *)getConfig {
// Singular Config Options
SingularConfig* config = [[SingularConfig alloc] initWithApiKey:APIKEY
andSecret:SECRET];
...
config.skAdNetworkEnabled = YES;
config.manualSkanConversionManagement = YES;
...
return config;
}
컨버전 값을 업데이트 하려면:
Manual Mod에서, 컨버전 값을 업데이트 하려면, skanUpdateConversionValue 메서드를 사용해야 합니다. 이는 앱의 생명주기 내 필요한 곳이면 어디든 사용할 수 있습니다.
참고: skanUpdateConversionValue 메서드는 manualSkanConversionManagement를 활성화하지 않았다면 동작하지 않습니다.
skanUpdateConversionValue 메서드 | |
---|---|
설명 | SKAdNetwork 컨버전 값을 수동으로 업데이트. |
표기 | (BOOL)skanUpdateConversionValue:(NSInteger)conversionValue; |
활용 예시 |
|
다른 SKAdNetwork 메서드:
현재의 컨버전 값을 가져오기 위해서는, use the skanGetConversionValue 메서드 또는 conversionValueUpdatedCallback 메서드를 사용하세요. 두 메서드 모두 Managed와 Manual Mode에서 작동합니다.
skanGetConversionValue 메서드 | |
---|---|
설명 | Singular SDK에 의해 추적된 현재 컨버전 값을 획득 |
표기 | (NSNumber *)skanGetConversionValue; |
사용 예시 |
|
conversionValueUpdatedCallback 콜백 | |
설명 | Singular SDK에 의해 추적된 현재 컨버전 값을 획득 |
기호 | void(^conversionValueUpdatedCallback)(NSInteger); |
사용 예시 |
|
2.4. ATT 동의 처리 (초기화 지연 설정)
ATT (App Tracking Transparency) 프롬프트 표시
iOS 14.5 부로, 앱들은 디바이스의 IDFA를 포함하여 유저 데이터에 접근하여 추적에 필요한 일부 데이터를 공유하기 전 유저 동의를 구해게 되어있습니다. (App Tracking Transparency 프레임워크 사용)
IDFA 없이 어트리뷰션을 수행하는 여러 방법들이 존재하나, Singular의 디바이스 및 유저 인스톨 성과 식별에 있어 IDFA 존재 여부는 매우 중요합니다. 그러므로, 유저의 동의를 얻어 IDFA를 획득하는 것을 강력히 권장합니다.
ATT 응답을 위해 초기화를 지연
기본적으로, Singular SDK는 초기화가 되면 유저 세션을 전송합니다. 세션이 신규 디바이스로부터 전송이 되면, Singular 어트리뷰션 과정을 바로 발생시키게 되는데, 어트리뷰션 과정은 Singular에 존재하는 데이터만을 기반으로 수행됩니다. 그러므로, Singular SDK가 첫 세션을 전송하기 전에 동의를 구하여 IDFA를 얻는 것이 중요합니다.
유저 세션 전송을 지연시키기 위해서는, Config 오브젝트 내 waitForTrackingAuthorizationWithTimeoutInterval 옵션을 통해 Singular SDK를 초기화하세요. 이 옵션에는 2.2. 컨피규레이션 오브젝트 생성의 코드 샘플이 포함되어 있습니다.
func getConfig() -> SingularConfig? {
guard let config = SingularConfig(apiKey: Constants.APIKEY,
andSecret: Constants.SECRET) else {
return nil
}
...
config.waitForTrackingAuthorizationWithTimeoutInterval = 300
...
return config
}
- (SingularConfig *)getConfig {
SingularConfig* config = [[SingularConfig alloc] initWithApiKey:APIKEY
andSecret:SECRET];
...
config.waitForTrackingAuthorizationWithTimeoutInterval = 300;
...
return config;
}
팁: 초기화 지연을 설정할 때, 진행되는 앱 플로우는 다음과 같습니다.
- 앱이 오픈되면, Singular SDK는 세션과 유저 이벤트를 기록하기 시작하지만, Singular 서버에는 아직 전송하지 않습니다.
- App Tracking Transparency(ATT) 동의를 얻었거나/거절됐을 때 또는 설정한 시간이 모두 경과했을 때, SDK는 세션을 전송하고 모든 대기 중인 이벤트들을 Singular 서버로 전송합니다 (IDFA가 존재하거나 하지 않는 경우 모두).
- Singular는 이때 어트리뷰션을 수행하기 시작하며, IDFA가 존재하는 경우 이를 활용합니다.
다음 테이블은 연동을 통해 가능한 모든 경우를 정리한 테이블입니다.
경우 | IDFA 사용 가능 여부 |
유저가 동의 관련 다이얼로그를 확인하고 설정 시간이 경과하기전 동의를 제공한 경우 | IDFA 사용 가능 |
유저가 동의 관련 다이얼로그를 확인하고 설정 시간이 경과하기전 동의를 거절한 경우 | IDFA 사용 불가 |
설정 시간이 모두 경과한 후 유저에게 동의 관련 다이얼로그가 표시되었고 유저가 동의를 제공한 경우 | 동의가 주어진 이후 보고된 유저 이벤트들에 대해 IDFA 사용 가능 |
설정 시간이 모두 경과한 후 유저 동의 다이얼로그가 표시되었고 유저가 동의를 거절한 경우 | IDFA 사용 불가 |
유저에게 동의 다이얼로그가 표시되었고, 앱에 존재하나 액션을 취하지 않았으며, 설정 시간이 모두 경과한 후 앱을 오픈하여 동의를 제공한 경우 | 앱이 다시 오픈되었을 때 대기 중인 이벤트들이 모두 Singular 서버로 전송. 해당 이벤트들의 IDFA 사용은 불가. 동의를 얻은 후 추적된 모든 이벤트에 대한 IDFA 사용 가능 |
유저에게 동의 다이얼로그가 표시되었고, 앱에 존재하나 액션을 취하지 않았으며, 후에 앱을 오픈하여 동의를 거절한 경우 | 앱이 다시 오픈되었을 때 대기 중인 이벤트들이 Singular 서버로 전송. 동의 전과 후의 모든 이벤트에 대한 IDFA 사용 불가 |
2.5. 딥링크 처리
유저가 앱이 설치된 디바이스에서 딥링크를 클릭하면, 앱이 오픈되어 특정 제품을 표시하거나 특정 경험을 보여주는 것을 의미합니다.
Singular 트래킹 링크는 딥링크 기능과 디퍼드 딥링크를 포함할 수 있습니다. (see our 딥링크 FAQ와 Singular 링크 FAQ를 통해 더 자세한 내용을 확인하세요).
이전 단계에서 구현된 Singular SDK 구성은 콜 백 기능을 의미합니다. ("processDeeplink"). "processDeeplink" 기능은 Singular SDK를 통해 딥링크와 디퍼드 딥링크를 활성화하는데 필요합니다.
딥링크 구현의 필요 조건
다음 단계들을 반드시 수행하세요.
- Singular 링크 필요 조건을 수행.
- Xcode에서, Signing & Capabilities > Associated Domains에 Singular Custom Subdomain 을 추가.
- 앱 스킴을 Info > URL Types의 URL에 추가.
- Singular 웹 앱의 Apps 페이지에서 Team ID와 Scheme을 Apple Developer에 추가.
참고:
- iOS Universal Links를 사용하도록 앱이 이미 설정이 되어있다면, Associated Domains에 이미 Universal Link domain가 존재하며 유지할 수 있습니다. 이 도메인은, 다음 섹션에서도 설명되었듯, Supported Domains config option에 추가되어야 합니다.
- 또, 반드시 Singular custom link domain를 추가하여, Singular가 마케팅 캠페인의 어트리뷰션을 추적하고 해당 캠페인들의 딥링크를 처리할 수 있게 하세요.
핸들러에 대한 콜 백 메서드를 생성
하단의 예시는 processDeeplink라는 콜 백 메서드를 생성합니다. (이 메서드는 상단의 구성 샘플에서도 언급되어 있습니다.
블록 사인은 void(^)(SingularLinkParams*) 입니다. SingularLinkParams는 딥링크 데스티네이션, 패스 스루 파라미터와 링크가 디퍼드 되는지의 여부를 포함합니다.
func processDeeplink(params: SingularLinkParams!) {
// Get Deeplink data from Singular Link
let deeplink = params.getDeepLink()
let passthrough = params.getPassthrough()
let isDeferredDeeplink = params.isDeferred() ? "Yes" : "No"
// Add deep link handling code here
}
- (void)processDeeplink:(SingularLinkParams*)params{
// Get Deeplink data from Singular Link
NSString* deeplink = [params getDeepLink];
NSString* passthrough = [params getPassthrough];
NSString* isDeferredDeeplink = [params isDeferred] ?@"Yes": @"No"
// Add deep link handling code here
}
다른 링크 옵션
Singular SDK는 비 Singular 유니버설 링크도 지원합니다. 이는 Google Ads와 같이 딥링크를 지원하는 파트너들의 어트리뷰션을 측정하는데 필요합니다.
써드 파티의 딥링크를 지원을 위해, 모든 관련 도메인들을(sng.link 제외)를 Singular SDK가 초기화될 때마다 Config 오브젝트의 supportedDomains 구성 옵션에 추가합니다. 이 작업은 써드 파티의 딥링크 동작을 허용하나, 딥링크로 어트리뷰션 되지 않게 합니다. 어트리뷰션을 하려면 Singular 트래킹 링크를 사용해야 합니다.
참고: 이 기능은 유니버설 링크를 앱에 구성했고, 도메인에서 AASA파일을 호스트하고 있다는 전제입니다.
func getConfig() -> SingularConfig? {
// Singular Config Options
guard let config = SingularConfig(apiKey: Constants.APIKEY,
andSecret: Constants.SECRET) else {
return nil
}
...
config.supportedDomains = ["subdomain.mywebsite.com","anothersubdomain.myotherwebsite.com"]
...
return config
}
- (SingularConfig *)getConfig {
// Singular Config Options
SingularConfig* config = [[SingularConfig alloc] initWithApiKey:APIKEY
andSecret:SECRET];
...
config.supportedDomains = @[@"subdomain.mywebsite.com","anothersubdomain.myotherwebsite.com"];
...
return config;
}
Singular SDK는 ESPs (Email Service Providers)에 의해 수행되는 유니버셜 링크를 지원합니다.
ESP 도메인은 반드시 HTTPS를 활성화해야 합니다. Apple은 리 다이렉션 없이 HTTPS 활성화 엔드포인트로부터 iOS 앱이 Apple 앱 사이트 관련 파일을 가져오도록 요구하기 때문입니다. 귀하 사이트의 DNS에서 DNS 구성을 요구할 수도 있으므로, ESP를 확인하여 앱에서 이 파일이 어떻게 호스트 되는지 확인하세요. 일반적으로, ESP는 HTTPS 활성화를 위해 필요한 과정들을 제공합니다.
ESP 도메인을 지원하려면, Singular SDK가 활성화될 때마다 커스텀 트래킹 도메인을 구성 오브젝트의 espDomains 구성 옵션에 추가하세요.
func getConfig() -> SingularConfig? {
// Singular Config Options
guard let config = SingularConfig(apiKey: Constants.APIKEY,
andSecret: Constants.SECRET) else {
return nil
}
...
config.espDomains = ["links.mywebsite.com"]
...
return config
}
- (SingularConfig *)getConfig {
// Singular Config Options
SingularConfig* config = [[SingularConfig alloc] initWithApiKey:APIKEY
andSecret:SECRET];
...
config.espDomains = @[@"links.mywebsite.com"];
...
return config;
}
2.6. Singular 초기화
팁: 시작 전 다음 단계들을 모두 완료했는지 확인하세요!
- Singular Library 추가
- Swift 사용 시: Swift Bridging Header 생성
- Singular Config 오브젝트에 코드 생성
- 딥링크 핸들러 추가
- SKAdNetwork 활성화
- ATT를 표시하는 경우: waitForTrackingAuthorizationWithTimeoutInterval 추가
- 빌드한 앱 테스트 (이 단계에서 빌드한 앱은 에러 없이 작동해야 함)
Singular SDK는 앱이 오픈될 때마다 초기화 되어야 합니다. 이는 모든 Singular 어트리뷰션 기능의 전제 조건이며, 이를 통해 신규 유저 세션을 Singular로 전송합니다. (세션들은 유저 리텐션을 계산하는데 사용됩니다). SDK는 2.2. 구성 오브젝트 생성에서 생성한 config 오브젝트를 사용하여 초기화됩니다.
어디에 초기화 코드를 추가할까요?
앱의 모든 엔트리 포인트에서 Singular SDK를 초기화해야 합니다.
-
iOS 13 이상 버전, 다음 SceneDelegate 기능에서 Singular SDK를 초기화하세요: willConnectTo session, continue userActivity, openURLContexts URLContexts.
-
SceneDelegate를 지원하지 않는 구 iOS 버전에서는, 다음 AppDelegate 기능에서 SDK를 초기화하세요: didFinishLaunchingWithOptions, continueUserActivity, openURL.
초기화 코드 예시
// INITIALIZE THE SDK IN THE FOLLOWING SCENEDELEGATE FUNCTIONS
// willConnectTo session
func scene(_ scene: UIScene, willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions) {
let userActivity = connectionOptions.userActivities.first
// Print IDFV to Console for use in Singular SDK Console
print(Date(), "-- Scene Delegate IDFV:",
UIDevice().identifierForVendor!.uuidString as Any)
//Initialize the Singular SDK here:
if let config = self.getConfig() {
config.userActivity = userActivity
Singular.start(config)
}
}
// continue userActivity
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
// Starts a new Singular session on continueUserActivity
if let config = self.getConfig() {
config.userActivity = userActivity
Singular.start(config)
}
}
//openURLContexts URLContexts
func scene(_ scene: UIScene, openURLContexts URLContexts:
Set<UIOpenURLContext>) {
// Starts a new Singular session on cold start from deeplink scheme
if let config = self.getConfig() {
config.openUrl = openurlString
Singular.start(config)
}
// Add custom code here to Redirect to non-Singular deep links
// ...
}
// INITIALIZE THE SDK IN THE FOLLOWING SCENEDELEGATE FUNCTIONS// willConnectToSession
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
NSUserActivity* userActivity = [[[connectionOptions userActivities] allObjects] firstObject];
// Print identifier for Vendor (IDFV) to Xcode Console for use in Singular SDK Console
NSLog(@"-- Scene Delegate IDFV: %@", [[[UIDevice currentDevice] identifierForVendor] UUIDString]);
// Start a new Singular session from a backgrounded app
SingularConfig *config = [self getConfig];
config.userActivity = userActivity;
[Singular start:config];
}
// continueUserActivity
- (void)scene:(UIScene *)scene continueUserActivity:(NSUserActivity *)userActivity{
// Starts a new Singular session from a backgrounded App
SingularConfig *config = [self getConfig];
config.userActivity = userActivity;
[Singular start:config];
}
// openURLContexts
- (void)scene:(UIScene *)scene openURLContexts:(nonnull NSSet *)URLContexts {
// Starts a new Singular session on cold start from deeplink scheme
SingularConfig *config = [self getConfig];
config.openUrl = url;
[Singular start:config];
// Add custom code here to Redirect to Non-Singular deep links
// ....
}
// INITIALIZE THE SDK IN THE FOLLOWING APPDELEGATE FUNCTIONS// didFinishLaunchingWithOptions
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Starts new session when user opens the app if session timeout passed/opened using Singular Link
SingularConfig *config = [self getConfig];
config.launchOptions = launchOptions;
[Singular start:config];
return YES;
}
// continueUserActivity
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity
restorationHandler:(void (^)(NSArray<id> *restorableObjects))restorationHandler {
// Starts a new session when the user opens the app using a Singular Link while it was in the background
SingularConfig *config = [self getConfig];
config.userActivity = userActivity;
[Singular start:config];
return YES;
}
// openURL
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options{
// Starts new session when user opens the app using a non-Singular link, like a traditional app scheme.
SingularConfig *config = [self getConfig];
config.openUrl = url;
[Singular start:config];
// Add custom code here to Redirect to non-Singular deep links
// ,,,
return YES;
}
참고:
- config 오브젝트를 생성할 때, 올바른 옵션을 - userActivity 또는 openUrl 중 - 전달하도록 주의하세요. 하단의 샘플 코드를 확인하여, 필요한 경우 샘플 앱을 참고하세요.
- GDPR, CCPA, COPPA를 포함하여, 비즈니스를 운영하는 지역의 여러 프라이버시 정책을 준수해야 합니다. 더 자세한 정보는, SDK 옵트인과 옵트아웃 프랙티스와 데이터 프라이버시 정책에 준수하는 Singular SDK 기능들을 참고하세요.
- SDK를 초기화하려면, Singular SDK 키와 SDK 시크릿이 필요합니다. 이는 Singular 웹 앱의 Developer Tools > SDK Keys에서 획득할 수 있습니다.
2.7. 유저 ID를 Singular로 전송 (선택 사항)
Singular SDK는 앱의 내부 유저 ID를 Singular로 전송할 수 있습니다.
- PII (Personally Identifiable Information) 외, 어떤 식별자든 전송할 수 있습니다. 예를 들어, 유저의 이메일 주소와 같은 정보는 전송하지 마세요.
- 이 식별자는 모든 플랫폼(웹/모바일)에 걸쳐 포획되는 내부 유저 ID와 동일해야 합니다.
- 만약 Singular의 크로스 디바이스 측정을 사용하고 있다면, 유저 ID는 모든 플랫폼에서 반드시 수집되어야 합니다.
- 구성된 경우, Singular는 유저 레벨 추출과 내부 BI 포스트 백의 유저 ID를 노출합니다. 유저 ID는 첫 파티 데이터이며 다른 파티들과 공유되지 않습니다.
- 유저 ID는 unsetCustomUserId를 사용하여 설정을 해제하거나 또는 앱이 삭제되기 전까지 잔존합니다. 앱을 종료하거나/다시 시작하는 동작은 유저 ID의 설정을 해제하지 않습니다.
유저 ID를 설정하려면, setCustomUserId 메서드를 사용하세요. 설정을 해제하려면 (예를 들어, 유저가 계정을 로그아웃하는 경우), unsetCustomUserId를 호출하세요. 만약 다수의 유저가 단일 디바이스를 사용하는 경우, 로그아웃 플로우와 설정를 구현하고 각 로그인과 로그 아웃시 유저 ID 설정을 해제하는 것을 권장합니다.
아시다시피, 앱이 오픈될 때마다 유저 ID는 setCustomUserIdbefore를 호출하여 Singular SDK를 초기화합니다. 이 과정을 통해, Singular는 매 첫 세션마다 유저 ID를 획득할 수 있습니다. 하지만, 일반적으로, 유저 ID는 유저가 회원 가입이나 로그인 동작을 하기 전까지는 제공되지 않습니다. 이 경우, 회원 가입 동작 이후 setCustomUserId를 호출하세요.
setCustomUserId와 unsetCustomUserId 메서드 | |
---|---|
설명 | 유저 ID를 설정하거나 설정 해제 |
표기 | (void)setCustomUserId:(NSString*)customUserId (void)unsetCustomUserId; |
사용 예시 |
|
2.8. 글로벌 속성 구현 (선택 사항)
Singular SDK에서는 앱의 모든 세션, 이벤트, Singular 서버에 전송되는 커스텀 속성들을 정의할 수 있습니다. 이 속성들은 앱 모드/현황, 유저로부터 원하는 정보나 그 이외의 속성들을 의미할 수도 있습니다.
최대 5개의 글로벌 속성을 정의할 수 있습니다. 이 속성들은 앱 실행(과 가장 최근 전달한 값)으로부터 설정 해제 전까지나 앱을 삭제하기 전까지 유효합니다.
활용 사례
글로벌 속성의 활용 사례는 다음과 같습니다.
- 써드파티 측에서 인식할 수 있는 고유 식별자를 통해 Singular가 측정한 이벤트를 전달받는 경우.
- 게임 앱의 경우, "레벨" 속성을 정의하여 "0"부터 시작하도록 설정할 수 있습니다. 이 경우, 앱에서 전송되는 모든 세션과 이벤트는 "레벨":"0"부터 전송됩니다. 유저가 레벨 업하면, 해당 특성을 "1"로 초기화하는 식으로 설정하는 경우.
참고:
- 글로벌 속성은 현재 Singular유저 레벨 이벤트 로그(Exporting Attribution Logs 참고)와 포스트 백에 반영됩니다. Singular의 집계 보고 지원(Reports 페이지 또는 리포팅 API)에서 글로벌 속성은 이후에 지원될 예정입니다. 해당 기능에 대한 문의나 글로벌 속성 지원에 대한 업데이트에 질문이 있다면, Singular 고객 성공 매니저에게 문의하세요.
- 각 특성 이름과 값은 최대 200자까지 기입할 수 있습니다. 그 이상의 특성 이름이나 값을 전달하려 하면, 200자에서 잘리게 됩니다.
Config 오브젝트를 통해 글로벌 속성 설정
SDK 초기화 전에 글로벌 속성을 설정하려면, Config 오브젝트의 setGlobalProperty 메서드를 사용하세요.
글로벌 특성들과 값들은 앱이 수행되는 동안에도 남는 값이기 때문에, 설정하려는 특성이 다른 값으로 설정될 수 있습니다. 그러므로 overrideExisting 파라미터를 사용하여 기존에 존재하는 특성을 새 값으로 오버라이드하게 할 것인지 SDK에 알리세요.
setGlobalProperty 메서드 | |
---|---|
설명 | 글로벌 특성 설정 |
표기 | (void)setGlobalProperty:(NSString*)key withValue:(NSString*)value overrideExisting:(BOOL)overrideExisiting; |
사용 예시 |
|
초기화 이후 글로벌 특성 설정
다음 메서드를 설정, 설정 해제하거나, 앱 실행하는 도중 언제든 글로벌 특성을 철회하는 데 사용하세요.
참고:
- 만약 특정 특성이 아직 존재하지 않는 상태에서 5개의 글로벌 특성이 이미 존재하는 경우라면, 해당 특성은 추가되지 않습니다.
- 만약 특정 특성이 이미 설정되어 있다면, overrideExisting 파라미터가 기존 값을 오버라이드 할지를 결정합니다.
- 해당 메서드는 해당 특성이 성공적으로 설정되었다면 true를 반환하고 그렇지 않았다면 false를 반환합니다.
setGlobalProperty 메서드 | |
---|---|
설명 | 글로벌 특성을 주어진 값으로 설정 |
표기 | (BOOL) setGlobalProperty:(NSString*)key andValue:(NSString*)value overrideExisting:(BOOL)overrideExisting |
사용 예시 |
|
getGlobalProperties 메서드 | |
설명 | 모든 글로벌 특성을 철회하고 현재 값들로 매핑 |
표기 | NSDictionary*) getGlobalProperties |
사용 예시 |
|
unsetGlobalProperty 메서드 | |
설명 | 글로벌 속성 제거 |
표기 | (void) unsetGlobalProperty:(NSString*)key |
사용 예시 |
|
clearGlobalProperties 메서드 | |
설명 | 모든 글로벌 속성 제거 |
표기 | (void) clearGlobalProperties |
사용 예시 |
|
2.9. 세션 타임아웃 수정 (선택 사항)
기본적으로, 포 그라운드로 돌아오기 전 앱이 백그라운드에서 60초 이상 실행되면, SDK는 이를 신규 세션으로 기록합니다. 타임아웃 값을 설정하려면, setSessionTimeout 메서드를 사용하여 Config에 추가하세요.
setSessionTimeout 메서드 | |
---|---|
설명 | 세션 타임아웃 값을 변경 |
표기 | (void)setSessionTimeout:(int)timeout |
사용 예시 |
|
3. 이벤트 추적과 매출
참고: 유저 이벤트 계획에 대한 자세한 내용은, SDK 계획과 전제조건 가이드의 앱이 유저 이벤트를 추적할까요?를 참고하세요.
참고: 앱 내 Singular SDK 메서드를 사용하여 모든 인 앱 이벤트들을 Singular 서버로 전송하는 것을 권장합니다. 타 제공처 또는 내부 서버로부터 Singular에 이벤트들을 전송할 계획이라면, 하단의 하이브리드 이벤트 추적에서 내용을 참조하세요.
3.1. 이벤트 추적
Singular는 캠페인의 성과를 분석하는 데 도움이 되는 인 앱 이벤트에 관한 데이터를 수집할 수 있고 KPI를 측정할 수 있습니다. 예를 들어, 유저 로그인, 회원가입, 튜토리얼 완료, 게임 앱에서의 레벨 업에 관한 데이터를 수집할 수 있습니다.
Singular로 보내는 이벤트 목록(과 수반되는 어트리뷰트들)은 마케팅 KPI에 기반하여 UA/마케팅/비즈니스팀이 작성하세요.
유저 이벤트를 계획하는 방법에 대한 자세한 내용은, SDK 계획과 전제조건 가이드의 앱이 유저 이벤트를 추적할까요?를 참고하세요.
코드에서 event 또는 eventWithArgs 메서드를 사용하여 Singular에 표준 이벤트를 전송하세요.
참고: 표준 이벤트들은 iOS SDK 표준 이벤트와 어트리뷰트의 목록에 표시되는 이벤트의 iOS 명에 표시되는 대로 사용하세요. (예시, EVENT_SNG_LOGIN).
커스텀 이벤트에 있어, Singular의 표준 이벤트와 측정하고 싶은 이벤트가 전혀 일치하지 않는 경우, 원하는 커스텀 명으로 사용하세요 (최대 32자). 최적화를 목적으로 Singular로부터 이벤트를 받을 수 있는 모든 매체와의 호환성을 위해 영어 사용을 권장합니다.
event 메서드 | |
---|---|
설명 | 추적을 위해 Singular에 유저 이벤트를 전송 |
표기 | (void)event:(NSString *)name |
사용 예시 |
|
eventWithArgs 메서드 | |
설명 | 추적을 위해 부가 정보와 유저 이벤트를 Singular에 전송 |
표기 | (void)eventWithArgs:(NSString *)name, ... |
사용 예시 |
다음 예시는 Content View 이벤트와 권장되는 표준 어트리뷰트를 전송하는 예시입니다.
|
3.2. 매출 추적
Singular는 앱을 통해 캠페인의 성과와 ROI 분석에 도움이 되는 매출에 관한 데이터를 수집할 수 있습니다. Singular는 이 데이터를 리포트, 로그 추출, 포스트 백에 제공합니다.
참고: 만약 앱이 앱 스토어를 통한 IAP 추적을 지원하면, 해당 메서드의 사용을 권장합니다. 앱 스토어를 통한 IAP를 사용하지 않는다면, 하단의 다른 대안을 참조하세요.
IAP 추적을 통한 매출 보고 (권장)
매출 이벤트를 Singular에 보고하기 위해서는, iapComplete SDK method 메서드를 사용하세요. 이 메서드는 IAP (Apple 인 앱 구매) 매출 이벤트를 다음의 내용과 함께 Singular에 전송합니다.
- Singular에서 리포트를 채우는 데 사용하는 세부 거래 내역.
- 거래 확인 및 분석에 사용되거나 프러드 시도를 방지하는 데 사용될 수 있는 거래 영수증.
참고:
- iapComplete를 사용할 때, 이벤트 내 SKPaymentTransaction 오브젝트를 반드시 포함해야 합니다.
- 다른 통화로 보고되는 모든 매출은 자동으로 Singular 계정에 설정한 고객의 선호 통화로 변환됩니다.
iapComplete 메서드 | |
---|---|
설명 | 거래 이벤트를 거래 영수증과 함께 Singular로 전송 |
표기 | (void)iapComplete:(id)transaction (void)iapComplete:(id)transaction withName:(NSString *)name; |
사용 예시 |
|
대안 매출 이벤트 보고
Singular가 iapComplete 사용을 권장하는 반면, 고객의 앱이 App Store IAP 추적을 사용하지 않을 경우를 위해 매출 이벤트를 Singular로 보고하는 다른 두 메서드를 대안으로 제공합니다.
Revenue와 customRevenue 메서드는 수동으로 거래량과 통화와 함께 제품 시리얼 번호와 수량 등 다른 부가적인 상세 내역을 추가로 명시할 수 있게 합니다. customRevenue 메서드를 사용하면 또한 커스텀 이벤트 명을 전달할 수 있습니다.
만약 이 메서드들 사용하면, Singular는 결제 영수증을 얻을 수 없고, 결제도 확인할 수 없으니 주의하세요.
참고: 통화를 ISO 4217통화 코드(예시, "USD," "EUR", "INR")와 같이 세 글자로 전달하세요.
revenue 메서드 | |
---|---|
설명 | 매출량과 통화, 부가적인 내용들과 함께 매출 이벤트를 Singular에 전송 |
표기 | (void)revenue:(NSString *)currency amount:(double)amount; (void)revenue:(NSString *)currency amount:(double)amount productSKU:(NSString *)productSKU productName:(NSString *)productName productCategory:(NSString *)productCategory productQuantity:(int)productQuantity productPrice:(double)productPrice; (void)revenue:(NSString *)currency amount:(double)amount withAttributes:(NSDictionary*)attributes; |
사용 예시 |
|
customRevenue 메서드 | |
설명 | 매출량과 통화, 부가적인 내용들과 함께 매출 이벤트를 Singular에 전송 |
표기 | (void)customRevenue:(NSString *)eventName currency:(NSString *)currency amount:(double)amount; (void)customRevenue:(NSString *)eventName currency:(NSString *)currency amount:(double)amount productSKU:(NSString *)productSKU productName:(NSString *)productName productCategory:(NSString *)productCategory productQuantity:(int)productQuantity productPrice:(double)productPrice; (void)customRevenue:(NSString*)eventname currency:(NSString *)currency amount:(double)amount withAttributes:(NSDictionary*)attributes; |
사용 사례 |
|
3.3. 하이브리드 이벤트 추적 (고급)
Singular는 모든 이벤트와 매출을 앱에 연동된 Singular SDK를 통해 전달하는 것을 권장합니다. 하지만, 필요한 경우, Singular는 다른 소스로부터 아벤트와 매출을 수집할 수 있습니다.
특정 파티가 전송하는 데이터는 반드시 Singular의 서버-투-서버 이벤트 도큐먼트 필수 사항을 준수해야 하며 이벤트에 올바르게 어트리뷰트할 수 있도록 일치하는 디바이스 식별자를 제공해야 합니다.
만약 제공자 또는 서버가 이벤트 또는 매출을 올바르지 않은 식별자와 데이터 포인트로 전송하는 경우, Singular에서 데이터 불일치가 초래될 수 있습니다.
하이브리드 이벤트 추적 가이드
엔드 포인트:
하단의 테이블을 참고하여 파라미터를 추가하고 Singular S2S 이벤트 엔드포인트인 https://s2s.singular.net/api/v1/evt로 이벤트를 전송하세요.
필요 조건:
- Singular SDK를 통해 디바이스 식별자(IDFA와 IDFV)를 포획하고, 이를 서버 측에서 유저 ID와 함께 보관하세요. 디바이스 식별자는 유저에 따라 변할 수 있기 때문에 유저가 앱 세션을 생성할 때 식별자도 업데이트하세요. 이 작업은 서버 측 이벤트가 올바른 디바이스에 어트리뷰션 될 수 있게 합니다.
- 서버 측 이벤트는 플랫폼에 따라 달라지고 디바이스 식별자와 디바이스 플랫폼(예, iOS의 디바이스의 IDFA 또는 IDFV)이 일치할 때에만 전송되어야 합니다.
- Singular 내부 BI 포스트 백 메커니즘을 통해 실시간으로 이벤트를 내부 엔드 포인트로 전송할 수 있고, 이를 통해 서버 측 데이터 세트를 업데이트 할 수 있습니다. 내부 BI 포스트 백 FAQ 참고.
- 하단의 예시에서, 서버 측 이벤트를 위해 iOS에서 필요한 데이터 포인트들은 "Y"로 표시되었습니다. 매출 이벤트에 대해, 매출 량, 통화, 매출 플래그를 반드시 포함해야 합니다.
호출 파라미터:
파라미터 | 필요 여부? | 설명 | 값 예시 |
---|---|---|---|
a= | Y | SDK 키 | |
&i= | Y | 번들 ID | com.myapp |
&p= | Y | 플랫폼 | iOS |
&use_ip= | Y* | 서버 IP 주소 사용을 위한 플래그 | TRUE |
&idfa | Y | 디바이스 IDFA | 131B7AF2-52E5-41A1-AA0B-C036037575AC |
&idfv | Y | 디바이스 IDFV | 230F6839-290B-4BF9-8C4E-F165FE5980CF |
&custom_user_id= | Y | 유저 ID | user123456789 |
&n= | Y | 이벤트 명 | s2sPurchase |
&e= | 이벤트 아규먼트 |
{'sampleKey1':'sampleValue1', 'sampleKey2':'sampleValue2', 'sampleKey3':'sampleValue3'} |
|
&is_revenue= | 매출 이벤트를 위해 필요 | 매출 플래그 | TRUE |
&amt= | 매출 량 | 2.99 | |
&cur= | 매출 ISO 4217통화 코드 | USD |
요청 샘플:
https://s2s.singular.net/api/v1/evt?a=<SDK KEY>&i=com.myapp&p=iOS&use_ip=true&idfa131B7AF2-52E5-41A1-AA0B-C036037575AC&idfv230F6839-290B-4BF9-8C4E-F165FE5980CF&custom_user_id=user123456789&n=s2sPurchase&e=%7B%27sampleKey1%27%3A%27sampleValue1%27%2C%27sampleKey2%27%3A%27sampleValue2%27%2C%27sampleKey3%27%3A%27sampleValue3%27%7D&is_revenue=true&amt=2.99&cur=USD
알려진 이슈:
- 새롭게 인스톨된 앱에서, Singular SDK가 첫 세션과 디바이스 ID를 Singular 서버에 전송하기 전 서버 측 이벤트를 받으면, Singular는 어트리뷰션 과정을 이벤트에 기반하여 디바이스 ID 없이 시작하며, 이 경우는 오가닉 어트리뷰션으로 카운트하게 됩니다.
- Singular SDK를 통한 디바이스 식별자가 서버 측 이벤트에서 명시된 디바이스 식별자와 다른 경우, 이벤트는 올바르지 않게 어트리뷰트 됩니다.
필요 조건:
- 디바이스 식별자 데이터를 앱의 매출 제공처에 전송합니다. RevenueCat에 대해서는, RevenueCat 도큐먼트를 참고하세요.
알려진 이슈:
- 새롭게 인스톨된 앱에서, Singular SDK가 첫 세션을 Singular 서버에 디바이스 ID와 전송하기 전 서버 측 이벤트를 받으면, Singular는 어트리뷰션 과정을 이벤트에 기반하여 디바이스 ID 없이 시작하며, 이 경우는 오가닉 어트리뷰션으로 카운트하게 됩니다. 이 경우, 모든 매출 제공처의 유저들(디바이스 ID들)이 Singular SDK에 인식될 때까지 불일치를 초래할 수 있습니다.
세그먼트가 Singular SDK와 함께 동시에 Singular로 이벤트를 전송하는 경우, 세그먼트에서 클라우드 모드 연동을 생성해야 합니다. 또, 반드시 세그먼트 라이프 스타일 이벤트 수집을 비활성화하거나 Singular 데스티네이션으로부터 막아야 합니다.
필요 조건:
- 세그먼트로 로그인하여, 데스티네이션 카탈로그에서 "Singular"를 찾고, 연결하고 싶은 소스임을 확인하세요.
- Singular SDK 키를 입력하세요.
알려진 이슈:
- 새롭게 인스톨된 앱에서, Singular SDK가 첫 세션을 Singular 서버에 디바이스 ID와 전송하기 전 서버 측 이벤트를 받으면, Singular는 어트리뷰션 과정을 이벤트에 기반하여 디바이스 ID 없이 시작하며, 이 경우는 오가닉 어트리뷰션으로 카운트하게 됩니다. 이 경우, 모든 매출 제공처의 유저들(디바이스 ID들)이 Singular SDK에 표시될 때까지 불일치를 초래할 수 있습니다.
4. 고급 옵션
짧은 레퍼러 링크 생성
참고: 이 기능은 SDK 버전 11.0.8 이상에서 제공됩니다.
createReferrerShortLink 메서드를 사용하여 유저가 친구들과 앱을 공유할 수 있는 짧은 공유 링크를 생성하세요. 링크가 생성될 때 앱 코드에서 사용자 세부 정보를 참조하도록 정의하세요. 이 작업은 리포팅시 레퍼러 어트리뷰션을 추적할 수 있게 합니다.
짧은 링크를 생성하려면 다음 단계를 따르세요.
- Singular 커스텀 소스 링크와 앱을 다운로드하도록 유도하는 정의한 딥링크를 빌드하세요 (Singular 링크 FAQ 참고). 이 링크는 하단 코드 내 기본 링크로써 참조됩니다.
- 모든 캠페인은 동적으로 링크에 추가하는 파라미터들을 오버라이드 합니다. (트래킹 링크 파라미터를 통해 옵션 목록을 확인하세요).
- 신규 앱 인스톨의 링크를 공유한 유저의 이름과 ID를 추적합니다.
하단의 예시와 같이 짧은 링크를 생성하기 위해 createReferrerShortLink 메서드를 사용하세요.
createReferrerShortLink 메서드 | |
---|---|
설명 | 매출량과 통화, 부가적인 내용들과 함께 매출 이벤트를 Singular에 전송 |
표기 | (void)createReferrerShortLink:(NSString *)baseLink referrerName:(NSString *)referrerName referrerId:(NSString *)referrerId passthroughParams:(NSDictionary *)passthroughParams completionHandler:(void(^)(NSString *, NSError *))completionHandler; |
사용 예시 |
|
광고 매출 어트리뷰션 지원을 추가
참고: SDK 버전 11.0.0부터, Singular는 Singular SDK를 통한 광고 매출 어트리뷰션을 설정하는 옵션을 추가합니다. 광고 매출 어트리뷰션은 계속하여 앱 내 Singular SDK 업데이트 없이 API 호출을 통해 설정될 수 있습니다. 하지만, SKAdNetwork 캠페인의 광고 매출을 측정하고 싶다면, SDK를 통해 광고 매출 어트리뷰션을 설정해야 합니다.
Signular SDK에서 광고 매출 어트리뷰션 지원을 추가하려면 다음을 완료하세요.
- Singular 고객 성공 매니저에게 문의하여 계정의 광고 매출 어트리뷰션 활성화하세요.
- 최신 Singular SDK 버전을 사용하세요.
- 광고 매출 데이터에 대한 매개 플랫폼에 기반하여, Singular SDK 연동에 올바른 코드 스니핏을 추가하세요.
// 참고: 본 기능은 베타 기능으로 Admob에 문의하여 활성화하세요.
GADRewardedAd* rewardedAd;
[GADRewardedAd loadWithAdUnitID:@"AD_UNIT_ID"
request:request
completionHandler:^(GADRewardedAd *ad, NSError *error) {
if (error) {
NSLog(@"Rewarded ad failed to load with error: %@", [error localizedDescription]);
return;
}
self.rewardedAd = ad;
self.rewardedAd.paidEventHandler = ^void(GADAdValue *_Nonnull adValue){
GADAdValue* impressionData = adValue;
SingularAdData* data = [[SingularAdData alloc] initWithAdPlatfrom:@"Admob" withCurrency:[impressionData currencyCode] withRevenue:[impressionData value]];
[data setAdUnitId:[rewardedAd adUnitID]];
[data setNetworkName:rewardedAd.responseInfo.adNetworkClassName];
}
}];
// The object received from AppLovin MAX's event, didReceivedMessage
ALCMessage* message;
SingularAdData* data = [[SingularAdData alloc] initWithAdPlatfrom:@"AppLovin" withCurrency:@"USD" withRevenue:message.data[@"revenue"] doubleValue];
[data setAdUnitId:message.data[@"max_ad_unit_id"]];
[data setNetworkName:message.data[@"network_name"]];
[data setAdType:message.data[@"ad_format"]];
[Singular adRevenue:data];
// The object received from IronSource's event, impressionDataDidSucceed
ISImpressionData* impressionData;
SingularAdData* data = [[SingularAdData alloc] initWithAdPlatfrom:@"IronSource" withCurrency:@"USD" withRevenue:impressionData.revenue];
[data setAdUnitId:[impressionData instanceId]];
[data setAdUnitName:[impressionData instanceName]];
[data setImpressionId:[impressionData auctionId]];
[data setNetworkName:[impressionData adNetwork]];
[data setAdPlacementName:[impressionData placement]];
[data setAdType:[impressionData adUnit]];
[Singular adRevenue:data];
// Ensure that the ARM SDK Postbacks Flag (click here) in IronSource is turned on
// Initialize the SingularAdData object with the relevant data
SingularAdData* data = [[SingularAdData alloc] initWithAdPlatfrom:@"YOUR_AD_PLATFORM" withCurrency:@"CURRENCY_CODE" withRevenue:[NSNumber numberWithDouble:9.90]];
// The more ad data you add, the greater the granularity
[data setAdGroupId:@"AD_GROUP_ID"];
[data setNetworkName:@"AD_NETWORK_NAME"];
// Report the data to Singular
[Singular adRevenue:data];
언인스톨 추적
참고: 언인스톨 추적은 엔터프라이즈 고객에게만 제공됩니다. 또, 언인스톨 추적의 푸시 알림을 지원하는 앱을 필요로합니다. Apple APNS 구현 가이드를 참고하세요.
언인스톨 추적 설정 방법:
- 다음 가이드에 따라 Singular에서 앱을 활성화하세요: iOS 인스톨 추적 설정.
- 앱에서, Apple 푸시 알림 서비스(APNS)로 부터 디바이스 토큰을 Singular에 전송하세요. Singular에게 디바이스 토큰을 전달하려면 registerDeviceTokenForUninstall 또는 registerDeviceToken 메서드 사용하세요. 이 작업을 Singular SDK가 초기화되기 전에 하세요. 해당 작업은 AppDelegate의 didRegisterForRemoteNotificationsWithDeviceToken 메서드로부터 호출되어야 합니다
참고: 기존의 푸시 알림 구현으로부터 이미 디바이스 토큰을 가져오고 있다면, 해당 값을 사용할 수 있습니다.
APNS 토큰은 일반적으로 네이티브 형식의 이진법 데이터입니다. APNS에서 받은 토큰을 전달하세요. 앱이 토큰 형식 유형을 변경하면, 이를 Hex 인코딩된 문자열로 전달하세요. 예시: b0adf7c9730763f88e1a048e28c68a9f806ed032fb522debff5bfba010a9b052
registerDeviceTokenForUninstall 메서드 | |
---|---|
설명 | APNS에서 반환된 디바이스 토큰을 전달. |
표시 | + (void)registerDeviceTokenForUninstall:(NSData*)deviceToken; |
사용 예시 |
|
Singular SDK 자바스크립트 인터페이스
Singular는 앱에서 Singular를 호출하는 데 사용하는 자바스크립트 인터페이스를 제공합니다.
예를 들어, 자바스크립트 인터페이스를 설정하면, 다음과 같은 자바스크립트 코드로부터 이벤트를 Singular에 전송할 수 있습니다.
Singular.event('event');
Singular.event('test', JSON.stringify({"a1":"bar", "a2":"boo", "a3":"baz"}));
자바스크립트에서 지원되는 메서드
인터페이스는 다음 SDK 메서드를 지원합니다:
- setCustomUserID
- unsetCustomUserID
- event
- revenue
자바스크립트 인터페이스 활성화
참고: iOS 8.0 이상부터, Apple은 WKWebView 를 사용하여 웹 콘텐츠를 앱에 추가하도록 권장합니다. UIWebView 또는 WebView는 사용하지 마세요. 자세한 내용은 Apple WKWebView 도큐먼트를 참고하세요.
WKWebView를 사용할 때 자바스크립트 인터페이스를 활성화하려면, 어떤 코드를 WKNavigationDelegate 프로토콜(웹 뷰가 네비게이션 리퀘스트를 처리할 때 발생하는 커스텀 동작을 구현하는데 도움 되는 프로토콜)의 webView 메서드에 추가해야 합니다.
extension ViewController: WKNavigationDelegate {
func webView(_: WKWebView, decidePolicyFor: WKNavigationAction,
decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
// Singular handler
let js = "typeof(Singular)"
webView.evaluateJavaScript(js) { (result, error) -> Void in
if let resultString = result as? String {
if resultString.isEqual("undefined") {
do {
let contents = try String(contentsOfFile:
Bundle.main.path(forResource: "Singular", ofType: "js")!)
self.webView.evaluateJavaScript(contents, completionHandler: nil)
} catch { }
}
else {
print(decidePolicyFor.request)
Singular.processJSRequestWK(self.webView, withURL:decidePolicyFor.request)
}
}
}
// rest of your code goes here
}
}
5. 데이터 프라이버시 정책 준수
Singular의 개인 정보 보호 기능을 통해 GDPR과 CCPA (California Consumer Privacy Act)와 같은 고객 프라이버시 법을 준수하는 파트너와 협업할 수 있습니다. 해당 파트너들은 개인 정보 제공에 동의한 유저들이 있는 경우 이에 대한 알림 받기를 희망합니다.
데이터 공유 제한
유저에게 개인 정보를 공유할지 동의 여부를 묻는 방법을 구현하려면, limitDataSharing 메서드를 사용하여 Singular에게 유저의 선택에 대해 보고하세요.
- limitDataSharing:NO를 사용하면 유저가 정보 제공에 동의(옵트 인)했는지를 나타냅니다.
- 유저가 정보 제공에 동의하지 않았다면 limitDataSharing:YES 를 사용하세요.
Singular는 관련 법안을 준수하기 위해 이를 필요로 하는 파트너들에게 이 정보를 전달합니다.
참고: 해당 메서드 사용이 필수는 아니지만, 특별히 유저가 옵트인 한 경우에만 파트너가 Singular에게 공유하는 어트리뷰션 정보가 있을 수 있습니다.
limitDataSharing 메서드 | |
---|---|
설명 | CCPA를 준수하는 개인 정보 데이터에 대한 공유에 동의(옵트 인)한 유저 동의를 Singular에게 알림 |
표기 | (void)limitDataSharing:(BOOL)shouldLimitDataSharing; |
사용 예시 |
|
GDPR 준수하는 다른 추가 메서드들
Singular SDK는 SDPR 정책을 준수할 수 있도록 몇 가지 메서드를 제공하고, 유저의 추적 동의에 대한 여부를 Singular에 보고합니다.
trackingOptIn 메서드 | |
---|---|
설명 | 유저가 추적에 동의했는 지(옵트 인)에 대해 Singular에 보고 |
표기 | (void)trackingOptIn; |
사용 예시 |
|
stopAllTracking 메서드 | |
설명 | 앱에서 특정 유저에 대한 추적 활동들을 모두 중지 |
표기 | (void)stopAllTracking; |
사용 예시 |
중요: 이 매서드를 호출하면 앱을 재시작하더라도 (상태가 지속됨) SDK를 활성화합니다. 사용을 중단하려면 resumeAllTracking 메서드를 호출해야 합니다.
|
resumeAllTracking 메서드 | |
설명 | 앱에서 유저 활동에 대해 추적을 지속 |
표기 | (void)resumeAllTracking; |
사용 예시 |
|
isAllTrackingStopped 메서드 | |
설명 | 앱 내 유저에 대한 추적 활동의 현황을 확인 |
표기 | (BOOL)isAllTrackingStopped; |
사용 예시 |
|
자주묻는 질문과 이슈
이 구간에 대한 설명은 테스트 앱을 빌드하는데 이슈나 에러가 있는 경우에 참조하세요.
- Bridging Header가 생성되어있는지 확인하세요.
- Bridging Header 파일이 Build Settings > Objective-C Bridging Header에 연결되어 있는지 확인하세요.
이 에러는 SKAdNetwork가 캠페인에서 노출을 발견하지 못했을 때 발생하는 현상으로, 무시해도 됩니다. (이 질문에 대한 Apple의 응답을 같이 참고).
다음 로깅 에러의 경우 무시해도 됩니다:
- [logging] duplicate column name: singular_link in "ALTER TABLE sessions ADD COLUMN singular_link TEXT DEFAULT NULL"
- [logging] duplicate column name: payload in "ALTER TABLE sessions ADD COLUMN payload TEXT DEFAULT NULL"
- [logging] duplicate column name: sequence in "ALTER TABLE events ADD COLUMN sequence INTEGER DEFAULT -1"
- [logging] duplicate column name: payload in "ALTER TABLE events ADD COLUMN payload TEXT DEFAULT NULL"