Android SDK - 広告収益トラッキング

広告収益アトリビューション

メディエーションプラットフォームからの広告収益をトラッキングし、ユーザーを獲得したマーケティングキャンペーンに紐付けることで、キャンペーンコスト、アプリ内課金、広告マネタイズ全体にわたる完全なROIの可視化を実現します。

概要

広告収益アトリビューションとは

広告収益アトリビューションは、モバイルアプリの広告収益とアプリインストールを促進したユーザー獲得キャンペーンを結びつけ、広告マネタイズを含む真のキャンペーン収益性を測定することを可能にします。

主なメリット:

  • 統合ROIビュー: キャンペーンコスト、アプリ内収益、広告収益を1つのダッシュボードで確認
  • キャンペーン最適化: 広告収益データを広告ネットワークに送り返し、入札とターゲティングを改善
  • LTV測定: 広告マネタイズを含む完全なユーザーライフタイムバリューを算出

データソース: 広告収益データは通常、メディエーションプラットフォーム(例: AdMob、AppLovin MAX、IronSource)からユーザー単位またはインプレッション単位で提供されます。Singularは、このデータを受信するための複数の連携方法をサポートしています。

詳細はこちら: セットアップ、レポート、トラブルシューティングの詳細については、 広告収益アトリビューションFAQ をご参照ください。


実装要件

重要なガイドライン

必須のSingularAdDataパラメーター: コンストラクター引数 adPlatform currency revenue はすべて必須です。いずれかが欠落、空、または無効な場合、SDKは例外を発生させたりエラーを返したりせずに Singular.adRevenue() の呼び出しを暗黙的に破棄します。 Singular.adRevenue() はSDKがまだ初期化されていない場合にも暗黙的にスキップされるため、呼び出し前に必ず Singular.init() が実行されていることを確認してください。

データの正確性が重要です:

  1. 通貨コード: 3文字のISO 4217通貨コード(例: USD、EUR、INR)を使用してください。多くのメディエーションプラットフォームはUSDで報告するため、実装前にプラットフォームの通貨を確認してください。
  2. 送信前の検証: Singular.adRevenue() を呼び出す前に、必ず収益と通貨データを検証してください。誤ったデータは送信後に修正できません。
  3. プラットフォーム間の違い: 一部のSDKは収益をmicros単位で報告し(1,000,000で除算が必要)、他のSDKは標準通貨単位で報告します。各プラットフォームのドキュメントを確認してください。

セットアップ手順

広告収益アトリビューションを実装するには、次の手順に従ってください:

  1. SDKの更新: 最新のSingular SDKバージョンを使用していることを確認してください。
  2. 連携方法の選択: ご利用の環境に合致するメディエーションプラットフォーム連携を以下から選択してください。
  3. コールバックの実装: 収益データを取得するためのプラットフォーム固有の有料イベントリスナーを追加してください。
  4. データの検証: 収益レポートをテストし、Singularダッシュボードにデータが表示されることを確認してください。

プラットフォーム連携

AdMob連携

インプレッション単位の収益レポートのために有料イベントリスナーを使用して、Google AdMobの広告収益をトラッキングします。

要件:

プラットフォーム別の収益レポート: AdMobはプラットフォームごとに収益の報告方法が異なります。Androidは収益をmicros単位(例: $0.005 = 5000)で返します。Singularに送信する前に adValue.valueMicros を1,000,000で除算して標準通貨単位に変換してください。

実装

広告のロード時に有料イベントリスナーを設定し、収益データを取得してSingularに送信します。

Kotlin Java
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}")
                }
            })
    }
}

AppLovin MAX連携

AppLovin Impression-Level User Revenue APIを使用して、インプレッション単位の広告収益を共有します。

要件:

実装

AppLovin Communicatorコールバックを通じて収益メッセージを処理します。

Kotlin Java
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")
        }
    }
}

Unity LevelPlay (IronSource)連携

IronSource SDKを使用して、ironSourceおよびメディエーションネットワークからのインプレッション単位の収益をトラッキングします。

要件:

  • ironSource SDKを実装 ( スタートガイド を参照)
  • IronSourceダッシュボードでARM SDK Postbacksフラグを有効化
  • 収益コールバックを受信するためのインプレッションデータリスナーを設定

詳細はこちら: セットアップの詳細については、 IronSource広告収益ドキュメント をご参照ください。

実装

インプレッションデータの成功コールバックを実装して、収益を取得し送信します。

Kotlin Java
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")
}

TradPlus連携

グローバルインプレッションリスナーを使用して、TradPlusメディエーションからの広告収益を取得します。

要件:

  • TradPlusSdk.setGlobalImpressionListener() 経由でグローバルインプレッションリスナーを設定
  • onImpressionSuccess コールバックを処理して収益データを受信
  • eCPMをミリ単位から標準通貨に変換 (1000で除算)

実装

すべての広告インプレッションと収益をトラッキングするためにグローバルインプレッションリスナーを登録します。

Kotlin Java
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")
        }
    }
)

汎用連携 (その他のプラットフォーム)

汎用 SingularAdData インターフェースを使用して、任意のメディエーションプラットフォームを連携できます。

要件:

  • メディエーションプラットフォームからのインプレッション単位の収益データへのアクセス
  • 標準通貨単位(microsではない)の収益額
  • ISO 4217通貨コード (例: USD、EUR、INR)

データの正確性: Singularに送信する前に収益と通貨データを検証してください。誤ったデータは送信後に修正できません。

実装

プラットフォーム名、通貨、収益を指定して SingularAdData オブジェクトを作成し、 Singular.adRevenue() を呼び出します。

Kotlin Java
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)

追加属性で広告データを拡充する

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へデータが正しく流れていることを確認するため、広告収益の実装をテストしてください。

  1. ログの確認: 収益コールバックのログが正しい値と通貨で表示されることを確認してください。
  2. 広告テスト: テスト広告をロードして表示し、収益イベントをトリガーしてください。
  3. ダッシュボード検証: 24時間以内にSingularダッシュボードに収益が表示されることを確認してください。
  4. データの正確性: 収益額がメディエーションプラットフォームのレポートと一致することを検証してください。

トラブルシューティング: Singularに収益が表示されない場合は、次を確認してください:

  • Singularアカウントで広告収益アトリビューションが有効化されているか
  • 収益値が0より大きいか
  • 通貨コードが有効なISO 4217コードであるか
  • プラットフォーム名がSingularの想定するフォーマットと一致するか