배너 및 전면 광고에 대한 맞춤 이벤트

이 가이드는AdMob 미디에이션을 사용하여 다음 작업을 실행하려는 게시자를 대상으로 작성되었습니다.

  • AdMob UI에서 직접 지원되지 않는 네트워크에 광고 표시
  • 광고 대신 맞춤 보기 표시

맞춤 이벤트를 사용하면 맞춤 미디에이션 어댑터를 작성해 뷰를 광고 공간에 배치할 수 있습니다. 이 가이드에서는 Google에서 개발한 샘플 SDK에서 광고를 요청하기 위해 맞춤 이벤트를 작성하는 방법을 알아보겠습니다. 맞춤 이벤트에 대한 모든 자료 및 해당 샘플 SDK는 GitHub에서 찾을 수 있습니다.

기본 요건

배너 또는 전면 광고에 맞춤 이벤트를 통합하려면 먼저 해당 광고 형식을 앱에 통합해야 합니다. 다음은 관련 가이드입니다.

다음 예에서는 먼저 AdMob 미디에이션 내에서 배너 맞춤 이벤트를 만듭니다. 이 배너 맞춤 이벤트를 만들려면 AdMob UI를 통해 앱에서 해당 특정 클래스를 가리키는 맞춤 이벤트를 정의한 다음 CustomEventBanner를 구현하여 뷰를 제공해야 합니다. 이 예에서는 맞춤 이벤트를 정의하여 샘플 광고 네트워크에 광고를 게시합니다.

맞춤 이벤트 정의

AdMob UI에서 맞춤 이벤트를 정의해야 합니다. 이 안내에 따라 맞춤 이벤트를 만드세요.

다음은 샘플 맞춤 이벤트 설정을 보여주는 스크린샷입니다.

배너 요청

배너 광고를 요청하려면 CustomEventBanner를 구현하는 클래스를 정의하고 SampleCustomEventBanner라고 지정합니다. 광고 미디에이션 과정에서 맞춤 이벤트가 선택되면 설정에서 제공한 클래스 이름에 대해 requestBannerAd() 메서드가 호출됩니다.

위에서 정의한 선택적 매개변수는 requestBannerAd() 메서드의 일부로 맞춤 이벤트에 전달됩니다. 일반적으로 이 매개변수는 맞춤 이벤트에 로드할 광고를 결정해주는 식별자입니다.

필요에 따라 수명 주기 메서드도 구현해야 합니다. 사용자가 AdView.pause(), AdView.resume(), 메서드를 호출하면 AdMob 미디에이션이 어댑터 onPause()onResume() 활동 이벤트를 전달합니다. 샘플 광고 네트워크에는 일시중지 또는 호출 재개가 포함되지 않으므로 비어있는 구현을 제공합니다. 어댑터가 폐기되려는 경우 미디에이션에서는 onDestroy() 호출을 시도합니다. 여기에서 필요한 정리를 실행하세요.

다음은 SampleCustomEventBanner 구현의 예입니다.

자바

public class SampleCustomEventBanner implements CustomEventBanner {

    /** The SampleAdView representing a banner ad. */
    private SampleAdView sampleAdView;

    /** The event is being destroyed. Perform any necessary cleanup here. */
    @Override
    public void onDestroy() {
        if (sampleAdView != null) {
            sampleAdView.destroy();
        }
    }

    /**
     * The app is being paused. This call is only forwarded to the adapter if
     * the developer notifies AdMob mediation that
     * the app is being paused.
     */
    @Override
    public void onPause() {
        // The sample ad network doesn't have an onPause method, so does nothing.
    }

    /**
     * The app is being resumed. This call is only forwarded to the
     * adapter if the developer notifies AdMob
     * mediation that the app is being resumed.
     */
    @Override
    public void onResume() {
        // The sample ad network doesn't have an onResume method, so does nothing.
    }

    @Override
    public void requestBannerAd(Context context,
            CustomEventBannerListener listener,
            String serverParameter,
            AdSize size,
            MediationAdRequest mediationAdRequest,
            Bundle customEventExtras) {

        sampleAdView = new SampleAdView(context);

        // Assumes that the serverParameter is the AdUnit for the Sample Network.
        sampleAdView.setAdUnit(serverParameter);

        sampleAdView.setSize(new SampleAdSize(size.getWidth(), size.getHeight()));

        // Implement a SampleAdListener and forward callbacks to AdMob.
        // The callback forwarding is handled by SampleBannerEventFowarder.
        sampleAdView.setAdListener(new SampleCustomBannerEventForwarder(listener, sampleAdView));

        // Make an ad request.
        sampleAdView.fetchAd(createSampleRequest(mediationAdRequest));

        }

    private SampleAdRequest createSampleRequest(MediationAdRequest mediationAdRequest) {
        SampleAdRequest request = new SampleAdRequest();
        request.setTestMode(mediationAdRequest.isTesting());
        request.setKeywords(mediationAdRequest.getKeywords());
        return request;
        }
}

Kotlin

class SampleCustomEventBanner : CustomEventBanner {

    /** The SampleAdView representing a banner ad. */
    private lateinit var mSampleAdView: SampleAdView

    /** The event is being destroyed. Perform any necessary cleanup here. */
    override fun onDestroy() {
        mSampleAdView.destroy()
    }

    /**
     * The app is being paused. This call is only forwarded to the adapter if
     * the developer notifies AdMob mediation that
     * the app is being paused.
     */
    override fun onPause() {
        // The sample ad network doesn't have an onPause method, so does nothing.
    }

    /**
     * The app is being resumed. This call is only forwarded to the
     * adapter if the developer notifies AdMob
     * mediation that the app is being resumed.
     */
    override fun onResume() {
        // The sample ad network doesn't have an onResume method, so does nothing.
    }

    override fun requestBannerAd(context: Context,
                                 listener: CustomEventBannerListener,
                                 serverParameter: String,
                                 size: AdSize,
                                 mediationAdRequest: MediationAdRequest,
                                 customEventExtras: Bundle?) {

        mSampleAdView = SampleAdView(context)

        // Assumes that the serverParameter is the AdUnit for the Sample Network.
        mSampleAdView.adUnit = serverParameter
        mSampleAdView.size = SampleAdSize(size.width, size.height)

        // Implement a SampleAdListener and forward callbacks to
        // AdMob mediation. The callback forwarding
        // is handled by SampleBannerEventFowarder.
        mSampleAdView.adListener = SampleCustomBannerEventForwarder(listener, mSampleAdView)

        // Make an ad request.
        mSampleAdView.fetchAd(createSampleRequest(mediationAdRequest))
    }

    private fun createSampleRequest(mediationAdRequest: MediationAdRequest): SampleAdRequest {
        val request = SampleAdRequest()
        request.testMode = mediationAdRequest.isTesting
        request.keywords = mediationAdRequest.keywords
        return request
    }
}

샘플에 사용된 SampleAdView 클래스는 샘플 SDK의 간단한 타사 광고 보기 예입니다.

맞춤 이벤트 요청을 위한 광고 네트워크 추가 전송(선택사항)

맞춤 이벤트에 추가 매개변수를 전송해야 하는 경우 AdRequest.Builder 클래스의 addCustomEventExtrasBundle() 메서드를 사용하세요. 맞춤 이벤트 어댑터 클래스 및 맞춤 이벤트 어댑터에서 예상되는 추가 번들을 전달해야 합니다.

다음은 앞에서 정의한 SampleCustomEventBanner 클래스의 SampleExtra 매개변수를 전달하는 방법을 보여주는 코드 스니펫입니다.

Bundle extras = new Bundle();
extras.putBoolean("SampleExtra", true);

AdRequest request = new AdRequest.Builder()
        .addCustomEventExtrasBundle(SampleCustomEventBanner.class, extras)
        .build();

올바른 맞춤 이벤트 클래스 및 맞춤 이벤트 요청 번들로 addCustomEventExtras()를 호출하지 않으면 어댑터가 수신한 bundle 매개변수는 null이 됩니다.

AdMob 미디에이션 알림

맞춤 이벤트가 광고를 로드하거나 로드하지 못한 경우 CustomEventBannerListener 인터페이스를 통해 미디에이션에 알려야 합니다. 미디에이션에 알리지 못하면 맞춤 이벤트 시간이 초과되고 다음 네트워크로 광고 미디에이션이 진행됩니다.

네트워크에 광고 리스너를 구현하고 CustomEventBannerListener에서 관련 콜백을 호출하여 AdMob미디에이션으로 메시지를 돌려 보냅니다.

샘플 광고 네트워크로부터 수신한 콜백을 전달하기 위해 SampleAdListener 인터페이스를 구현하는 SampleCustomBannerEventForwarder 클래스가 생성되었습니다.

AdMob 미디에이션에서는 다음과 같은 콜백을 지원합니다.

메서드 호출 시점
onAdLoaded() 배너 요청에 성공한 경우
onAdFailedToLoad() 배너 요청에 실패한 경우
onAdClicked() 배너를 클릭한 경우
onAdOpened() 배너가 전체 화면 보기로 렌더링된 경우
onAdClosed() 사용자가 배너를 클릭한 후 앱으로 돌아가는 경우
onAdLeftApplication() 배너로 인해 사용자가 앱을 떠난 경우

전면 광고

메서드 호출 시점
onAdLoaded() 전면 광고 요청에 성공한 경우
onAdFailedToLoad() 전면 광고 요청에 실패한 경우
onAdClicked() 전면 광고를 클릭한 경우
onAdOpened() 전면 광고가 전체 화면 보기로 렌더링된 경우
onAdClosed() 전면 광고가 닫힌 경우
onAdLeftApplication() 전면 광고로 인해 사용자가 앱을 떠난 경우

다음은 SampleCustomBannerEventForwarder 구현 예입니다.

자바

public class SampleCustomBannerEventForwarder extends SampleAdListener {
    private CustomEventBannerListener mBannerListener;
    private SampleAdView mAdView;

    /**
     * Creates a new {@code SampleBannerEventForwarder}.
     * @param listener A {@link CustomEventBannerListener} that should receive
     *                 forwarded events.
     * @param adView   A {@link SampleAdView}.
     */
    public SampleCustomBannerEventForwarder(
            CustomEventBannerListener listener, SampleAdView adView) {
        this.mBannerListener = listener;
        this.mAdView = adView;
    }

    @Override
    public void onAdFetchSucceeded() {
        mBannerListener.onAdLoaded(mAdView);
    }

    @Override
    public void onAdFetchFailed(SampleErrorCode errorCode) {
        switch (errorCode) {
            case UNKNOWN:
                mBannerListener.onAdFailedToLoad(AdRequest.ERROR_CODE_INTERNAL_ERROR);
                break;
            case BAD_REQUEST:
                mBannerListener.onAdFailedToLoad(AdRequest.ERROR_CODE_INVALID_REQUEST);
                break;
            case NETWORK_ERROR:
                mBannerListener.onAdFailedToLoad(AdRequest.ERROR_CODE_NETWORK_ERROR);
                break;
            case NO_INVENTORY:
                mBannerListener.onAdFailedToLoad(AdRequest.ERROR_CODE_NO_FILL);
                break;
        }
    }

    @Override
    public void onAdFullScreen() {
        mBannerListener.onAdClicked();
        mBannerListener.onAdOpened();
        // Only call onAdLeftApplication if your ad network actually exits the developer's app.
        mBannerListener.onAdLeftApplication();
    }

    @Override
    public void onAdClosed() {
        mBannerListener.onAdClosed();
    }
}

Kotlin

class SampleCustomBannerEventForwarder(private val mBannerListener: CustomEventBannerListener,
                                       private val mAdView: SampleAdView) : SampleAdListener() {

    override fun onAdFetchSucceeded() {
        mBannerListener.onAdLoaded(mAdView)
    }

    override fun onAdFetchFailed(errorCode: SampleErrorCode) {
        when (errorCode) {
            UNKNOWN -> mBannerListener.onAdFailedToLoad(AdRequest.ERROR_CODE_INTERNAL_ERROR)
            BAD_REQUEST -> mBannerListener.onAdFailedToLoad(AdRequest.ERROR_CODE_INVALID_REQUEST)
            NETWORK_ERROR -> mBannerListener.onAdFailedToLoad(AdRequest.ERROR_CODE_NETWORK_ERROR)
            NO_INVENTORY -> mBannerListener.onAdFailedToLoad(AdRequest.ERROR_CODE_NO_FILL)
        }
    }

    override fun onAdFullScreen() {
        mBannerListener.onAdClicked()
        mBannerListener.onAdOpened()
        // Only call onAdLeftApplication if your ad network actually exits the developer's app.
        mBannerListener.onAdLeftApplication()
    }

    override fun onAdClosed() {
        mBannerListener.onAdClosed()
    }
}

전면 광고 맞춤 이벤트

전면 광고 맞춤 이벤트를 구현하려면 먼저 배너 맞춤 이벤트처럼 AdMob 미디에이션 내에 전면 광고 맞춤 이벤트를 만듭니다. 그런 다음 CustomEventInterstitial을 구현하여 알림을 발송합니다. 이 예에서는 앞에서와 같이 샘플 광고 네트워크를 사용합니다.

맞춤 이벤트 정의

AdMob UI를 통해 전면 광고 맞춤 이벤트를 정의할 수 있습니다.

클래스 이름에 지정한 값의 전체 경로가 있는지 확인합니다. 매개변수에는 맞춤 이벤트에서 구현 중인 네트워크에 광고를 요청하는 데 필요한 정보가 포함되어야 합니다.

전면 광고 요청

전면 광고를 요청하려면 CustomEventInterstitial을 구현하는 클래스를 정의합니다. 이 클래스를 SampleCustomEventInterstitial이라고 지정합니다. 미디에이션 과정에서 맞춤 이벤트가 선택되면 미디에이션에서 설정에서 제공한 클래스 이름에 대해 requestInterstitialAd() 메서드를 호출합니다. 이 메서드에 제공된 매개변수를 사용하여 원하는 네트워크에 전면 광고를 요청할 수 있습니다. 다음 예에서는 맞춤 이벤트를 통해 샘플 광고 네트워크에 전면 광고를 요청하는 방법을 보여줍니다.

다음은 SampleCustomEventInterstitial 구현 예입니다.

자바

public class SampleCustomEventInterstitial implements CustomEventInterstitial {

    /** Represents a SampleInterstitial. */
    private SampleInterstitial sampleInterstitial;

    @Override
    public void requestInterstitialAd(Context context,
            CustomEventInterstitialListener listener,
            String serverParameter,
            MediationAdRequest mediationAdRequest,
            Bundle customEventExtras) {
        /**
         * In this method, you should:
         * 1. Create your interstitial ad.
         * 2. Set your ad network's listener.
         * 3. Make an ad request.
         */

        sampleInterstitial = new SampleInterstitial(context);

        // Here we're assuming the serverParameter is the ad unit for the sample ad network.
        sampleInterstitial.setAdUnit(serverParameter);

        // Implement a SampleAdListener and forward callbacks to
        // AdMob.
        sampleInterstitial.setAdListener(new SampleCustomInterstitialEventForwarder(listener));

        // Make an ad request.
        sampleInterstitial.fetchAd(createSampleRequest(mediationAdRequest));
    }

    /**
     * Helper method to create a SampleAdRequest.
     * @param mediationAdRequest The mediation request with targeting information.
     * @return The created SampleAdRequest.
     */
    private SampleAdRequest createSampleRequest(MediationAdRequest mediationAdRequest) {
        SampleAdRequest request = new SampleAdRequest();
        request.setTestMode(mediationAdRequest.isTesting());
        request.setKeywords(mediationAdRequest.getKeywords());
        return request;
    }

    @Override
    public void showInterstitial() {
        // Show your interstitial ad.
        sampleInterstitial.show();
    }

    /** The event is being destroyed. Perform any necessary cleanup here. */
    @Override
    public void onDestroy() {
        if (sampleInterstitial != null) {
            sampleInterstitial.destroy();
        }
    }

    /**
     * The app is being paused. This call is only forwarded to the adapter if
     * the developer notifies AdMob mediation
     * that the app is being paused.
     */
    @Override
    public void onPause() {
        // The sample ad network doesn't have an onPause method, so does nothing.
    }

    /**
     * The app is being resumed. This call is only forwarded to the
     * adapter if the developer notifies AdMob
     * mediation that the app is being resumed.
     */
    @Override
    public void onResume() {
        // The sample ad network doesn't have an onResume method, so does nothing.
    }
}

Kotlin

class SampleCustomEventInterstitial : CustomEventInterstitial {

    /** Represents a SampleInterstitial.  */
    private lateinit var mSampleInterstitial: SampleInterstitial

    override fun requestInterstitialAd(context: Context,
                                       listener: CustomEventInterstitialListener,
                                       serverParameter: String,
                                       mediationAdRequest: MediationAdRequest,
                                       customEventExtras: Bundle?) {
        /**
         * In this method, you should:
         * 1. Create your interstitial ad.
         * 2. Set your ad network's listener.
         * 3. Make an ad request.
         */

        mSampleInterstitial = SampleInterstitial(context)

        // Here we're assuming the serverParameter is the ad unit for the sample ad network.
        mSampleInterstitial.adUnit = serverParameter

        // Implement a SampleAdListener and forward callbacks to
        // AdMob mediation.
        mSampleInterstitial.adListener = SampleCustomInterstitialEventForwarder(listener)

        // Make an ad request.
        mSampleInterstitial.fetchAd(createSampleRequest(mediationAdRequest))
    }

    /**
     * Helper method to create a [SampleAdRequest].
     * @param mediationAdRequest The mediation request with targeting information.
     * *
     * @return The created [SampleAdRequest].
     */
    private fun createSampleRequest(mediationAdRequest: MediationAdRequest): SampleAdRequest {
        val request = SampleAdRequest()
        request.testMode = mediationAdRequest.isTesting
        request.keywords = mediationAdRequest.keywords
        return request
    }

    override fun showInterstitial() {
        // Show your interstitial ad.
        mSampleInterstitial.show()
    }

    /** The event is being destroyed. Perform any necessary cleanup here. */
    override fun onDestroy() {
        mSampleInterstitial.destroy()
    }

    /**
     * The app is being paused. This call is only forwarded to the adapter if
     * the developer notifies AdMob mediation that
     * the app is being paused.
     */
    override fun onPause() {
        // The sample ad network doesn't have an onPause method, so does nothing.
    }

    /**
     * The app is being resumed. This call is only forwarded to the adapter if
     * the developer notifies AdMob mediation that
     * the app is being resumed.
     */
    override fun onResume() {
        // The sample ad network doesn't have an onResume method, so does nothing.
    }
}

전면 광고 맞춤 이벤트 인터페이스는 showInterstitial() 메서드를 구현해야 합니다. 미디에이션에서 이 메서드를 실행하여 Google 모바일 광고 SDK를 통해 전면 광고를 게재합니다.

맞춤 이벤트 요청을 위한 광고 네트워크 추가 전송(선택사항)

맞춤 이벤트에 추가 매개변수를 전송해야 하는 경우 AdRequest.Builder 클래스의 addCustomEventExtrasBundle() 메서드를 사용하세요. 맞춤 이벤트 어댑터에서 예상되는 맞춤 이벤트 어댑터 클래스 및 추가 번들을 전달해야 합니다.

다음은 앞에서 정의한 SampleCustomEventInterstitial 클래스의 'SampleExtra' 매개변수를 전달하는 방법을 보여주는 코드 스니펫입니다.

Bundle extras = new Bundle();
extras.putBoolean("SampleExtra", true);

AdRequest request = new AdRequest.Builder()
        .addCustomEventExtrasBundle(SampleCustomEventInterstitial.class, extras)
        .build();

올바른 맞춤 이벤트 클래스 및 맞춤 이벤트 요청 번들로 addCustomEventExtrasBundle()을 호출하지 않으면 어댑터가 수신한 bundle 매개변수는 null이 됩니다.

AdMob 미디에이션 알림

배너 맞춤 이벤트 예와 마찬가지로 네트워크의 광고 리스너를 구현하여 AdMob 미디에이션에 메시지를 돌려 보냅니다.

SampleCustomInterstitialEventForwarder 클래스 예시에서 SampleAdListener 인터페이스를 구현하여 샘플 광고 네트워크로부터 수신한 콜백을 전달합니다.

자바

public class SampleCustomInterstitialEventForwarder extends SampleAdListener {
    private CustomEventInterstitialListener mInterstitialListener;

    /**
     * Creates a new SampleInterstitialEventForwarder.
     * @param listener An AdMob CustomEventInterstitialListener that should
     *                 receive forwarded events.
     */
    public SampleCustomInterstitialEventForwarder(CustomEventInterstitialListener listener) {
        this.mInterstitialListener = listener;
    }

    @Override
    public void onAdFetchSucceeded() {
        mInterstitialListener.onAdLoaded();
    }

    @Override
    public void onAdFetchFailed(SampleErrorCode errorCode) {
        switch (errorCode) {
            case UNKNOWN:
                mInterstitialListener.onAdFailedToLoad(AdRequest.ERROR_CODE_INTERNAL_ERROR);
                break;
            case BAD_REQUEST:
                mInterstitialListener.onAdFailedToLoad(AdRequest.ERROR_CODE_INVALID_REQUEST);
                break;
            case NETWORK_ERROR:
                mInterstitialListener.onAdFailedToLoad(AdRequest.ERROR_CODE_NETWORK_ERROR);
                break;
            case NO_INVENTORY:
                mInterstitialListener.onAdFailedToLoad(AdRequest.ERROR_CODE_NO_FILL);
                break;
        }
    }

    @Override
    public void onAdFullScreen() {
        mInterstitialListener.onAdOpened();
        // Only call onAdLeftApplication if your ad network actually exits the developer's app.
        mInterstitialListener.onAdLeftApplication();
    }

    @Override
    public void onAdClosed() {
        mInterstitialListener.onAdClosed();
    }
}

Kotlin

class SampleCustomInterstitialEventForwarder(private val mInterstitialListener: CustomEventInterstitialListener)
        : SampleAdListener() {

    override fun onAdFetchSucceeded() {
        mInterstitialListener.onAdLoaded()
    }

    override fun onAdFetchFailed(errorCode: SampleErrorCode) {
        when (errorCode) {
            UNKNOWN -> mInterstitialListener.onAdFailedToLoad(AdRequest.ERROR_CODE_INTERNAL_ERROR)
            BAD_REQUEST -> mInterstitialListener.onAdFailedToLoad(AdRequest.ERROR_CODE_INVALID_REQUEST)
            NETWORK_ERROR -> mInterstitialListener.onAdFailedToLoad(AdRequest.ERROR_CODE_NETWORK_ERROR)
            NO_INVENTORY -> mInterstitialListener.onAdFailedToLoad(AdRequest.ERROR_CODE_NO_FILL)
        }
    }

    override fun onAdFullScreen() {
        mInterstitialListener.onAdOpened()
        // Only call onAdLeftApplication if your ad network actually exits the developer's app.
        mInterstitialListener.onAdLeftApplication()
    }

    override fun onAdClosed() {
        mInterstitialListener.onAdClosed()
    }
}

전면 광고용 맞춤 이벤트 구현이 완료되었습니다. 전체 예시는 on GitHub에서 확인할 수 있습니다. 이미 지원되는 광고 네트워크에 예시를 사용하거나 예시를 수정하여 맞춤 전면 광고를 게재할 수도 있습니다.