연동하는 동안 문제가 발생했나요? 아래 FAQ를 참조하세요.
시작하기 전에: SDK 사전 요구 사항
Singular SDK 연동하기의단계를 따르세요: 계획 및 사전요구사항의 단계를 따르세요.
이 단계는 모든 Singular SDK 연동을 위한 전제 조건입니다.
1. SDK 설치하기
코코아팟, Swift 패키지 관리자 또는 스태틱 라이브러리를 사용하여 Singular SDK를 설치할 수 있습니다.
- 최신 버전의 CocoaPods를 다운로드하여 설치합니다.
-
pod 파일을 생성하려면 터미널에서 프로젝트 루트 폴더로 이동하여 다음을 입력합니다:
pod init
-
Singular SDK 종속성을 추가하려면 프로젝트의 Podfile에 다음을 추가합니다:
pod 'Singular-SDK'
예를 들어
-
터미널에서 프로젝트 루트 폴더로 이동하여 실행합니다:
pod install
- 이 시점부터는 .xcodeproj 파일 대신 Xcode 워크스페이스 파일인 .xcworkspace를 열어 프로젝트를 엽니다.
- 아래 지침에 따라 Swift 브리징 헤더를 생성합니다.
-
Xcode에서 파일 > 패키지 추가로 이동하여 Singular SDK GitHub 리포지토리로 들어갑니다:
https://github.com/singular-labs/Singular-iOS-SDK
-
Singular SDK 버전을 업데이트합니다:
- 패키지 추가 버튼을 클릭합니다.
-
빌드 단계 > 라이브러리와 바이너리 링크로 이동하여 AdServices.framework 라이브러리를 추가합니다. iOS 14.3 이상의 기기에서만 사용할 수 있으므로 선택 사항으로 표시해야 합니다.
-
빌드 설정 > 연동 > 기타 링커 플래그로 이동하여 다음 항목으로 기타 링커 플래그를 업데이트합니다:
- 아래 지침에 따라 Swift 브리징 헤더를 생성합니다.
Singular 프레임워크 다운로드 및 설치는 위의 코코아팟 또는 SPM 방법을 사용하지 않는 경우에만 필요합니다.
Singular SDK 12.3.2 이하에서 업그레이드하시나요?
아래 단계에 따라 이전 스태틱 라이브러리를 제거하세요.
- 프로젝트 파일로 이동하여 Singular 스태틱 라이브러리를 제거합니다. 일반적으로 Singular-iOS-sdk-v12.3.2와 같은 이름의 폴더가 있을 것입니다. 폴더를 마우스 오른쪽 버튼으로 클릭하고 프로젝트에서 삭제합니다.
- 다음 섹션으로 진행하여 새 프레임워크를 설치합니다.
처음으로 Singular 프레임워크 추가하기
-
SDK 프레임워크를 다운로드하여 압축을 풉니다.
구현에 적합한 프레임워크를 선택합니다:
- Xcode 12 이상의 경우 .xcframework [여기에서 다운로드] 사용
- Xcode 11 이하의 경우 .framework [여기에서 다운로드]를 사용합니다.
-
압축을 푼 폴더를 Xcode 프로젝트의 폴더에 추가합니다:
Xcode에서 앱 이름 > [프로젝트 이름]에 파일 추가를 마우스 오른쪽 버튼으로 클릭합니다. 대화 상자가 열리면 옵션 > 그룹 생성을 선택하고 SDK의 압축을 푼 폴더를 추가합니다.
이제 Singular 프레임워크가 프로젝트
에 있어야합니다. -
필요한 라이브러리를 추가합니다:
- Xcode에서 빌드 단계 > 라이브러리와 바이너리 링크를 선택합니다.
-
를 클릭하고 다음 라이브러리를 추가합니다:
Libsqlite3.0.tbd SystemConfiguration.framework Security.framework Libz.tbd AdSupport.framework WebKit.framework StoreKit.framework AdServices.framework (iOS 14.3 이상의 기기에서만 사용할 수 있으므로 선택 사항으로 표시합니다.).
- Singular 프레임워크 임베드 및 서명
- 일반 > 프레임워크, 라이브러리 및 임베디드 콘텐츠로 이동합니다.
- Singular 프레임워크를 "임베드 및 서명"으로 조정합니다.
코코아팟 또는 Swift 패키지 관리자를 사용하여 SDK를 설치한 경우, Singular SDK의 Obj-C 라이브러리를 사용하려면 Swift용 브리징 헤더를 생성해야 합니다.
-
프로젝트에서 Header 유형의 새 파일을 생성하고 이름을 YourProjectName-Bridging-Header로 지정합니다.
-
파일을 열고 다음을 추가합니다:
#import <Singular/Singular.h>
예시
-
빌드 설정 > Objective-C 브리징 헤더로이동하여 파일의 상대 경로를 추가합니다:
2. 기본 SDK 연동 설정
중요:
- Swift를 사용하려면 브리징 헤더가 있어야 합니다(위 가이드 참조).
- Swift 패키지 관리자를 사용하여 Singular SDK를 추가한 경우, 위에서 설명한 대로 빌드 설정 > 기타 링커 플래그를 업데이트했는지 확인하세요.
2.1. Singular 라이브러리 임포트
SceneDelegate, AppDelegate 또는 Singular가 사용될 파일에서 Singular 클래스 라이브러리를 임포트하여 Singular SDK 사용을 시작하세요.
// Cocoapods 또는 Swift Package Manager와 함께 설치된 경우
import Singular
// Objective-C(새 프레임워크)에 수동으로 설치한 경우
#import <Singular/Singular.h>
// Objective-C(레거시)에 수동으로 설치한 경우
#import "Singular.h"
2.2. 구성 객체 생성
코드에서 Singular 기능을 초기화하기 전에 Singular 구성 개체를 생성하고 모든 구성 옵션을 설정해야 합니다. 이 코드 블록은 SceneDelegate에 추가해야 합니다(또는 SceneDelegate를 사용하지 않는 경우 AppDelegate에 추가).
다음 코드 예제에서는 구성 개체를 생성하고 관리 모드에서 SKAdNetwork를 활성화하고 ATT 응답을 기다리는 시간 제한을 설정하는 등 몇 가지 일반적인 구성 옵션을 설정합니다.
다음 섹션에서는 이러한 각 옵션에 대한 자세한 내용과 사용자 지정 방법에 대해 설명합니다.
예시: 몇 가지 일반적인 옵션을 사용하여 구성 개체 만들기
func getConfig() -> SingularConfig? {
// SDK 키와 SDK 비밀번호를 사용하여 구성 개체를 만듭니다.
guard let config = SingularConfig(apiKey: Constants.APIKEY, andSecret:
Constants.SECRET) else {
return nil
}
// 사용자의 ATT 응답을 기다리기 위해 초기화하기 전에 300초 지연을 설정하십시오.
// ATT 프롬프트를 표시하지 않는 경우 이를 제거하십시오!
config.waitForTrackingAuthorizationWithTimeoutInterval = 300
// 맞춤형 ESP 도메인 지원
config.espDomains = ["links.your-website-domain.com"]
// 딥링크에 대한 핸들러 메소드 설정
config.singularLinksHandler = { params in self.handleDeeplink(params: params)}
return config
}
- (SingularConfig *)getConfig {
NSLog(@"-- Scene Delegate getConfig");
// SDK 키와 SDK 비밀번호를 사용하여 구성 개체를 만듭니다.
SingularConfig* config = [[SingularConfig alloc] initWithApiKey:APIKEY
andSecret:SECRET];
// 사용자의 ATT 응답을 기다리기 위해 초기화하기 전에 300초 지연을 설정하십시오.
// ATT 프롬프트를 표시하지 않는 경우 이를 제거하십시오!
config.waitForTrackingAuthorizationWithTimeoutInterval = 300;
// 맞춤형 ESP 도메인 지원
config.espDomains = @[@"links.your-website-domain.com"];
// 딥링크에 대한 핸들러 메소드 설정
config.singularLinksHandler = ^(SingularLinkParams * params) {[self handleDeeplink:params];};
return config;
}
참고: Singular iOS SDK 버전 12.0.6부터 SKAdNetwork가 기본적으로 활성화됩니다.
아직 이전 버전의 SDK를 사용하는 경우, 구성 개체를 생성할 때 다음 코드를 사용하여 SKAdNetwork를 활성화해야 합니다:
// 관리 모드에서 SKAdNetwork 활성화
config.skAdNetworkEnabled = true
// 관리 모드에서 SKAdNetwork 활성화
config.skAdNetworkEnabled = YES;
2.3. SKAdNetwork 옵션 사용자 지정
SKAdNetwork는최종 사용자의 개인정보를 침해하지 않고 모바일 인스톨 어트리뷰션을 결정하기 위한 Apple의 프레임워크입니다. SKAdNetwork를 사용하면 사용자의 개인 식별 정보를 공유하지 않고도 앱 마케팅 캠페인의 성과를 측정할 수 있습니다.
기본적으로 SKAdNetwork는 서버 측에서 Singular가 직접 전환 값을 관리하는 관리 모드에서 활성화됩니다. 관리 모드를 사용하는 경우, 앱에 SKAdNetwork를 처리하기 위한 코드를 추가할 필요가 없습니다.
클라이언트 측 코드를 수정하지 않고도 Singular 플랫폼을 통해 전환 값을설정하고 변경할수 있어 유연성을 극대화할 수 있습니다.
이 서버 측 관리 모드는 SKAdNetwork 타이머를 처리하는 데도 도움이 됩니다. SKAdNetwork에 등록한 시점부터 24시간 이내에 전환 값을 업데이트할 수 있습니다. 전환 값을 업데이트하기 위해 호출하면 타이머가 24시간 더 연장됩니다. 따라서 전환 이벤트를 선택할 때 해당 업데이트 기간 내에 이벤트가 발생하는지 확인해야 합니다. 관리 모드에서는 앱의 새 버전을 릴리스하지 않고도 언제든지 전환 이벤트 구성을 변경할 수 있습니다.
수동 모드에서 SKAdNetwork 사용(고급)
앱 코드를 사용하여 직접 전환 값을 업데이트하려면, 먼저 Singular 컨피그에서 manualSkanConversionManagement 플래그를 설정해야 합니다. 이렇게 하면 여러 SDK 메서드를 사용하여 전환 값을 수동으로 검색하고 업데이트할 수 있습니다.
수동 모드를 활성화하려면
func getConfig() -> SingularConfig? {
// Singular 구성 옵션
guard let config = SingularConfig(apiKey: Constants.APIKEY,
andSecret: Constants.SECRET) else {
return nil
}
//...
config.manualSkanConversionManagement = true
//...
return config
}
- (SingularConfig *)getConfig {
// Singular 구성 옵션
SingularConfig* config = [[SingularConfig alloc] initWithApiKey:APIKEY
andSecret:SECRET];
//...
config.manualSkanConversionManagement = YES;
//...
return config;
}
전환 값을 업데이트하려면:
수동 모드에서 전환 값을 업데이트하려면 skanUpdateConversionValue 메서드를 사용해야 합니다. 앱의 라이프사이클에서 필요할 때마다 사용할 수 있습니다.
참고: 수동스캔컨버젼관리를 활성화하지 않은 경우, skanUpdateConversionValue 메서드는 작동하지 않습니다.
skanUpdateConversionValue 메서드 | |
---|---|
설명 | SKAdNetwork 전환 값을 수동으로 업데이트합니다. |
시그니처 | (BOOL)skanUpdateConversionValue:(NSInteger)conversionValue; |
사용 예시 |
|
기타 SKAdNetwork 메서드:
현재 전환 값을 가져오려면, skanGetConversionValue 메서드 또는 conversionValueUpdatedCallback을 사용하세요. 둘 다 관리 및 수동 모드에서 작동합니다.
skanGetConversionValue 메서드 | |
---|---|
설명 | Singular SDK가 추적하는 현재 전환 값을 가져옵니다. |
서명 | (NSNumber *)skanGetConversionValue; |
사용 예시 |
|
전환 값 업데이트 콜백 콜백 | |
설명 | Singular SDK가 추적하는 현재 전환 값을 가져옵니다. |
시그니처 | void(^conversionValueUpdatedCallback)(NSInteger); |
사용 예시 |
|
2.4. ATT 동의 처리(초기화 지연 설정)
ATT(앱 추적 투명성) 프롬프트 표시하기
iOS 14.5부터 앱은 추적 목적에 도움이 되는 일부 사용자 데이터에 액세스하고 공유하기 전에 ( 앱 추적 투명성 프레임워크를 사용하여) 사용자 동의를 요청해야 하며, 여기에는 기기의 IDFA가포함됩니다.
Singular는 디바이스를 식별하고 인스톨 어트리뷰션을 수행하기 위해 IDFA를 사용하는 것이 매우 유용합니다( IDFA 없이 어트리뷰션을 수행하는 방법도 있지만). IDFA를 얻기 위해 사용자의 동의를 요청하는 것이 좋습니다.
ATT 응답을 기다리기 위해 초기화 지연하기
기본적으로 Singular SDK는 사용자 세션을 초기화할 때 전송합니다. 새 디바이스에서 세션이 전송되면 즉시 Singular의 어트리뷰션 프로세스가 트리거되며, 이 프로세스는 해당 시점에 Singular에서 사용 가능한 데이터만을 기반으로 수행됩니다. 따라서 Singular SDK가 첫 번째 세션을 전송하기 전에 동의를 요청하고 IDFA를 검색하는 것이 필수적입니다.
사용자 세션의 실행을 지연시키려면 구성 객체에서 대기 시간 간격으로 추적 권한 부여를 기다리는 옵션을 사용하여 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 서버로 전송하지는 않습니다.
- 앱 추적 투명성 동의가 승인/거부되거나 설정된 시간이 경과하면, SDK는 세션과 대기열에 있는 모든 이벤트를 (IDFA를 사용하거나 사용하지 않고) Singular 서버로 전송합니다.
- 그러면 Singular가 어트리뷰션 프로세스를 시작하여 사용 가능한 경우 IDFA를 활용합니다.
다음 표에는 이 연동을 사용하여 가능한 시나리오가 요약되어 있습니다:
시나리오 | IDFA 사용 가능여부 |
사용자가 동의 대화 상자를 보고 설정된 시간이 경과하기 전에 동의를 부여합니다. | IDFA 사용 가능 |
사용자가 동의 대화 상자를 보고 설정된 시간이 경과하기 전에 동의를 거부합니다. | IDFA를 사용할 수 없음 |
설정된 시간이 만료된 후 사용자에게 동의 대화 상자가 표시되고 동의를 허용합니다. | 동의가 허용된 후 보고된 사용자 이벤트에 대해서만 IDFA를 사용할 수 있습니다. |
설정된 시간이 만료되면 사용자에게 동의 대화 상자가 표시되고 동의를 거부합니다. | IDFA를 사용할 수 없는 경우 |
사용자에게 동의 대화 상자가 표시되고 아무런 조치를 취하지 않고 앱을 종료한 후 설정된 시간이 만료된 후 앱을 열고 동의를 부여합니다. | 앱이 다시 열리면 대기 중인 모든 이벤트가 Singular 서버로 전송됩니다. 이러한 이벤트에는 IDFA를 사용할 수 없습니다. 동의가 부여된 후 추적된 모든 이벤트에는 IDFA가 연결됩니다. |
사용자에게 동의 대화 상자가 표시되고 아무런 조치를 취하지 않고 앱을 종료한 후 나중에 앱을 열고 동의를 거부합니다. | 대기 중인 모든 이벤트는 앱이 다시 열리면 Singular 서버로 전송됩니다. 이러한 이벤트 또는 이후 추적된 이벤트에 대해서는 IDFA를 사용할 수 없습니다. |
2.5. 딥링크 처리
사용자가 앱이 설치된 기기에서 딥링크를 클릭하면 앱이 열리고 특정 제품이나 경험을 표시합니다.
Singular 추적 링크에는 딥링킹 기능뿐만 아니라 디퍼드 딥링킹도포함될 수 있습니다(자세한 내용은 딥링킹 FAQ및 Singular 링크 FAQ참조).
이전 단계에서 구현한 Singular SDK 구성은 콜백 함수("handleDeeplink")를 참조합니다. "handleDeeplink" 함수는 Singular SDK를 통해 딥링크 및 디퍼드 딥링크 지원을 활성화하는 데 필요합니다.
딥링크 구현을 위한 전제 조건
다음 단계를 완료했는지 확인하세요:
- Singular 링크 전제 조건의 지침을 따릅니다.
- Xcode에서 서명 및 기능 > 연결된 도메인에 Singular 사용자 지정 하위 도메인을 추가합니다.
- 정보 > URL 유형에서 URL 유형에 앱 스키마를 추가했습니다.
- Singular 플랫폼의 앱 페이지에서 Apple 개발자 팀 ID 및 스키마를 추가했습니다.
참고:
- 앱이 이미 iOS 유니버설 링크를 사용하도록 구성된 경우 유니버설 링크 도메인은 이미 연관된 도메인에 존재하며 그대로 유지될 수 있습니다. 이 도메인은 다음 섹션에 설명된 대로 지원되는 도메인 구성 옵션에 추가해야 합니다.
- 또한 Singular가 마케팅 캠페인의 어트리뷰션을 추적하고 이러한 캠페인의 딥링크를 처리할 수 있도록 Singular 사용자 지정 링크 도메인도 포함해야 합니다.
핸들러에 대한 콜백 메서드 만들기
아래 코드 예시는 handleDeeplink라는 콜백 메서드를 생성합니다(이 메서드는 위의 구성 코드 샘플에서 참조됨).
블록 시그니처는 void(^)(SingularLinkParams*)입니다. Singular링크 파라미터에는 딥링크 대상, 패스스루 파라미터, 링크 디퍼드 여부가 포함됩니다.
func handleDeeplink(params: SingularLinkParams?) {
// Singular Link에서 딥링크 데이터 가져오기
let deeplink = params?.getDeepLink()
let passthrough = params?.getPassthrough()
let isDeferredDeeplink = params?.isDeferred()
let urlParams = params?.getURLParameters()
// 여기에 딥링크 처리 코드를 추가하세요.
//...
}
- (void)handleDeeplink:(SingularLinkParams*)params{
// Singular Link에서 딥링크 데이터 가져오기
NSString* deeplink = [params getDeepLink];
NSString* passthrough = [params getPassthrough];
BOOL isDeferredDeeplink = [params isDeferred];
NSDictionary *urlParams = [params getURLParameters];
// 여기에 딥링크 처리 코드를 추가하세요.
//...
}
기타 링크 옵션
Singular SDK는 Singular가 제공하지 않는 유니버설 링크도 지원합니다. 이는 구글 애즈나 페이스북과 같이 딥링킹을 지원하는 파트너의 어트리뷰션을 측정하는 데 필요합니다.
Singular iOS SDK 버전 12.0.3 이상에서는 기본적으로 비Singular 유니버설 링크가 지원됩니다.
이전 버전의 SDK에서 타사 딥링크를 지원하려면:
- 이전 버전의 Singular iOS SDK에서는 Singular SDK를 초기화할 때마다 모든 관련 도메인( sng.link 제외)을 지원되는 도메인 구성 옵션( 구성 개체의)에 추가해야 합니다. 이렇게 하면 타사 딥링크 동작은 허용되지만 딥링크에 대한 어트리뷰션은 허용되지 않습니다. 어트리뷰션의 경우 여전히 Singular 추적 링크를 사용해야 합니다.
- supportedDomains 기능은 유니버설 링크에 대해 앱을 구성하고 현재 도메인에 자체 AASA 파일을 호스팅하고 있다고 가정합니다.
func getConfig() -> SingularConfig? {
// Singular 구성 옵션
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 구성 옵션
SingularConfig* config = [[SingularConfig alloc] initWithApiKey:APIKEY
andSecret:SECRET];
//...
config.supportedDomains = @[@"subdomain.mywebsite.com","anothersubdomain.myotherwebsite.com"];
//...
return config;
}
Singular SDK는 ESP(이메일 서비스 제공업체)가 제공하는 유니버설 링크를 지원합니다.
ESP 도메인은 HTTPS를 사용해야 합니다. Apple은 iOS 앱이 리디렉션 없이 HTTPS가 활성화된 엔드포인트에서 apple-app-site-association 파일을 가져올 것을 요구합니다. 사이트의 DNS에 DNS 구성이 필요할 수 있으므로 ESP가 앱에 대해 이 파일을 호스팅하는 방법을 확인하세요. 일반적으로 ESP는 HTTPS를 활성화하는 데 필요한 단계를 제공합니다.
ESP 도메인을 지원하려면 Singular SDK를 초기화할 때마다 구성 개체의 espDomains 구성 옵션에 사용자 지정 추적 도메인을 추가하세요.
func getConfig() -> SingularConfig? {
// Singular 구성 옵션
guard let config = SingularConfig(apiKey: Constants.APIKEY,
andSecret: Constants.SECRET) else {
return nil
}
//...
config.espDomains = ["links.mywebsite.com"]
//...
return config
}
- (SingularConfig *)getConfig {
// Singular 구성 옵션
SingularConfig* config = [[SingularConfig alloc] initWithApiKey:APIKEY
andSecret:SECRET];
//...
config.espDomains = @[@"links.mywebsite.com"];
//...
return config;
}
2.6. Singular 초기화
팁: 계속 진행하기 전에 아래 단계를 완료했는지 확인하세요!
- Singular 라이브러리 추가
- 스위프트를 사용하는 경우: 스위프트 브리징 헤더를 생성했습니다.
- Singular 컨피규레이션 객체를 생성하는 코드 추가
- 딥링크 핸들러 추가
- SKAdNetwork 활성화
- ATT를 표시하는 경우: 대기 시간 간격이 있는 대기 추적 권한 부여를 추가했습니다.
- 앱이 성공적으로 빌드되었는지 테스트합니다(이 단계에서는 앱이 오류 없이 빌드되어야 합니다).
앱이 열릴 때마다 Singular SDK를 초기화해야 합니다. 이는 모든 Singular 어트리뷰션 기능의 전제 조건이며, 새 사용자 세션을 Singular로 전송합니다(세션은 사용자 리텐션을 계산하는 데 사용됩니다). SDK는 2 .2에서 생성한 구성 개체를 사용하여 초기화됩니다. 구성 객체 만들기.
초기화 코드는 어디에 추가하나요?
앱의 모든 진입점에서 Singular SDK를 초기화해야 합니다:
-
SceneDelegate 또는 AppDelegate가 없는 SwiftUI 인터페이스를 사용하는 iOS 13+의 경우, 다음 ContentView().onOpenURL() 및 .onChange(of: scenePhase)에서 Singular SDK를 초기화하세요(예는 아래 코드 참조).
-
iOS 13+의 경우, 다음 SceneDelegate 함수에서 Singular SDK를 초기화합니다: willConnectTo 세션, continue userActivity, openURLContexts URLContexts.
-
SceneDelegate를 지원하지 않는 이전 버전의 iOS의 경우, 다음 AppDelegate 함수에서 SDK를 초기화합니다: didFinishLaunchingWithOptions, continueUserActivity, openURL.
초기화 코드 예시
// 다음 시나리오 델리게이트 함수에서 SDK를 초기화합니다.]
// willConnectTo session
func scene(_ scene: UIScene, willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions) {
let userActivity = connectionOptions.userActivities.first
// Singular SDK 콘솔에서 사용하기 위해 콘솔에 IDFV를 인쇄합니다.
print(Date(), "-- Scene Delegate IDFV:",
UIDevice().identifierForVendor!.uuidString as Any)
// 여기에서 Singular SDK를 초기화합니다:
if let config = self.getConfig() {
config.userActivity = userActivity
Singular.start(config)
}
}
// continue userActivity
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
// 계속 사용자 활동에서 새 Singular 세션을 시작합니다.
if let config = self.getConfig() {
config.userActivity = userActivity
Singular.start(config)
}
}
//openURLContexts URLContexts
func scene(_ scene: UIScene, openURLContexts URLContexts:
Set<UIOpenURLContext>) {
// 딥링크 방식에서 콜드 스타트 시 새 Singular 세션 시작
if let config = self.getConfig() {
config.openUrl = openurlString
Singular.start(config)
}
// 여기에 사용자 지정 코드를 추가하여 비Singular 딥링크로 리디렉션하기
//...
}
// 다음 창그룹 함수에서 SDK를 초기화합니다.
var body: some Scene {
WindowGroup {
ContentView()
.onOpenURL(perform: { url in
openURL = url
// openURL에서 Singular 초기화하기
if let config = self.getConfig() {
config.openUrl = url
Singular.start(config)
}
})
}
.onChange(of: scenePhase) { oldValue, phase in
// SwiftUI ScenePhases는 기존 SceneDelegate 수명 주기 이벤트를 대체합니다.
switch phase {
case .background:
print("앱 장면: 배경")
case .inactive:
print("앱 장면: 비활성")
case .active:
print("앱 장면: 활성")
// Singular 초기화
if let config = self.getConfig() {
Singular.start(config)
}
@unknown default:
print("앱 장면: 알 수 없음")
}
}
}
// 다음 시나리오 델리게이트 함수에서 SDK를 초기화합니다.
// willConnectToSession
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session
options:(UISceneConnectionOptions *)connectionOptions {
NSUserActivity* userActivity = [[[connectionOptions userActivities] allObjects]
firstObject];
// Singular SDK 콘솔에서 사용할 수 있도록 공급업체 식별자(IDFV)를 Xcode 콘솔에 인쇄합니다.
NSLog(@"-- Scene Delegate IDFV: %@", [[[UIDevice currentDevice] identifierForVendor] UUIDString]);
// 백그라운드 앱에서 새 Singular 세션 시작하기
SingularConfig *config = [self getConfig];
config.userActivity = userActivity;
[Singular start:config];
}
// continueUserActivity
- (void)scene:(UIScene *)scene continueUserActivity:(NSUserActivity *)userActivity{
// 백그라운드 앱에서 새 Singular 세션을 시작합니다.
SingularConfig *config = [self getConfig];
config.userActivity = userActivity;
[Singular start:config];
}
// openURLContexts
- (void)scene:(UIScene *)scene openURLContexts:(nonnull NSSet *)URLContexts {
// 딥링크 방식에서 콜드 스타트 시 새 Singular 세션 시작
SingularConfig *config = [self getConfig];
config.openUrl = url;
[Singular start:config];
// 여기에 사용자 지정 코드를 추가하여 비Singular 딥링크로 리디렉션하기
//...
}
// 다음 앱 델리게이트 함수에서 SDK를 초기화합니다.
// didFinishLaunchingWithOptions
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// 사용자가 앱을 열 때 세션 시간 초과/Singular 링크를 사용하여 열린 경우 새 세션을 시작합니다.
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 {
// 사용자가 백그라운드에 있는 동안 Singular 링크를 사용하여 앱을 열면 새 세션을 시작합니다.
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{
// 사용자가 기존 앱 방식과 같이 비Singular 링크를 사용하여 앱을 열면 새 세션을 시작합니다.
SingularConfig *config = [self getConfig];
config.openUrl = url;
[Singular start:config];
// 여기에 사용자 지정 코드를 추가하여 비Singular 딥링크로 리디렉션하기
//...
return YES;
}
참고:
- 구성 개체를 만들 때 올바른 옵션(userActivity 또는 openUrl)을 전달하도록 주의하세요. 아래 샘플 코드를 참조하고 필요한 경우 샘플 앱을 참조하세요.
- 비즈니스를 운영하는 지역에서 제정된 다양한 개인정보 보호법(GDPR, CCPA, COPPA 포함)을 준수해야 한다는 점을 잊지 마세요. 자세한 내용은 SDK 옵트인 및 옵트아웃 사례를참조하고 데이터 개인정보 보호법을 준수하는 데 도움이 되는 Singular SDK 기능을 검토하세요.
- SDK를 초기화하려면 Singular SDK 키와 SDK 시크릿이 필요합니다. Singular 플랫폼의 "개발자 도구 > SDK 연동 > SDK 키"에서 얻을 수 있습니다.
2.7. Singular에 사용자 ID 보내기(선택 사항)
Singular SDK 방법을 사용하여 내부 사용자 ID를 Singular에 전송할 수 있습니다.
참고: Singular의 크로스 디바이스 솔루션을 사용하는 경우, 모든 플랫폼에서 사용자 ID를 수집해야 합니다.
- 사용자 ID는 모든 식별자가 될 수 있으며 PII(개인 식별 정보)를 노출해서는 안 됩니다. 예를 들어 사용자의 이메일 주소, 사용자 이름 또는 전화번호를 사용해서는 안 됩니다. Singular는 퍼스트 파티 데이터에만 고유한 해시값을 사용할 것을 권장합니다.
- 또한 Singular에 전달되는 사용자 ID 값은 모든 플랫폼(웹/모바일/PC/콘솔/오프라인)에서 캡처한 내부 사용자 ID와 동일해야 합니다.
- Singular는 사용자 수준 내보내기, ETL 및 내부 BI 포스트백(구성된 경우)에 사용자 ID를 포함합니다. 사용자 ID는 퍼스트 파티 데이터이며, Singular는 이를 다른 당사자와 공유하지 않습니다.
- Singular SDK 메서드로 설정한 사용자 ID 값은 unsetCustomUserId 메서드를 사용하여 설정 해제하거나 앱을 제거할 때까지 지속됩니다. 앱을 닫거나 다시 시작해도 사용자 ID는 설정이 해제되지 않습니다.
사용자 ID를 설정하려면 setCustomUserId 메서드를 사용합니다. 설정을 해제하려면(예: 사용자가 계정에서 '로그아웃'하는 경우) unsetCustomUserId 으로 전화하세요.
참고: 여러 사용자가 하나의 디바이스를 사용하는 경우 로그인 및 로그아웃할 때마다 사용자 ID를 설정하고 설정 해제하는 로그아웃 플로우를 구현하는 것이 좋습니다.
앱이 열릴 때 사용자 ID를 이미 알고 있는 경우 Singular SDK를 초기화하기 전에 setCustomUserId 으로 전화하세요. 이렇게 하면 Singular가 첫 번째 세션부터 사용자 ID를 가질 수 있습니다. 그러나 일반적으로 사용자가 등록하거나 로그인을 수행할 때까지 사용자 ID를 사용할 수 없습니다. 이 경우 등록 절차가 완료된 후 setCustomUserId 으로 전화하세요.
setCustomUserId 및 unsetCustomUserId 메서드 | |
---|---|
설명 | 사용자 ID를 설정 및 설정 해제합니다. |
서명 | (void)setCustomUserId:(NSString*)customUserId (void)unsetCustomUserId; |
사용 예시 |
|
중요: 이 고급 엔터프라이즈 기능은 예외적인 경우에만 사용할 수 있습니다.이 기능을 구현하기 전에 Singular의 솔루션 엔지니어와 상담하세요.
Singular는 서버 간 연동을 통해 추가 모바일 이벤트 추적 데이터를 수신할 수 있습니다. 이 기능을 활용하려면 사용자 ID를 Singular의 모바일 디바이스 추적 식별자에 매핑해야 합니다.
참고: 이 메서드는 Singular SDK를 초기화한 후 또는 사용자 ID를 확보한 후 가능한 한 빨리 호출하세요.
설정 디바이스 커스텀 유저 아이디 메서드 | |
---|---|
설명 | 사용자 지정 사용자 ID를 로그인과 동일하게 설정하고 이를 Singular의 추적 식별자에 매핑합니다. |
서명 | static void setDeviceCustomUserId(String customUserId) |
사용 예시 |
|
2.8. 글로벌 프로퍼티 구현하기(선택 사항)
Singular SDK를 사용하면 앱에서 전송되는 모든 세션 및 이벤트와 함께 Singular 서버로 전송할 사용자 정의 프로퍼티를 정의할 수 있습니다. 이러한 프로퍼티는 사용자, 앱 모드/상태 등 원하는 모든 정보를 나타낼 수 있습니다.
글로벌 프로퍼티는 최대 5개까지 정의할 수 있습니다. 이러한 속성은 설정 해제하거나 사용자가 앱을 제거할 때까지 앱 실행 사이에 (사용자가 지정한 최신 값으로) 유지됩니다.
사용 사례
글로벌 프로퍼티의 몇 가지 사용 사례는 다음과 같습니다:
- 타사 SDK에서 식별자를 전달한 다음 Singular에서 해당 타사로의 포스트백에서 매칭 목적으로 사용합니다.
- 게임 앱에서 '레벨'이라는 프로퍼티를 정의하고 초기에 '0'으로 설정할 수 있습니다. 앱에서 전송되는 모든 세션과 이벤트는 "레벨": "0"으로 전송됩니다. 사용자가 레벨을 올리면 이 속성을 "1"로 재설정하는 등의 방식으로 재설정합니다.
참고:
- 글로벌 프로퍼티는 현재 Singular의 사용자 레벨 이벤트 로그(어트리뷰션 로그 내보내기 참조)와 포스트백에 반영됩니다. Singular의 집계 보고(보고서 페이지 또는 보고 API)에서 글로벌 속성에 대한 지원은 향후 추가될 예정입니다. 이 기능에 대해 궁금한 점이 있거나 글로벌 속성 지원에 대한 업데이트에 관심이 있는 경우 Singular 고객 성공 매니저에게 문의하세요.
- 각 속성 이름과 값은 최대 200자까지 입력할 수 있습니다. 더 긴 속성 이름이나 값을 전달하면 200자로 잘립니다.
구성 개체를 통해 전역 속성 설정하기
SDK를 초기화하기 전에 전역 프로퍼티를 설정하려면 Config 객체에서 setGlobalProperty 메서드를 사용합니다.
글로벌 프로퍼티와 해당 값은 앱 실행 간에 지속되므로 설정하려는 프로퍼티가 이미 다른 값으로 설정되어 있을 수 있습니다. 기존 프로퍼티를 새 값으로 재정의할지 여부를 SDK에 알려주려면 overrideExisting 파라미터를 사용합니다.
설정 글로벌 프로퍼티 메서드 | |
---|---|
설명 | 글로벌 프로퍼티를 설정합니다. |
Signature | (void)setGlobalProperty:(NSString*)key withValue:(NSString*)value overrideExisting:(BOOL)overrideExisiting; |
사용 예시 |
|
초기화 후 전역 속성 설정
다음 메서드를 사용하여 앱 실행 중 언제든지 글로벌 프로퍼티를 설정, 설정 해제 및 검색할 수 있습니다.
참고:
- 프로퍼티가 아직 존재하지 않고 이미 5개의 다른 전역 프로퍼티가 있는 경우 프로퍼티가 추가되지 않습니다.
- 프로퍼티가 이미 설정되어 있는 경우 overrideExisting 매개변수에 따라 기존 값을 재정의할지 여부가 결정됩니다.
- 프로퍼티가 성공적으로 설정되면 이 메서드는 참을 반환하고 그렇지 않으면 거짓을 반환합니다.
setGlobalProperty 메서드 | |
---|---|
설명 | 글로벌 프로퍼티를 지정된 값으로 설정합니다. |
Signature | (BOOL) setGlobalProperty:(NSString*)key andValue:(NSString*)value overrideExisting:(BOOL)overrideExisting |
사용 예시 |
|
getGlobalProperties 메서드 | |
설명 | 모든 글로벌 프로퍼티와 해당 프로퍼티의 현재 값을 맵으로 가져옵니다. |
시그니처 | (NSDictionary*) getGlobalProperties |
사용 예시 |
|
언셋글로벌프로퍼티 메서드 | |
설명 | 글로벌 프로퍼티를 제거합니다. |
Signature | (void) unsetGlobalProperty:(NSString*)key |
사용 예시 |
|
clearGlobalProperties 메서드 | |
설명 | 모든 글로벌 프로퍼티를 제거합니다. |
Signature | (void) clearGlobalProperties |
사용 예시 |
|
2.9. 세션 타임아웃 수정하기(선택 사항)
기본적으로 앱이 백그라운드에서 60초 이상 실행된 후 포그라운드로 돌아오면 SDK는 새 세션을 등록합니다. 이 시간 제한 값을 변경하려면 설정 세션 시간 제한 메서드를 사용하여 구성에 추가합니다.
설정 세션 타임아웃 메서드 | |
---|---|
설명 | 세션 타임아웃 값을 변경합니다. |
시그니처 | (void)setSessionTimeout:(int)timeout |
사용 예시 |
|
3. 이벤트 및 구매 추적
참고: 사용자 이벤트 계획에 대한 자세한내용은 SDK 계획 및 전제조건 가이드에서 앱이 사용자 이벤트를 추적할까요?를 참조하십시오(
).
참고: 모든 인앱 이벤트는 앱에서 Singular SDK 메서드를 사용하여 Singular 서버로 전송하는 것이 좋습니다. 다른 제공업체나 내부 서버에서 Singular로 이벤트를 전송하려는 경우 아래의 하이브리드 이벤트 추적섹션을 참조하세요.
3.1. 이벤트 추적(비구매)
Singular는 인앱 이벤트에 대한 데이터를 수집하여 캠페인의 성과를 분석하고 KPI를 측정하는 데 도움을 줄 수 있습니다. 예를 들어, 게임 앱에서 사용자 로그인, 등록, 튜토리얼 완료 또는 레벨 업에 대한 데이터를 수집하고자 할 수있습니다.
Singular로 전송되는 이벤트 목록(함께 제공되는 속성 포함)은 UA/마케팅/비즈니스 팀에서 마케팅 KPI에 따라 컴파일해야 합니다.
사용자 이벤트 계획에 대한 자세한 내용은 SDK 계획 및 전제조건 가이드에서 앱이 사용자 이벤트를 추적하나요?를 참조하세요.
코드에서 event 또는 eventWithArgs 메서드를 사용하여 표준 이벤트를 Singular로 전송합니다.
참고: 표준 이벤트의 경우, 이벤트의 iOS 이름을 iOS SDK 표준 이벤트 및 속성 목록에 표시된 대로 사용하십시오(예: EVENT_SNG_LOGIN).
사용자 지정 이벤트의 경우, 조직에서 측정하려는 이벤트 중 Singular의 표준 이벤트와 일치하지 않는 이벤트는 사용자 지정 이름 (최대 32자)을 사용합니다. 최적화 목적으로 Singular로부터 이벤트를 수신할 수 있는 애드 네트워크 파트너와의 호환성을 위해 영어로 된 이름을 사용하는 것이 좋습니다.
이벤트 메서드 | |
---|---|
설명 | 추적을 위해 Singular에 사용자 이벤트를 전송합니다. |
서명 | (void)event:(NSString *)name |
사용 예시 |
|
eventWithArgs 메서드 | |
설명 | 추적할 사용자 이벤트를 추가 정보와 함께 Singular로 전송합니다. |
Signature | (void)eventWithArgs:(NSString *)name, ... |
사용 예시 | 다음 예는 권장 표준 속성이 포함된 콘텐츠 보기 이벤트를 전송합니다.
|
3.2. 구매 추적
Singular는 인앱 구매(IAP), 구독, 맞춤 구매에서 발생한 구매 이벤트를 캡처하여 캠페인 성과와 광고 비용 대비 구매률(ROAS)을 측정합니다. 구매 데이터는 세 가지 주요 채널을 통해 제공됩니다:
- Singular 대시보드의 대화형 보고서
- 사용자 지정 분석을 위한 상세 내보내기 로그 및 ETL 데이터 대상
- 외부 플랫폼에 대한 실시간 포스트백
이러한 포괄적인 구매 추적 기능을 통해 마케팅 비용 및 캠페인 최적화에 대한 데이터 기반 의사결정을 내릴 수 있으며, 데이터 소비 및 분석 방식에 유연성을 제공합니다.
요구 사항
- 사용자 지정 구매 이벤트 이름은 32개의 ASCII 문자로 제한됩니다. ASCII가 아닌 문자의 경우 UTF-8로 변환하면 32바이트로 제한됩니다.
- 이벤트 속성 이름과 속성 값은 500자로 제한됩니다.
- 통화를 3글자 ISO 4217 통화 코드로 전달합니다:
USD, EUR, INR
모범 사례
- Singular는 Singular의 표준 이벤트 및 속성 명명 규칙을 사용하여 이벤트를 전달할 것을 권장합니다.
- 맞춤 구매 이벤트 이름을 사용하는 경우, 애드 네트워크 포스트백과의 호환성을 높이기 위해 영문으로 전송해야 합니다.
- 구매 이벤트는 구매 금액이 0보다 크거나 작은 경우에만 Singular에 전송해야 합니다.
구매 추적 구현
비구독 인앱 구매
Singular에 구매 이벤트를 보고하려면 iapComplete SDK 메서드를 사용합니다. 이 메서드는 IAP(Apple의 인앱 구매) 구매 이벤트를 Singular로 전송합니다:
- 모든 거래 세부 정보, Singular가 보고서를 보강하는 데 사용할 것입니다.
- 트랜잭션의 유효성을 검사하고 사기 시도를 분석하거나 방지하는 데 사용할 수 있는 트랜잭션 영수증.
참고:
- iapComplete를 사용할 때는 이벤트에SKPaymentTransaction 객체를 포함해야 합니다.
- 다른 통화로 보고된 모든 구매은 Singular 계정에 설정된 대로 조직의 기본 통화로 자동 변환됩니다.
iapComplete 메서드
거래 영수증과 함께 구매 이벤트를 Singular로 전송합니다.
서명
(void)iapComplete:(id)transaction
(void)iapComplete:(id)transaction withName:(NSString *)name;
사용 예시
// *** Get the SKPaymentTransaction* transaction object ***
let transaction:SKPaymentTransaction = ...
// Send a transaction event to Singular without a custom event name
Singular.iapComplete(transaction)
// Send a transaction event to Singular with a custom event name
Singular.iapComplete(transaction, withName:"MyCustomRevenue")
// *** Get the SKPaymentTransaction* transaction object ***
SKPaymentTransaction* transaction = ...;
// Send a transaction event to Singular without a custom event name
[Singular iapComplete:transaction];
// Send a transaction event to Singular with a custom event name
[Singular iapComplete:transaction withName:@"MyCustomRevenue"];
구독 구매
StoreKit 연동을 통해 iOS 기기에서 실시간 구독 관리가 가능합니다. 중요: Singular는 구독 이벤트의 유효성을 검사하지 않으며, 이벤트를 Singular로 보내기 전에 디바이스에서 모든 영수증 유효성 검사를 수행해야 합니다. 스토어키트 영수증 확인에 성공한 후에만 Singular의 customRevenue 메서드를 통해 사용자 지정 구매 이벤트를 전송하세요.
customRevenue 메서드를 사용할 때는 IAP 함수를 사용하지 말고 영수증 값을 Singular로 보내지 마세요.
-
StoreKit 구현
스토어키트 프레임워크를 iOS 앱에 연동합니다.
-
구독 설정
앱 스토어 커넥트에서 인앱 제품 및 구독 항목을 설정합니다.
-
구독 정보 쿼리
구독 상태 및 영수증 정보를 조회하려면 SKPaymentQueue 및 SKReceiptRefreshRequest를 사용하세요.
-
유효성 검사 수행
영수증 유효성 검사 기술을 통해 기본 제공 확인을 수행합니다.
- 구독 이벤트 보내기
import StoreKit
class YourViewController: UIViewController, SKPaymentTransactionObserver {
override func viewDidLoad() {
super.viewDidLoad()
// Add the observer for payment transactions
SKPaymentQueue.default().add(self)
// Refresh the receipt to get the latest subscription information
refreshReceipt()
}
func refreshReceipt() {
let request = SKReceiptRefreshRequest()
request.delegate = self
request.start()
}
// Implement SKPaymentTransactionObserver methods
func paymentQueue(_ queue: SKPaymentQueue,
updatedTransactions transactions: [SKPaymentTransaction]) {
for transaction in transactions {
switch transaction.transactionState {
case .purchased, .restored:
// Handle the purchase or restore
// You can check the transaction.transactionReceipt
// for receipt information
break
case .failed:
// Handle the failed transaction
break
case .deferred:
// Handle the deferred transaction
break
case .purchasing:
// Transaction is in progress
break
@unknown default:
break
}
}
}
// Implement SKRequestDelegate method
func requestDidFinish(_ request: SKRequest) {
// Receipt refresh request completed
// Now you can use the updated receipt to check subscription status
}
func request(_ request: SKRequest, didFailWithError error: Error) {
// Handle the error during the receipt refresh request
}
}
사용자 지정 구매 방법
이벤트 이름과 함께 구매 금액, 통화 및 추가 세부 정보가 포함된 구매 이벤트를 Singular로 전송합니다.
서명
(void)customRevenue:(NSString*)eventname
currency:(NSString *)currency
amount:(double)amount
withAttributes:(NSDictionary*)attributes;
사용 예시
// Create attributes dictionary for subscription purchase
let attributes: [String: Any] = [
"subscription_id": "premium_monthly",
"is_trial": false,
"subscription_period": "monthly",
"product_id": "com.app.subscription.premium",
"renewal_type": "auto_renewable",
"subscription_status": "active"]
// Track revenue event with Singular SDK
Singular.customRevenue("subscription_purchased", // Event name
currency: "USD", // Currency code
amount: 9.99, // Purchase amount
withAttributes: attributes // Custom attributes dictionary
)
구매 유효성 검사 없는 사용자 지정 구매
Singular는 iapComplete 사용을 권장하지만, 앱이 앱스토어 IAP 추적을 사용하지 않는 경우를 대비하여 구매 이벤트를 Singular에 보고할 수 있는 두 가지 대체 방법도 제공합니다.
구매 및 customRevenue 메서드를 사용하면 거래 금액과 통화를 수동으로 지정할 수 있으며, 제품 일련 번호 및 수량 등과 같은 추가 세부 정보도 선택적으로 지정할 수 있습니다. customRevenue 메서드를 사용하면 사용자 지정 이벤트 이름도 전달할 수 있습니다.
이러한 메서드를 사용하는 경우 Singular는 거래 영수증을 받지 못하며 거래의 유효성을 검사할 수 없다는 점에 유의하세요.
구매 메서드
구매 금액, 통화 및 선택적 세부 정보가 포함된 구매 이벤트를 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;
사용 예시
// Revenue with no product details
Singular.revenue("USD", amount:1.99)
// Revenue with product details
Singular.revenue("EUR", amount:5.00,
productSKU:"SKU1928375",
productName:"Reservation Fee",
productCategory:"Fee",
productQuantity:1, productPrice:5.00)
// Send a Revenue Event with attributes in a dictionary
var dic: [AnyHashable : Any] = [:]
dic[ATTRIBUTE_SNG_ATTR_ITEM_DESCRIPTION] = "100% Organic Cotton Mixed Plaid Flannel Shirt"
dic[ATTRIBUTE_SNG_ATTR_ITEM_PRICE] = "$69.95"
dic[ATTRIBUTE_SNG_ATTR_RATING] = "5 Star"
dic[ATTRIBUTE_SNG_ATTR_SEARCH_STRING] = "Flannel Shirt"
Singular.revenue("USD", amount: 19.95, withAttributes: dic)
// Revenue with no product details
[Singular revenue:@"USD" amount:1.99];
// Revenue with product details
[Singular revenue:@"EUR" amount:5.00 productSKU:@"SKU1928375"
productName:@"Reservation Fee"
productCategory:@"Fee"
productQuantity:1
productPrice:5.00];
// Send a Revenue Event with attributes in a dictionary
NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
[dic setValue:@"100% Organic Cotton Mixed Plaid Flannel Shirt"
forKey:ATTRIBUTE_SNG_ATTR_ITEM_DESCRIPTION];
[dic setValue:@"$69.95" forKey:ATTRIBUTE_SNG_ATTR_ITEM_PRICE];
[dic setValue:@"5 Star" forKey:ATTRIBUTE_SNG_ATTR_RATING];
[dic setValue:@"Flannel Shirt" forKey:ATTRIBUTE_SNG_ATTR_SEARCH_STRING];
[Singular revenue:@"USD" amount:19.99 withAttributes:dic];
customRevenue 메서드
이벤트 이름, 구매 금액, 통화 코드 및 추가 거래 속성을 지정하여 사용자 지정 구매 이벤트를 Singular로 전송합니다. 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;
사용 예시
// Revenue with a custom name and no product details
Singular.customRevenue("MyCustomRevenue", currency:"USD", amount:1.99)
// Revenue with a custom name and product details
Singular.customRevenue("MyCustomRevenue", currency:"EUR", amount:5.00,
productSKU:"SKU1928375",
productName:"Reservation Fee",
productCategory:"Fee",
productQuantity:1,
productPrice:5.00)
// Send a Custom Revenue Event with attributes in a dictionary
var dic: [AnyHashable : Any] = [:]
dic[ATTRIBUTE_SNG_ATTR_ITEM_DESCRIPTION] = "100% Organic Cotton Mixed Plaid Flannel Shirt"
dic[ATTRIBUTE_SNG_ATTR_ITEM_PRICE] = "$69.95"
dic[ATTRIBUTE_SNG_ATTR_RATING] = "5 Star"
dic[ATTRIBUTE_SNG_ATTR_SEARCH_STRING] = "Flannel Shirt"
Singular.customRevenue("CustomRevenueWithArgsDic", currency: "USD", amount: 44.99, withAttributes: dic)
// Revenue with a custom name and no product details
[Singular customRevenue:@"MyCustomRevenue" currency:@"USD" amount:1.99];
// Revenue with a custom name and product details
[Singular customRevenue:@"MyCustomRevenue" currency:@"EUR" amount:5.00
productSKU:@"SKU1928375"
productName:@"Reservation Fee"
productCategory:@"Fee"
productQuantity:1
productPrice:5.00];
// Send a Custom Revenue Event with attributes in a dictionary
NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
[dic setValue:@"100% Organic Cotton Mixed Plaid Flannel Shirt"
forKey:ATTRIBUTE_SNG_ATTR_ITEM_DESCRIPTION];
[dic setValue:@"$69.95" forKey:ATTRIBUTE_SNG_ATTR_ITEM_PRICE];
[dic setValue:@"5 Star" forKey:ATTRIBUTE_SNG_ATTR_RATING];
[dic setValue:@"Flannel Shirt" forKey:ATTRIBUTE_SNG_ATTR_SEARCH_STRING];
[Singular customRevenue:@"MyCustomRevenue" currency:@"USD" amount:44.99 withAttributes:dic];
3.3. 하이브리드 이벤트 추적(고급)
Singular는 앱에 연동된 Singular SDK를 통해 모든 이벤트와 구매을 전송할 것을 권장합니다. 그러나 Singular는 다른 소스에서 이벤트와 구매을 수집할 수 있습니다.
Singular SDK에서 전송되지 않은 모든 이벤트는 Singular의 서버 간 이벤트 문서 요구사항을준수해야 하며, 이벤트의 정확한 어트리뷰션을 위해 일치하는 기기 식별자를 제공해야 합니다.
중요:
서버 간 이벤트 요청에 사용된 디바이스 식별자가 Singular에서 일치하는 디바이스 식별자가 없는 경우 불일치가 발생할 수 있습니다. 다음과 같은 가능성에 유의하세요:
- 이벤트 요청이 앱 세션에서 Singular SDK가 디바이스 식별자를 기록하기 '전에 ' 수신된 경우, 이벤트 요청은 알 수 없는 디바이스에 대한 '첫 번째 세션'으로 간주되며, Singular는 해당 디바이스를 오가닉 어트리뷰션으로 어트리뷰션합니다.
- Singular SDK가 디바이스 식별자를 기록했지만, Singular SDK 식별자가 서버 간 이벤트 요청에 지정된 디바이스 식별자와 다른 경우, 이벤트는 잘못 어트리뷰션됩니다.
하이브리드 이벤트 추적 가이드
Singular는 서버에서 구매에 대한 데이터를 수집하여 캠페인의 성과와 ROI를 분석하는 데 도움을 줄 수 있습니다.
요구사항:
- 인앱 등록 또는 로그인 이벤트에서 디바이스 식별자를 캡처하여 전달하고 이 데이터를 서버의 사용자 ID와 함께 저장하세요. 디바이스 식별자는 사용자에 따라 변경될 수 있으므로 사용자가 앱 세션을 생성할 때 식별자를 업데이트해야 합니다. 이렇게 하면 서버 측 이벤트가 올바른 디바이스에 어트리뷰션되도록 보장할 수 있습니다.
- 서버 측 이벤트는 플랫폼별로 다르므로 디바이스 플랫폼과 일치하는 디바이스 식별자(예: iOS 디바이스의 경우 IDFA 또는 IDFV)로만 전송해야 합니다.
- Singular 내부 BI 포스트백 메커니즘을 사용하여 이벤트를 내부 엔드포인트로 실시간으로 푸시하여 서버 측의 데이터 집합을 업데이트할 수 있습니다. 내부 BI 포스트백 FAQ를 참조하세요.
- 자세한 내용은 서버 간 연동 가이드의 "구매 추적 " 섹션을 검토하세요.
이러한 파트너를 활성화하는 방법에 대한 자세한 내용은 아래 링크를 참조하세요.
- RevenueCat 문서에서 자세히 알아보세요.
- adapty 문서에서 자세히 알아보세요.
4. 고급 옵션
4.1.짧은 리퍼러 링크 생성
참고: 이 기능은 SDK 버전 11.0.8 이상에서 사용할 수 있습니다.
사용자가 친구와 앱을 공유할 수 있도록 단축된 공유 링크를 생성하려면 createReferrerShortLink 메서드를 사용합니다. 링크가 생성되면 앱 코드에 추천 사용자 세부 정보를 정의하세요. 이를 통해 보고 시 리퍼러 어트리뷰션을 추적할 수 있습니다.
짧은 링크를 만들려면다음과 같이 하세요:
- 정의된 딥링크로 앱 다운로드로 연결되는 Singular 맞춤 소스 링크를 작성합니다( Singular 링크 FAQ 참조). 이 링크는 아래 코드에서 기본 링크라고 불립니다.
- 모든 캠페인은 매개변수를 재정의하여 링크에 동적으로 추가할 수 있습니다(옵션 목록은 링크 매개변수 추적참조).
- 링크를 공유한 사용자의 새 앱 설치를 추적하기 위한 추천 사용자의 이름과 ID입니다.
아래 예시와 같이 createReferrerShortLink 메서드를 사용하여 짧은 링크를 생성합니다.
createReferrerShortLink 메서드 | |
---|---|
설명 | 사용자가 친구와 앱을 공유할 수 있도록 단축된 공유 링크를 생성하려면 createReferrerShortLink 메서드를 사용합니다. |
Signature | (void)createReferrerShortLink:(NSString *)baseLink referrerName:(NSString *)referrerName referrerId:(NSString *)referrerId passthroughParams:(NSDictionary *)passthroughParams completionHandler:(void(^)(NSString *, NSError *))completionHandler; |
사용 예시 |
|
4.2.광고 구매 어트리뷰션 지원 추가
Singular는 광고 구매 어트리뷰션을 위해 구글 애드몹, 앱러빈, 유니티 레벨플레이(아이언소스), 트레이드플러스와 같은 미디에이션 플랫폼과 연동되어 있습니다. 또한 Singular는 일반 광고 구매 SDK 연동을 통해 다른 미디에이션 플랫폼도 지원합니다.
Singular SDK 연동 코드 스니펫을 추가하여 미디에이션 플랫폼에서 광고 구매 어트리뷰션 데이터를 가져올 수 있습니다. 이를 통해 SKAdNetwork 캠페인에 대한 광고 구매 데이터도 얻을 수 있습니다.
미디에이션 플랫폼에서 사용자 수준의 광고 구매을 확보하면 Singular는 이 데이터를 수락할 수 있는 미디어 소스에 어트리뷰션 광고 구매을 다시 전송하여 AdROAS 캠페인을 실행할 수 있습니다.
SDK 구현을 위한 지침 및 코드 스니펫 보기 [여기].
4.3.제거 추적
참고: 앱 제거 추적을 사용하려면 앱이 푸시 알림을 지원해야 합니다. APNS 구현에 대한 Apple의 가이드를 참조하세요.
제거 추적을 구성하려면 다음과 같이 하세요:
- iOS 설치 추적 설정 가이드에 따라 Singular에서 앱을 활성화합니다.
- 앱에서 Apple 푸시 알림 서비스(APNS)에서 반환된 기기 토큰을 Singular로 보냅니다. Singular에 디바이스 토큰을 전달하려면 registerDeviceTokenForUninstall 또는 registerDeviceToken 메서드를 사용합니다. 이 작업은 Singular SDK가 초기화되기 전에 수행해야 합니다. 이 메서드는 앱 델리게이트 didRegisterForRemoteNotificationsWithDeviceToken 메서드에서 호출해야 합니다.
참고: 기존 푸시 알림 구현에서 이미 디바이스 토큰을 검색하고 있는 경우 해당 값을 사용할 수 있습니다.
APNS 토큰은 일반적으로 네이티브 형식의 바이너리 데이터입니다. APNS에서 받은 토큰을 그대로 전달합니다. 앱에서 토큰 데이터 유형을 변경하는 경우 토큰을 16진법으로 인코딩된 문자열로 전달합니다(예: b0adf7c9730763f88e1a048e28c68a9f806ed032fb522debff5bfba010a9b052).
등록 디바이스 토큰 제거 메서드 | |
---|---|
설명 | APNS에서 반환된 디바이스 토큰을 전달합니다. |
서명 | + (void)registerDeviceTokenForUninstall:(NSData*)deviceToken; |
사용 예시 |
|
4.4.Singular SDK 자바스크립트 인터페이스
싱귤래러는 앱에서 싱귤래러를 호출하는 데 사용할 수 있는 자바스크립트 인터페이스를 제공합니다.
예를 들어, 자바스크립트 인터페이스를 설정하면 다음과 같이 자바스크립트 코드에서 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 핸들러
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)
}
}
}
// 나머지 코드는 여기에 들어갑니다
}
}
5. 데이터 개인정보 보호법 준수
Singular는 개인정보 보호 기능을 제공하여 GDPR 및 CCPA(캘리포니아 소비자 개인정보 보호법)와 같은 소비자 개인정보 보호법을 준수하는 파트너와 협력할 수 있도록 지원합니다. 이러한 파트너는 최종 사용자가 개인 정보 공유에 동의한 경우 알림을 받기를 원합니다.
5.1.데이터 공유 제한
사용자에게 정보 공유에 대한 동의를 요청하는 방법을 구현한 경우, limitDataSharing 메서드를 사용하여 사용자의 선택 사항을 Singular에 알려주세요:
- 사용자가 정보 공유에 동의(옵트인)했음을 표시하려면 limitDataSharing:NO를 사용합니다.
- 사용자가 동의하지 않은 경우 limitDataSharing:YES를 사용합니다.
Singular는"사용자 개인정보 포스트백"에서 제한데이터공유를 사용할 뿐만 아니라 관련 규정을 준수하기 위해 이 정보를 필요로 하는 파트너에게 전달합니다. 자세한 내용은"사용자 개인정보 및 데이터 공유 제한"을 참조하세요.
참고: 이 방법의 사용은 선택 사항이지만, 사용자가 옵트인했음을 구체적으로 고지한 경우에만 파트너가 Singular와 공유하는 어트리뷰션 정보가 있을 수 있습니다.
제한 데이터 공유 방법 | |
---|---|
설명 | 개인 데이터 공유에 대한 사용자 동의(옵트인)를 Singular로 알립니다. 데이터 공유 제한 방법을 사용하면 앱에서 제3자에게 사용자 데이터를 전송할지 여부를 제어할 수 있는 옵션이 제공됩니다. 이 방법은 사용자 기본 설정 또는 개인정보 보호 요구 사항에 따라 데이터 공유를 제한하려는 경우에 유용합니다. |
서명 | (void)limitDataSharing:(BOOL)shouldLimitDataSharing; |
사용 예시 |
|
5.2.GDPR 준수를 위한 추가 메서드
Singular SDK는 GDPR 정책을 준수하고 추적에 대한 사용자 동의 또는 비동의를 Singular에 알리는 데 도움이 되는 몇 가지 메서드를 제공합니다.
추적 옵트인 메서드 | |
---|---|
설명 | 추적에 대한 사용자 동의(옵트인)를 Singular에 알립니다. TrackingOptIn() 메서드는 Singular 서버에 “gdpr” 이벤트를 전송하는 데 사용됩니다. 이 메서드를 호출하지 않으면 앱은 사용자가 동의한 것처럼 계속 추적하지만, 사용자에게 특별히 GDPR 옵트인 표시를 하지는 않습니다. 앱이 GDPR(일반 데이터 보호 규정)을 준수해야 하는 경우 이 함수를 호출하여 사용자 동의가 제대로 기록되었는지 확인해야 합니다. |
서명 | (void)trackingOptIn; |
사용 예시 |
|
stopAllTracking 메서드 | |
설명 | 이 앱에서 이 사용자에 대한 모든 추적 활동을 중지합니다. |
서명 | (void)stopAllTracking; |
사용 예시 |
중요: 이 메서드를 호출하면 앱이 다시 시작될 때에도 SDK가 비활성화됩니다(상태는 지속됨). 이 메서드를 끄는 유일한 방법은 resumeAllTracking 메서드를 호출하는 것입니다.
|
resumeAllTracking 메서드 | |
설명 | 이 앱에서 이 사용자에 대한 활동을 다시 추적합니다. |
Signature | (void)resumeAllTracking; |
사용 예시 |
|
isAllTrackingStopped 메서드 | |
설명 | 이 앱에서 이 사용자에 대한 추적 활동의 상태를 확인합니다. |
서명 | (BOOL)isAllTrackingStopped; |
사용 예시 |
|
6.자주 묻는 질문 및 문제
테스트 앱을 빌드할 때 문제나 오류가 발생하면 이 섹션을 참조하세요.
Xcode 15에는 빌드에서 중요한 역할을 하는 "User Script Sandboxing" 이라는 새로운 옵션이 있습니다. 이 옵션의 목적은 스크립트가 시스템을 의도하지 않게 변경하는 것을 방지하여 빌드의 안정성과 보안을 강화하는 것입니다. 이 기능을 활성화하면 빌드 시스템은 사용자 스크립트가 선언되지 않은 입력/출력 종속성을 허용하지 않도록 제한합니다. 이는 종속성을 동적으로 연결하기 위해 스크립트를 실행해야 하는 Singular SDK에 문제가 됩니다.
문제를 해결하려면다음과 같이 하세요:
- Build Settings > Build Options. 로 이동합니다.
- "User Script Sandboxing" 을 "No"값으로 조정합니다.
- 브리징 헤더가 생성되었는지 확인합니다.
- 브리징 헤더 파일이 Build Settings > Objective-C Bridging Header.에 링크되어 있는지 확인합니다.
경우에 따라 iOS 시뮬레이터는 Build Settings > Excluded Architectures 에서 arm64 를 제외해야 합니다.
이 오류는 캠페인에서 노출이 확인되지 않았을 때 예상되는 오류이므로 무시해도 됩니다( 이 질문에 대한 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"