広告収益アトリビューション
メディエーションプラットフォームからの広告収益をトラッキングし、ユーザーを獲得したマーケティングキャンペーンに紐付けることで、キャンペーンコスト、アプリ内課金、広告マネタイズ全体にわたる完全なROIの可視化を実現します。
概要
広告収益アトリビューションとは
広告収益アトリビューションは、モバイルアプリの広告収益とアプリインストールを促進したユーザー獲得キャンペーンを結びつけ、広告マネタイズを含む真のキャンペーン収益性を測定することを可能にします。
主なメリット:
- 統合ROIビュー: キャンペーンコスト、アプリ内収益、広告収益を1つのダッシュボードで確認
- キャンペーン最適化: 広告収益データを広告ネットワークに送り返し、入札とターゲティングを改善
- LTV測定: 広告マネタイズを含む完全なユーザーライフタイムバリューを算出
データソース: 広告収益データは通常、メディエーションプラットフォーム(例: AdMob、AppLovin MAX、IronSource)からユーザー単位またはインプレッション単位で提供されます。Singularは、このデータを受信するための複数の連携方法をサポートしています。
詳細はこちら: セットアップ、レポート、トラブルシューティングの詳細については、 広告収益アトリビューションFAQ をご参照ください。
実装要件
重要なガイドライン
必須のSingularAdDataパラメーター:
コンストラクター引数
adPlatform
、
currency
、
revenue
はすべて必須です。いずれかが欠落、空、または無効な場合、SDKは例外を発生させたりエラーを返したりせずに
Singular.adRevenue()
の呼び出しを暗黙的に破棄します。
Singular.adRevenue()
はSDKがまだ初期化されていない場合にも暗黙的にスキップされるため、呼び出し前に必ず
Singular.init()
が実行されていることを確認してください。
データの正確性が重要です:
- 通貨コード: 3文字のISO 4217通貨コード(例: USD、EUR、INR)を使用してください。多くのメディエーションプラットフォームはUSDで報告するため、実装前にプラットフォームの通貨を確認してください。
-
送信前の検証:
Singular.adRevenue()を呼び出す前に、必ず収益と通貨データを検証してください。誤ったデータは送信後に修正できません。 - プラットフォーム間の違い: 一部のSDKは収益をmicros単位で報告し(1,000,000で除算が必要)、他のSDKは標準通貨単位で報告します。各プラットフォームのドキュメントを確認してください。
セットアップ手順
広告収益アトリビューションを実装するには、次の手順に従ってください:
- SDKの更新: 最新のSingular SDKバージョンを使用していることを確認してください。
- 連携方法の選択: ご利用の環境に合致するメディエーションプラットフォーム連携を以下から選択してください。
- コールバックの実装: 収益データを取得するためのプラットフォーム固有の有料イベントリスナーを追加してください。
- データの検証: 収益レポートをテストし、Singularダッシュボードにデータが表示されることを確認してください。
プラットフォーム連携
AdMob連携
インプレッション単位の収益レポートのために有料イベントリスナーを使用して、Google AdMobの広告収益をトラッキングします。
要件:
プラットフォーム別の収益レポート:
AdMobはプラットフォームごとに収益の報告方法が異なります。Androidは収益をmicros単位(例: $0.005 = 5000)で返します。Singularに送信する前に
adValue.valueMicros
を1,000,000で除算して標準通貨単位に変換してください。
実装
広告のロード時に有料イベントリスナーを設定し、収益データを取得して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());
}
});
}
}
AppLovin MAX連携
AppLovin Impression-Level User Revenue APIを使用して、インプレッション単位の広告収益を共有します。
要件:
- AppLovin MAX SDKを実装 ( Impression-Level Revenue APIガイド を参照)
-
AppLovin Communicator経由で
max_revenue_eventsトピックを購読
実装
AppLovin Communicatorコールバックを通じて収益メッセージを処理します。
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);
}
}
}
Unity LevelPlay (IronSource)連携
IronSource SDKを使用して、ironSourceおよびメディエーションネットワークからのインプレッション単位の収益をトラッキングします。
要件:
- ironSource SDKを実装 ( スタートガイド を参照)
- IronSourceダッシュボードでARM SDK Postbacksフラグを有効化
- 収益コールバックを受信するためのインプレッションデータリスナーを設定
詳細はこちら: セットアップの詳細については、 IronSource広告収益ドキュメント をご参照ください。
実装
インプレッションデータの成功コールバックを実装して、収益を取得し送信します。
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連携
グローバルインプレッションリスナーを使用して、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 ecpm = tpAdInfo.ecpm ?: run {
Log.w("TradPlus", "eCPM is null")
return
}
val revenue = 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
インターフェースを使用して、任意のメディエーションプラットフォームを連携できます。
要件:
- メディエーションプラットフォームからのインプレッション単位の収益データへのアクセス
- 標準通貨単位(microsではない)の収益額
- 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);
追加属性で広告データを拡充する
SingularAdData は、インプレッション単位のメタデータ用にチェーン可能なセッターを提供します。メディエーションプラットフォームが提供する場合、これらのメソッドを使用してプレースメント、広告ユニット、メディエーショングルーピング、精度の詳細でイベントを拡充してください。これらのメソッドで設定された属性は、Singularのレポートおよび後続のポストバックに反映されます。
| メソッド | 説明 |
|---|---|
withNetworkName(String networkName)
|
ネットワーク名を上書きします(デフォルトはコンストラクターに渡された広告プラットフォーム)。基盤のネットワークがメディエーションプラットフォームと異なるメディエーションで使用します。 |
withAdType(String adType)
|
広告フォーマット (例:
"Rewarded"
、
"Interstitial"
、
"Banner"
)。
|
withAdGroupType(String adGroupType)
|
メディエーションプラットフォームで定義された広告グループの分類。 |
withImpressionId(String impressionId)
|
インプレッションの一意の識別子で、重複排除と照合に使用されます。 |
withAdPlacementName(String adPlacementName)
|
人間が読めるプレースメント名 (例:
"level_complete"
)。
|
withAdUnitId(String adUnitId)
|
プラットフォーム固有の広告ユニット識別子 (例: AdMobの
"ca-app-pub-..."
)。
|
withAdUnitName(String adUnitName)
|
人間が読める広告ユニット名。 |
withAdGroupId(String adGroupId)
|
メディエーションプラットフォームの広告グループ識別子。 |
withAdGroupName(String adGroupName)
|
人間が読める広告グループ名。 |
withAdGroupPriority(String adGroupPriority)
|
メディエーションウォーターフォール内で広告グループに割り当てられた優先順位。 |
withPrecision(String precision)
|
プラットフォームがサポートしている場合の収益精度インジケーター (例:
"publisher_provided"
、
"estimated"
、
"exact"
)。
|
withPlacementId(String placementId)
|
プラットフォーム固有のプレースメント識別子。 |
withLimitDataSharing(boolean shouldLimitDataSharing)
|
この単一の広告イベントに対してグローバルなデータ共有制限を上書きします。例えば、ユーザーがパーソナライズド広告をオプトアウトした場合に使用します。 |
Kotlin使用例:
val data = SingularAdData("AdMob", "USD", 0.05)
.withAdUnitId("ca-app-pub-123456789/1234567890")
.withAdType("Rewarded")
.withAdPlacementName("level_complete")
.withImpressionId("imp_abc123")
.withPrecision("publisher_provided")
Singular.adRevenue(data)
Java使用例:
SingularAdData data = new SingularAdData("AdMob", "USD", 0.05)
.withAdUnitId("ca-app-pub-123456789/1234567890")
.withAdType("Rewarded")
.withAdPlacementName("level_complete")
.withImpressionId("imp_abc123")
.withPrecision("publisher_provided");
Singular.adRevenue(data);
テストと検証
収益レポートの検証
Singularへデータが正しく流れていることを確認するため、広告収益の実装をテストしてください。
- ログの確認: 収益コールバックのログが正しい値と通貨で表示されることを確認してください。
- 広告テスト: テスト広告をロードして表示し、収益イベントをトリガーしてください。
- ダッシュボード検証: 24時間以内にSingularダッシュボードに収益が表示されることを確認してください。
- データの正確性: 収益額がメディエーションプラットフォームのレポートと一致することを検証してください。
トラブルシューティング: Singularに収益が表示されない場合は、次を確認してください:
- Singularアカウントで広告収益アトリビューションが有効化されているか
- 収益値が0より大きいか
- 通貨コードが有効なISO 4217コードであるか
- プラットフォーム名がSingularの想定するフォーマットと一致するか