광고 구매 어트리뷰션
미디에이션 플랫폼의 광고 구매을 추적하고 사용자를 확보한 마케팅 캠페인에 어트리뷰션하여 캠페인 비용, 인앱 구매, 광고 구매화 전반에 걸쳐 완벽한 ROI 가시성을 제공합니다.
개요
광고 구매 어트리뷰션이란?
광고 구매 어트리뷰션은 모바일 앱 광고 구매을 앱 설치를 유도한 사용자 확보 캠페인에 연결하여 광고 구매화를 포함한 진정한 캠페인 구매성을 측정할 수 있도록 해줍니다.
주요 혜택
- 연동 ROI 보기: Singular 대시보드에서 캠페인 비용, 인앱 구매, 광고 구매을 확인할 수 있습니다.
- 캠페인 최적화: 광고 구매 데이터를 광고 네트워크에 다시 전송하여 비딩 및 타겟팅 개선
- LTV 측정: 광고 구매화를 포함한 전체 사용자 생애 가치 계산
데이터 소스: 광고 구매 데이터는 일반적으로 사용자 수준 또는 노출 수준에서 미디에이션 플랫폼(예: 애드몹, 앱러빈 MAX, 아이언소스)에서 가져옵니다. Singular는 이 데이터를 수신하기 위한 다양한 연동 방법을 지원합니다.
자세히 알아보기: 설정, 보고 및 문제 해결에 대한 자세한 내용은 광고 구매 어트리뷰션 FAQ를참조하세요.
구현 요구 사항
중요 가이드라인
데이터 정확성이 중요합니다:
- 통화 코드: 세 글자로 구성된 ISO 4217 통화 코드(예: USD, EUR, INR)를 사용하세요. 많은 중개 플랫폼이 USD로 보고하므로 구현하기 전에 플랫폼의 통화를 확인하세요.
-
전송 전에 유효성을 검사하세요:
Singular.adRevenue()으로 전화하기 전에 항상 구매 및 통화 데이터를 확인하시기 바랍니다. 잘못된 데이터는 제출 후 수정할 수 없습니다. - 플랫폼 차이: 일부 SDK는 구매을 마이크로 단위(1,000,000으로 나누기)로 보고하는 반면, 다른 SDK는 표준 통화 단위로 보고합니다. 플랫폼의 설명서를 확인하세요.
설정 단계
광고 구매 어트리뷰션을 구현하려면 다음 단계를 따르세요:
- SDK 업데이트: 최신 Singular SDK 버전을 사용하고 있는지 확인합니다.
- 연동을 선택합니다: 아래에서 설정과 일치하는 미디에이션 플랫폼 연동을 선택합니다.
- 콜백을 구현합니다: 플랫폼별 유료 이벤트 리스너를 추가하여 구매 데이터를 캡처합니다.
- 데이터 검증: 구매 보고를 테스트하고 데이터가 Singular 대시보드에 표시되는지 확인합니다.
플랫폼 연동
애드몹 연동
노출 수준 구매 보고를 위해 유료 이벤트 리스너를 사용하여 구글 애드몹에서 광고 구매을 추적하세요.
요구 사항:
플랫폼 구매 보고: 애드몹은 플랫폼별로 구매을 다르게 보고합니다. Android는 마이크로 단위(예: $0.005 = 5000)로 구매을 반환합니다. adValue.valueMicros 을 1,000,000으로 나누어 표준 통화 단위로 변환한 후 Singular로 전송합니다.
구현
광고를 로드할 때 유료 이벤트 리스너를 설정하여 구매 데이터를 캡처하고 이를 Singular로 전송합니다.
import com.singular.sdk.Singular
import com.singular.sdk.SingularAdData
import com.google.android.gms.ads.AdRequest
import com.google.android.gms.ads.rewarded.RewardedAd
import com.google.android.gms.ads.rewarded.RewardedAdLoadCallback
private const val AD_UNIT_ID = "YOUR_AD_UNIT_ID"
class AdManager(private val context: Context) {
private var rewardedAd: RewardedAd? = null
fun loadRewardedAd() {
val adRequest = AdRequest.Builder().build()
RewardedAd.load(context, AD_UNIT_ID, adRequest,
object : RewardedAdLoadCallback() {
override fun onAdLoaded(ad: RewardedAd) {
rewardedAd = ad
// Set full screen content callback
rewardedAd?.fullScreenContentCallback =
object : FullScreenContentCallback() {
override fun onAdShowedFullScreenContent() {
Log.d("AdManager", "Rewarded ad displayed")
}
override fun onAdDismissedFullScreenContent() {
Log.d("AdManager", "Rewarded ad dismissed")
}
}
// Set paid event listener for revenue tracking
rewardedAd?.setOnPaidEventListener { adValue ->
// Convert revenue from micros to standard units
val revenue = adValue.valueMicros / 1_000_000.0
val currency = adValue.currencyCode
// Validate revenue data before sending
if (revenue > 0 && !currency.isNullOrEmpty()) {
val data = SingularAdData(
"AdMob",
currency,
revenue
)
Singular.adRevenue(data)
Log.d("AdManager", "Ad revenue sent: $revenue $currency")
} else {
Log.w("AdManager", "Invalid revenue: $revenue $currency")
}
}
}
override fun onAdFailedToLoad(error: LoadAdError) {
Log.e("AdManager", "Ad failed to load: ${error.message}")
}
})
}
}
import com.singular.sdk.Singular;
import com.singular.sdk.SingularAdData;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.rewarded.RewardedAd;
import com.google.android.gms.ads.rewarded.RewardedAdLoadCallback;
private static final String AD_UNIT_ID = "YOUR_AD_UNIT_ID";
public class AdManager {
private RewardedAd rewardedAd;
private Context context;
public AdManager(Context context) {
this.context = context;
}
public void loadRewardedAd() {
AdRequest adRequest = new AdRequest.Builder().build();
RewardedAd.load(context, AD_UNIT_ID, adRequest,
new RewardedAdLoadCallback() {
@Override
public void onAdLoaded(RewardedAd ad) {
rewardedAd = ad;
// Set full screen content callback
rewardedAd.setFullScreenContentCallback(
new FullScreenContentCallback() {
@Override
public void onAdShowedFullScreenContent() {
Log.d("AdManager", "Rewarded ad displayed");
}
@Override
public void onAdDismissedFullScreenContent() {
Log.d("AdManager", "Rewarded ad dismissed");
}
});
// Set paid event listener for revenue tracking
rewardedAd.setOnPaidEventListener(new OnPaidEventListener() {
@Override
public void onPaidEvent(AdValue adValue) {
// Convert revenue from micros to standard units
double revenue = adValue.getValueMicros() / 1_000_000.0;
String currency = adValue.getCurrencyCode();
// Validate revenue data before sending
if (revenue > 0 && currency != null && !currency.isEmpty()) {
SingularAdData data = new SingularAdData(
"AdMob",
currency,
revenue
);
Singular.adRevenue(data);
Log.d("AdManager", "Ad revenue sent: " + revenue + " " + currency);
} else {
Log.w("AdManager", "Invalid revenue: " + revenue + " " + currency);
}
}
});
}
@Override
public void onAdFailedToLoad(LoadAdError error) {
Log.e("AdManager", "Ad failed to load: " + error.getMessage());
}
});
}
}
앱러빈 MAX 연동
앱러빈 노출 수준 사용자 구매 API를 사용하여 노출 수준 광고 구매을 공유하세요.
요구 사항:
- 앱러빈 MAX SDK를 구현합니다( 노출 수준 구매 API 가이드 참조).
-
AppLovin 커뮤니케이터를 통해
max_revenue_events주제를 구독합니다.
구현
앱러빈 커뮤니케이터 콜백을 통해 구매 메시지를 처리합니다.
import com.singular.sdk.Singular
import com.singular.sdk.SingularAdData
import com.applovin.communicator.AppLovinCommunicatorMessage
override fun onMessageReceived(message: AppLovinCommunicatorMessage) {
// Check for revenue events topic
if (message.topic == "max_revenue_events") {
val adData: Bundle? = message.messageData
// Extract and validate revenue value
val revenueValue = adData?.getDouble("revenue", 0.0) ?: 0.0
if (revenueValue > 0) {
val data = SingularAdData(
"AppLovin",
"USD", // AppLovin typically reports in USD
revenueValue
)
Singular.adRevenue(data)
Log.d("AppLovin", "Ad revenue sent: $revenueValue USD")
} else {
Log.w("AppLovin", "Invalid revenue value: $revenueValue")
}
}
}
import com.singular.sdk.Singular;
import com.singular.sdk.SingularAdData;
import com.applovin.communicator.AppLovinCommunicatorMessage;
@Override
public void onMessageReceived(AppLovinCommunicatorMessage message) {
// Check for revenue events topic
if ("max_revenue_events".equals(message.getTopic())) {
Bundle adData = message.getMessageData();
// Extract and validate revenue value
double revenueValue = (adData != null) ?
adData.getDouble("revenue", 0.0) : 0.0;
if (revenueValue > 0) {
SingularAdData data = new SingularAdData(
"AppLovin",
"USD", // AppLovin typically reports in USD
revenueValue
);
Singular.adRevenue(data);
Log.d("AppLovin", "Ad revenue sent: " + revenueValue + " USD");
} else {
Log.w("AppLovin", "Invalid revenue value: " + revenueValue);
}
}
}
유니티 레벨플레이(아이언소스) 연동
IronSource SDK를 사용하여 IronSource 및 미디에이티드 네트워크의 노출 수준 구매을 추적합니다.
요구 사항
- ironSource SDK 구현( 시작 가이드 참조)
- 아이언소스 대시보드에서 ARM SDK 포스트백 플래그를 활성화합니다.
- 구매 콜백을 수신하도록 노출 데이터 리스너 설정
자세히 알아보기: 전체 설정에 대한 자세한 내용은 아이언소스 광고 구매 문서를참조하세요.
구현
노출 데이터 성공 콜백을 구현하여 구매을 캡처하고 전송합니다.
import com.singular.sdk.Singular
import com.singular.sdk.SingularAdData
import com.ironsource.mediationsdk.impressionData.ImpressionData
fun onImpressionDataSuccess(impressionData: ImpressionData?) {
// Validate impression data
if (impressionData == null) {
Log.d("IronSource", "No impression data available")
return
}
// Extract and validate revenue
val revenue = impressionData.revenue?.toDouble() ?: 0.0
if (revenue <= 0) {
Log.w("IronSource", "Invalid revenue: $revenue")
return
}
// Create and send ad revenue data
val data = SingularAdData(
"IronSource",
"USD", // IronSource typically reports in USD
revenue
)
Singular.adRevenue(data)
Log.d("IronSource", "Ad revenue sent: $revenue USD")
}
import com.singular.sdk.Singular;
import com.singular.sdk.SingularAdData;
import com.ironsource.mediationsdk.impressionData.ImpressionData;
public void onImpressionDataSuccess(ImpressionData impressionData) {
// Validate impression data
if (impressionData == null) {
Log.d("IronSource", "No impression data available");
return;
}
// Extract and validate revenue
double revenue = (impressionData.getRevenue() != null) ?
impressionData.getRevenue().doubleValue() : 0.0;
if (revenue <= 0) {
Log.w("IronSource", "Invalid revenue: " + revenue);
return;
}
// Create and send ad revenue data
SingularAdData data = new SingularAdData(
"IronSource",
"USD", // IronSource typically reports in USD
revenue
);
Singular.adRevenue(data);
Log.d("IronSource", "Ad revenue sent: " + revenue + " USD");
}
트레이드플러스 연동
글로벌 노출 리스너를 사용하여 TradPlus 중개에서 광고 구매을 캡처하세요.
요구 사항:
-
TradPlusSdk.setGlobalImpressionListener()을 통해 글로벌 노출 리스너 설정 -
onImpressionSuccess콜백을 처리하여 구매 데이터를 수신합니다. - eCPM을 밀리 단위에서 표준 통화로 변환(1000으로 나누기)
구현
글로벌 노출 리스너를 등록하여 모든 광고 노출과 구매을 추적합니다.
import com.singular.sdk.Singular
import com.singular.sdk.SingularAdData
import com.tradplus.ads.mgr.GlobalImpressionManager
import com.tradplus.ads.base.bean.TPAdInfo
// Set global impression listener
TradPlusSdk.setGlobalImpressionListener(
object : GlobalImpressionManager.GlobalImpressionListener {
override fun onImpressionSuccess(tpAdInfo: TPAdInfo?) {
// Validate ad info
if (tpAdInfo == null) {
Log.w("TradPlus", "AdInfo is null")
return
}
// Convert eCPM from milli-units to dollars
val revenue = tpAdInfo.ecpm.toDouble() / 1000.0
// Validate revenue
if (revenue <= 0) {
Log.w("TradPlus", "Invalid revenue: $revenue")
return
}
// Create and send ad revenue data
val data = SingularAdData(
"TradPlus",
"USD",
revenue
)
Singular.adRevenue(data)
Log.d("TradPlus", "Ad revenue sent: $revenue USD")
}
}
)
import com.singular.sdk.Singular;
import com.singular.sdk.SingularAdData;
import com.tradplus.ads.mgr.GlobalImpressionManager;
import com.tradplus.ads.base.bean.TPAdInfo;
// Set global impression listener
TradPlusSdk.setGlobalImpressionListener(
new GlobalImpressionManager.GlobalImpressionListener() {
@Override
public void onImpressionSuccess(TPAdInfo tpAdInfo) {
// Validate ad info
if (tpAdInfo == null) {
Log.w("TradPlus", "AdInfo is null");
return;
}
// Validate eCPM is not null
if (tpAdInfo.getEcpm() == null) {
Log.w("TradPlus", "eCPM is null");
return;
}
// Convert eCPM from milli-units to dollars
double revenue = tpAdInfo.getEcpm().doubleValue() / 1000.0;
// Validate revenue
if (revenue <= 0) {
Log.w("TradPlus", "Invalid revenue: " + revenue);
return;
}
// Create and send ad revenue data
SingularAdData data = new SingularAdData(
"TradPlus",
"USD",
revenue
);
Singular.adRevenue(data);
Log.d("TradPlus", "Ad revenue sent: " + revenue + " USD");
}
}
);
일반 연동(기타 플랫폼)
일반 SingularAdData 인터페이스를 사용하여 모든 미디에이션 플랫폼을 연동하세요.
요구 사항:
- 미디에이션 플랫폼에서 노출 수준 구매 데이터에 액세스할 수 있어야 합니다.
- 표준 통화 단위의 구매 금액(마이크로 단위 아님)
- ISO 4217 통화 코드(예: USD, EUR, INR)
데이터 정확도: Singular로 전송하기 전에 구매 및 통화 데이터의 유효성을 검사하세요. 잘못된 데이터는 제출 후에는 수정할 수 없습니다.
구현
플랫폼 이름, 통화, 구매이 포함된 SingularAdData 개체를 생성한 다음 Singular.adRevenue() 으로 호출합니다.
import com.singular.sdk.Singular
import com.singular.sdk.SingularAdData
fun reportAdRevenue(adPlatform: String, currency: String, revenue: Double) {
// Validate revenue
if (revenue <= 0) {
Log.w("AdRevenue", "Invalid revenue: $revenue")
return
}
// Validate currency
if (currency.isEmpty()) {
Log.w("AdRevenue", "Invalid currency: $currency")
return
}
// Create ad revenue data object
val data = SingularAdData(
adPlatform,
currency,
revenue
)
// Send to Singular
Singular.adRevenue(data)
Log.d("AdRevenue", "Revenue sent: $revenue $currency from $adPlatform")
}
// Example usage
reportAdRevenue("MyMediationPlatform", "USD", 0.05)
import com.singular.sdk.Singular;
import com.singular.sdk.SingularAdData;
public void reportAdRevenue(String adPlatform, String currency, double revenue) {
// Validate revenue
if (revenue <= 0) {
Log.w("AdRevenue", "Invalid revenue: " + revenue);
return;
}
// Validate currency
if (currency == null || currency.isEmpty()) {
Log.w("AdRevenue", "Invalid currency: " + currency);
return;
}
// Create ad revenue data object
SingularAdData data = new SingularAdData(
adPlatform,
currency,
revenue
);
// Send to Singular
Singular.adRevenue(data);
Log.d("AdRevenue", "Revenue sent: " + revenue + " " + currency +
" from " + adPlatform);
}
// Example usage
reportAdRevenue("MyMediationPlatform", "USD", 0.05);
테스트 및 유효성 검사
구매 보고 확인
광고 구매 구현을 테스트하여 데이터가 Singular에 올바르게 전달되는지 확인합니다.
- 로그를 확인합니다: 구매 콜백 로그가 올바른 값과 통화로 표시되는지 확인합니다.
- 광고 테스트: 테스트 광고: 구매 이벤트를 트리거하기 위해 테스트 광고를 로드하고 표시합니다.
- 대시보드 확인: 24시간 이내에 Singular 대시보드에 구매이 표시되는지 확인합니다.
- 데이터 정확성: 구매 금액이 미디에이션 플랫폼 리포트와 일치하는지 검증합니다.
문제 해결: Singular에 구매이 표시되지 않는 경우, 이를 확인하세요:
- Singular 계정에서 광고 구매 어트리뷰션이 활성화되어 있습니다.
- 구매 값이 0보다 큽니다.
- 통화 코드가 유효한 ISO 4217 코드입니다.
- 플랫폼 이름이 Singular의 예상 형식과 일치합니다.