Andrioidアプリ広告におけるメディエーション機能について

はじめに

ジモティーでAndroidとiOSの開発をしている3年目の坂本です。

最近はマユリカというお笑いコンビのマユリカのうなげろりん!!というラジオを聴くのにハマっています。

特に#36の回、めちゃくちゃ笑いました。ポッドキャストで聴けるので気になった方はぜひ!

さて、今回はジモティーAdsについて書きたいと思います。

ジモティーAdsについて

2023年11月にジモティーAdsをリリースしました🎉

ジモティー独自のデータを活用することで、より高い広告効果の提供を目指しています。

ジモティーアプリで今まで表示していたAdMob広告とジモティーAdsを共存させるために、AdMobのメディエーション機能を採用しています。

メディエーションについて

メディエーションについて、以下のように紹介されています。

メディエーションは、アプリでの広告配信に使用する広告ソースを 1 か所で管理できる機能です。
メディエーションを使用すると、届いた広告リクエストを複数の広告ソースに送信し、使用可能かつ最適な広告ソースを確実に見つけて広告を掲載できます。

つまり、AdMobにリクエストを投げたらいろんな広告ソースの中から最適な広告を返してくれるので、広告掲載率と収益を向上が期待できるというわけです。

その最適な広告ソースの選ばれ方は以下の2種類あります。

  • 入札
  • ウォーターフォール

入札

入札は、リクエストを受け取るとリアルタイムで入札オークションが行われ、見事オークションを落札した広告が選ばれるみたいです。

ウォーターフォール

ウォーターフォールは、リクエストを受けると全ての広告のeCPMが再計算され、最上位のネットワークから順に紹介が行われ、リクエストに一致する広告があれば配信されます。

以下の例だと、eCPMが4ドルのネットワークDが選ばれ、リクエストに一致した広告があればネットワークDが配信されます。

一致する広告がなければ、次に高い3ドルのAdMobネットワークの広告が配信されます。

メディエーションにジモティーAdsを組み込む

今回はその中にジモティーAdsを組み込みます。

ジモティーAds単体だと3.5$ですが、メディエーション機能を使うことでネットワークDの4$の広告を表示できるようになります。

https://support.google.com/admob/answer/13420272?hl=ja

実装

カスタムイベントを作成

まずはカスタムイベントを管理画面で作成します。(詳しくはこちらJmtyCustomEventなどカスタムイベントアダプタを実装するクラスの名前を決めます。

そのクラスの完全修飾名を管理画面のClass Nameに設定します。 → 例: com.google.ads.mediation.sample.customevent.HogeHogeCustomEvent

アダプターを初期化する

Google Mobile Ads SDK が初期化されると、アプリ用に設定されたすべてのサードパーティ製アダプタとカスタムイベントに対してinitialize()が呼び出されるそうです。

今回作成したJmtyCustomEventでもinitialize()メソッドが走るので、初期化完了のメソッドを呼び出します。

class JmtyCustomEvent : Adapter() {

    override fun initialize(
        context: Context,
        initializationCompleteCallback: InitializationCompleteCallback,
        mediationConfigurations: MutableList<MediationConfiguration>,
    ) {
        Log.d(TAG, "initialize: JmtyAdsMediation")
        initializationCompleteCallback.onInitializationSucceeded()
    }
}

バージョン番号の報告

カスタムイベントを作成したら、カスタムイベントアダプタ自体のバージョンと、サードパーティSDKのバージョンの両方をGoogle Mobile Ads SDKに報告する必要があります。

今回ジモティーAdsの部分はSDK化していないため1.0.0にしています。

具体的な実装は省略しますが、気になる方は以下のドキュメントに実装コードがありますのでご確認ください。 https://developers.google.com/admob/android/custom-events/setup#report_version_numbers

リクエスト

今まで通りロードメソッドを呼ぶ

リクエストの仕方は今まで通りのloadAdメソッドを呼ぶだけです。

        adView.loadAd(request)

例えば以下のようなウォーターフォールの順番の場合、ネットワークDの広告があればそれがAdViewとして表示され、JmtyCustomEventは起動しません。

ネットワークDがない場合、ジモティーAdsが選ばれJmtyCustomEventloadBannerAdメソッドが呼び出されます。

class JmtyCustomEvent : Adapter() {

    private lateinit var bannerLoader: JmtyCustomEventLoader

    override fun initialize(
        context: Context,
        initializationCompleteCallback: InitializationCompleteCallback,
        mediationConfigurations: MutableList<MediationConfiguration>,
    ) {
        Log.d(TAG, "initialize: JmtyAdsMediation")
        initializationCompleteCallback.onInitializationSucceeded()
    }

    override fun loadBannerAd(
        adConfiguration: MediationBannerAdConfiguration,
        callback: MediationAdLoadCallback<MediationBannerAd, MediationBannerAdCallback>,
    ) {
        bannerLoader = JmtyCustomEventLoader(adConfiguration, callback)
        bannerLoader.loadAd()
    }
}

JmtyCustomEventLoaderでは、実際にジモティーAdsのサーバーに広告のリクエストを行います。

class JmtyCustomEventLoader(
    private val mediationBannerAdConfiguration: MediationBannerAdConfiguration,
    private val mediationAdLoadCallback: MediationAdLoadCallback<MediationBannerAd, MediationBannerAdCallback>,
) : JmtyAdListener, MediationBannerAd {

    private lateinit var adView: JmtyAdView

    fun loadAd() {
         // ジモティーAdsのリクエスト
         // Viewの生成
    }

    override fun getView(): View {
        return adView.getView()
    }
}

リクエスト時のパラメータ

ジモティーAdsのリクエスト時にパラメータを渡したいが、リクエスト時にはJmtyCustomEventのアダプターに直接渡すことができません。

この解決策としてAdRequest.addNetworkExtrasBundleを使います。

リクエストする箇所で、Bundleに値を詰めてアダプタークラスを指定してAdRequestに渡します。

        val jmtyAdRequestBundle = Bundle().apply {
                putInt("id", 1)
        }
        val request = AdRequest.Builder()
                .addNetworkExtrasBundle(
                    JmtyCustomEvent::class.java,
                    jmtyAdRequestBundle,
                )
                .build()
        adView.loadAd(request)

指定したJmtyCustomEventのアダプターのMediationBannerAdConfiguration.mediationExtrasから取り出すことができます。

class JmtyCustomEventLoader(
    private val mediationBannerAdConfiguration: MediationBannerAdConfiguration,
    private val mediationAdLoadCallback: MediationAdLoadCallback<MediationBannerAd, MediationBannerAdCallback>,
) : JmtyAdListener, MediationBannerAd {
    fun loadAd() {
        val id = mediationBannerAdConfiguration.mediationExtras.getInt("id", -1)
    }
}

ジモティーAdsがない場合

mediationAdLoadCallback.onFailureを呼び出します。

class JmtyCustomEventLoader(
    private val mediationBannerAdConfiguration: MediationBannerAdConfiguration,
    private val mediationAdLoadCallback: MediationAdLoadCallback<MediationBannerAd, MediationBannerAdCallback>,
) : JmtyAdListener, MediationBannerAd {

    private lateinit var adView: JmtyAdView

    fun loadAd() {
         // ジモティーAdsのリクエスト

        // 広告がない時
        val adError = AdError(JmtyAdErrorCode.NO_FILL.errorCode, code.getErrorMessage(), ERROR_DOMAIN)
        mediationAdLoadCallback.onFailure(adError)
        return
    }
}

ジモティーAdsがなかったことが通知され、次のネットワークへリクエストが移り、AdMobネットワークがあればその広告がAdViewで表示されます。

Viewの生成

サーバーから受け取った広告の情報を使ってViewを作成しています。

作成したViewはMediationBannerAdgetView()メソッドに渡します。これでAdViewでジモティーAdsを表示できるようになります。

class JmtyCustomEventLoader(
    private val mediationBannerAdConfiguration: MediationBannerAdConfiguration,
    private val mediationAdLoadCallback: MediationAdLoadCallback<MediationBannerAd, MediationBannerAdCallback>,
) : JmtyAdListener, MediationBannerAd {

    private lateinit var adView: JmtyAdView

    fun loadAd() {
         // ジモティーAdsのリクエスト
         // Viewの生成
    }

    override fun getView(): View {
        return adView.getView()
    }
}

最後に

今回はリリースしたジモティーAdsをAdMobメディエーションに組み込んだ経緯やその方法について紹介させていただきました。

今後はジモティーAdsのCPMをあげていって配信比率を増やしていけるように、改善していければなと思います。


弊社では一緒にプロダクトを改善していただける仲間を探しています!

こちらでお気軽にお声がけください!

ネイティブアプリエンジニアの採用って難しいですよね。。。

ジモティーのウェブチームについてお話ししたいです