This guide is intended for ad networks looking to build a bidding adapter
in order to participate in real-time bidding (RTB) within Google mediation. If you
are a publisher, see the [publisher mediation](https://developers.google.com/admob/android/mediation.md.txt)
instructions.

A bidding adapter is the client-side part of the integration. The adapter
enables your ad network SDK to communicate with Google Mobile Ads SDK (Legacy) to
load ads served by your bidder.

For bidding to work correctly your adapter will need to handle
initialization, collecting signals, loading ads, and relaying ad lifecycle
events. In this guide we will walk you through how your adapter should be
implemented to handle these operations.

> [!NOTE]
> **Note:** Participation in bidding also requires a bidder that can respond to OpenRTB requests. Instructions on how to stand up a bidder are outside the scope of this guide.

## Workflow of a bidding adapter

### Initialization

A detailed flow of the entire request-response-rendering lifecycle
of an adapter is shown below:

![](https://developers.google.com/static/admob/images/open_bidding_flow_android.png)

The adapter is responsible for the following portions of the workflow:

- Steps 4-7: Initialize your adapter and call back Google Mobile Ads SDK (Legacy)
  once initialization completes.

- Steps 10-13: Collect signals from your ad network SDK to be sent to your
  bidder to participate in an RTB request, and forward them to the Google Mobile
  Ads SDK.

- Steps 18-21: Should your bidder return the winning bid, load the ad according
  to the response from your bidder. Once loaded, notify Google Mobile Ads SDK (Legacy)
  that the ad was loaded.

- Step 23 and later: While your ad is displaying, notify the Google Mobile Ads
  SDK of impression and click events, as well as the other ad events that occur
  during the presentation lifecycle of your ad.

> [!NOTE]
> **Note:** Google Mobile Ads SDK (Legacy) separately tracks impression events, but it is also important that you forward your ad network's impression event so that we can check for discrepancies.

## Implementing the bidding adapter

To create a bidding adapter for Google Mobile Ads SDK (Legacy), you must extend the `RtbAdapter`
abstract class. The following sections explain each abstract method in
`RtbAdapter`.

### getSDKVersionInfo()

Here you should return your SDK's version. This version is passed to your
bidder as part of the OpenRTB request.

This method requires you to return a `VersionInfo`. The example below shows how
you might convert your SDK's string version into a `VersionInfo.`

    @Override
    public VersionInfo getSDKVersionInfo() {
      // Get your SDK's version as a string. E.g. "1.2.3"
      // String versionString = YourSdk.getVersion();
      String splits[] = versionString.split("\\.");
      if (splits.length >= 3) {
          int major = Integer.parseInt(splits[0]);
          int minor = Integer.parseInt(splits[1]);
          int micro = Integer.parseInt(splits[2]);
          return new VersionInfo(major, minor, micro);
       }

       String logMessage = String.format("Unexpected SDK version format: %s." +
               "Returning 0.0.0 for SDK version.", sdkVersion);
       Log.w(TAG, logMessage);
       return new VersionInfo(0, 0, 0);
    }

### getVersionInfo()

Here you should return your adapter's version. This version is passed to your
bidder as part of the OpenRTB request.

Google's [open source and versioned
adapters](https://developers.google.com/admob/android/mediation#open_source_and_versioned_adapters)
use a 4-digit adapter version scheme, but the `VersionInfo` only allows for 3
digits. To work around this, it is recommended to combine the last two digits
into the patch version, as shown below.

    @Override
    public VersionInfo getVersionInfo() {
      // Get your adapters's version as a string. E.g. "1.2.3.0"
      String versionString = BuildConfig.VERSION_NAME;
      String splits[] = versionString.split("\\.");
      if (splits.length >= 4) {
          int major = Integer.parseInt(splits[0]);
          int minor = Integer.parseInt(splits[1]);
          int micro = Integer.parseInt(splits[2]) * 100 + Integer.parseInt(splits[3]);
          return new VersionInfo(major, minor, micro);
        }

        String logMessage = String.format("Unexpected adapter version format: %s." +
                    "Returning 0.0.0 for adapter version.", versionString);
        Log.w(TAG, logMessage);
        return new VersionInfo(0, 0, 0);
    }

### initialize()

Timeout: 30 seconds

The `initialize()` method is the first method called in your adapter. It is
called only once per session. This method provides you with a list of
`MediationConfiguration` objects that represent the full list of
placements in this app that are configured for your ad network; You can loop
through this list to parse the credentials for each placement,
and pass relevant data to your SDK for initialization.

Once your SDK is initialized and is ready to receive ad requests, invoke the
`onInitializationSucceeded()` method of the `InitializationCompleteCallback`.
This callback is forwarded to the app publishers so that they can know they
can start loading ads.

> [!NOTE]
> **Note:** The `initialize()` method is called on a throwaway instance of an adapter. No other methods will be called on this particular instance. If your adapter needs to save state as a result of this method, any state should be static.

    @Override
    public void initialize(Context context,
        InitializationCompleteCallback initializationCompleteCallback,
        List<MediationConfiguration> mediationConfigurations) {
      // Initialize your ad network's SDK.
      ...

      // Invoke the InitializationCompleteCallback once initialization completes.
      initializationCompleteCallback.onInitializationSucceeded();
    }

### collectSignals()

Timeout: 1 second

Each time the publisher requests an ad, a new instance of your `RtbAdapter` is
created and the `collectSignals()` method is called. This instance of
`RtbAdapter` will be used for the duration of the ad request, response, and
rendering lifecycle for that ad. The `collectSignals()` method enables your
adapter to provide signals from the device to be sent to your bidder in an
OpenRTB request.

`collectSignals()` is called on a background thread. Google Mobile Ads SDK (Legacy)
simultaneously asks for signals from all adapters
participating in bidding. Please be respectful and limit calls to the UI thread
during this time. Any heavy work that your adapter or SDK needs to do to collect
signals should be done in the [`initialize()`](https://developers.google.com/admob/android/open-bidding-adapter.md.txt#initialize) method and cached.

Once you have your signals ready, call the `onSuccess()` callback with your
encoded signals.

Here's an example implementation:

    @Override
    public void collectSignals(RtbSignalData rtbSignalData,
                               SignalCallbacks signalCallbacks) {
      String signals = YourSdk.getSignals();
      signalCallbacks.onSuccess(signals);
    }

If your adapter fails to collect signals, call `signalCallbacks.onFailure()`
with a string explaining the error that occurred.

> [!NOTE]
> **Note:** The signals string could represent any object, and it could be in any format, such as plain JSON, Base64 encoded, or any other form of encryption you choose. Encrypting signals is recommended to ensure that signals are opaque outside of your network.

### Implement ad loading methods

Timeout: 10 seconds

If your bidder returns the winning bid, the Google Mobile Ads SDK (Legacy)
calls your adapter to load the winning ad, passing you any data that your
bidder returned that your SDK needs to load that ad.

The exact load method that is called depends on the ad
format this request is for:

| Ad Format | Load method |
|---|---|
| Banner | `loadBannerAd()` |
| Interstitial | `loadInterstitialAd()` |
| Rewarded | `loadRewardedAd()` |

Implement these methods for the ad formats your adapter supports.

The load method is called on the UI thread, on the same instance of the
adapter from which you provided signals. This method provides you the following
parameters:

- A `MediationAdConfiguration`, which contains parameters your SDK needs to
  load the ad for the winning bid, such as the bid response and any credentials
  the publisher configured in the AdMob UI.

- A `MediationAdLoadCallback` object used to notify Google Mobile Ads SDK (Legacy)
  when the loading succeeds or fails.

Once your SDK loads the ad, call `mediationAdLoadCallback.onSuccess()`. In the
event ad loading fails, call `mediationAdLoadCallback.onFailure()` with a
string explaining the error that occurred.

The `mediationAdLoadCallback.onSuccess()` method requires that you pass in an
object that confirms to one of the "Ad" interfaces defined by the Google Mobile
Ads SDK. These ad interfaces ask you to provide some information about the ad.

`MediationAdConfiguration` also has a [`getWatermark()`](https://developers.google.com/admob/android/reference/com/google/android/gms/ads/mediation/MediationAdConfiguration.md.txt#getWatermark())
method to return a base64-encoded string representing a PNG image. This image
should be tiled in a transparent overlay on your ads.
Reach out to Google for additional guidance on how to render the watermark.
It contains metadata about the ad being shown for use by publishers to determine
the source of ads shown.

For banners, you'll be asked to provide the banner view. For interstitial and
rewarded ads, you'll be asked to implement a `show()` method to show the ad at
a later point in time. As a best practice, we recommend making your class that
does the ad loading also be responsible for implementing these ad methods.

The following is a sample implementation of `loadBannerAd()`. Keep in mind
that your adapter's implementation will look different, as your adapter
integrates against a different SDK.

    public final class SampleRtbAdapter extends RtbAdapter {
      ...

      @Override
      public void loadBannerAd(
          MediationBannerAdConfiguration adConfiguration,
          MediationAdLoadCallback<MediationBannerAd, MediationBannerAdCallback> callback) {

          SampleBannerRenderer bannerRenderer =
              new SampleBannerRenderer(adConfiguration, callback);
          bannerRenderer.render();
        }
    }

    // Renders a banner ad, and forwards callbacks to Google Mobile Ads SDK (Legacy).
    public class SampleBannerRenderer implements MediationBannerAd {
      private MediationBannerAdConfiguration adConfiguration;
      private final MediationAdLoadCallback<MediationBannerAd, MediationBannerAdCallback> adLoadCallback;
      private AdView adView;
      private MediationBannerAdCallback callback;

      public SampleRtbBannerRenderer(
          MediationBannerAdConfiguration adConfiguration,
          MediationAdLoadCallback<MediationBannerAd, MediationBannerAdCallback> adLoadCallback) {
        this.adConfiguration = adConfiguration;
        this.adLoadCallback = adLoadCallback;
      }

      public void render() {
        adView = new AdView(adConfiguration.getContext());
        adView.setAdSize(adConfiguration.getAdSize());
        // serverParameters are the parameters entered in the AdMob UI for your network.
        adView.setAdUnitId(adConfiguration.getServerParameters().getString("adUnitId"));

        // Map the callbacks from your SDK to Google's SDK.
        adView.setAdListener(new AdListener() {
          // See the next step for more information on callback mapping.
          // ...
        });

        // Get the bid response and watermark from the ad configuration and
        // pass the relevant information to your SDK.
        String ad = adConfiguration.getBidResponse();
        String watermark = adConfiguration.getWatermark();
        Bundle extras = new Bundle();
        extras.putString("bid", ad);
        extras.putString("watermark", watermark);
        AdRequest request = new AdRequest.Builder()
            .addNetworkExtrasBundle(AdMobAdapter.class, extras)
            .build();
        adView.loadAd(request);
      }

      // MediationBannerAd implementation

      @NonNull
      @Override
      public View getView() {
        return adView;
      }
    }

### Relay ad presentation lifecycle events

The final responsibility of the adapter is to notify Google Mobile Ads SDK (Legacy)
of any presentation lifecycle events, so that they can be forwarded to the
publisher. The publisher expects these callbacks at specific times no matter
which ad network serves the ad, so it's important that as many of these
callbacks are invoked as possible, and at the right time, so that Google Mobile Ads SDK (Legacy)
can forward them to the publisher.

Adapters should invoke the following events when applicable:

| Common to all formats ||
| Method | When to call |
|---|---|
| `reportAdClicked()` | The ad was clicked. |
| `reportAdImpression()` | The ad rendered an impression. |
| `onAdOpened()` | The ad presented a full screen view. |
| `onAdClosed()` | The ad's full screen view has been closed. |
| `onAdLeftApplication()` | The ad caused the user to leave the application. |
| `onRewarded()` | The user is granted a reward. |
| `onVideoStarted()` | The ad's video started. |
| `onVideoCompleted()` | The ad's video completed. |

<br />

The adapter gets a `MediationAdLoadCallback<MediationAdT, MediationAdCallbackT>`
object back upon calling `mediationAdLoadCallback.onSuccess()`. Adapters are
expected to hold onto this object and use it to invoke presentation events
that occur on your ad.

Typically, most of these events are driven by your ad network's SDK. The
adapter's role is simply to map the callbacks from your ad network SDK to the
Google Mobile Ads SDK (Legacy).

The following example demonstrates how you would forward callbacks from your
SDK's ad listener to Google Mobile Ads SDK (Legacy):

    adView.setAdListener(new AdListener() {
        public void onAdLoaded() {
            callback = adLoadCallback.onSuccess(SampleBannerRenderer.this);
        }

        public void onAdImpression() {
            if (callback != null) {
                callback.reportAdImpression();
            }
        }

        public void onAdFailedToLoad(LoadAdError adError) {
            adLoadCallback.onFailure("Error: " + adError.toString());
        }

        public void onAdClosed() {
            if (callback != null) {
                callback.onAdClosed();
            }
        }

        public void onAdOpened() {
            if (callback != null) {
                callback.onAdOpened();
                callback.reportAdClicked();
            }
        }

        public void onAdLeftApplication() {
            if (callback != null) {
                callback.onAdLeftApplication();
            }
        }
    });

## Required assets for native ad impression tracking

Google Mobile Ads SDK (Legacy) records an impression for a native ad when 1 px of the
ad is visible. If your ad network SDK requires specific assets to be displayed
in order to render a valid impression, your bidder can indicate these required
native assets in the bid response. Google Mobile Ads SDK (Legacy) then validates
that your required native assets are displayed prior to recording an impression.

See the [native required assets
documentation](https://developers.google.com/authorized-buyers/rtb/open-bidding#native-required-assets) for
more information on how to specify additional required assets in the bid
response.

> [!IMPORTANT]
> **Key Point:** Any impressions rendered invalid due to your ad network's additional native required assets will affect your billable event ratio for that publisher.

## Show ad errors

For full screen formats, such as interstitial and rewarded ads, in the success
load callback you will provide an implementation of

[`MediationInterstitialAd`](https://developers.google.com/admob/android/reference/com/google/android/gms/ads/mediation/MediationInterstitialAd.md.txt)
or [`MediationRewardedAd`](https://developers.google.com/admob/android/reference/com/google/android/gms/ads/mediation/MediationRewardedAd.md.txt)

so that Google Mobile Ads SDK (Legacy) can ask your adapter to show the ad.

Google Mobile Ads SDK (Legacy) expects that if an adapter successfully loaded an ad,
the ad is ready to show when the publisher asks to show it. This means that
every show call should result in an impression.

However, there may be corner cases where you're unable to show an ad. If you
can't show the ad, call the

[`onAdFailedToShow()`](https://developers.google.com/admob/android/reference/com/google/android/gms/ads/mediation/MediationRewardedAdCallback.md.txt#onAdFailedToShow(com.google.android.gms.ads.AdError))

callback to cancel the impression.

The table below shows how presentation callbacks affect impression recording for full screen ad formats:

| Callback | Result |
|---|---|
| onAdOpened() | `Impression recorded` |
| onAdFailedToShow() | `Impression failure[1](https://developers.google.com/admob/android/open-bidding-adapter#impression-failure-footnote)` |
| None of the above for several seconds | `Impression recorded` |

^1^ For failed
impressions, your ad network is not charged for the impression, but it
impacts your billable event rate adjustment. See [bid request
signals](https://developers.google.com/authorized-buyers/rtb/open-bidding#bid-request-signals) for more
information.

The following mock example demonstrates a load/show lifecycle where an ad
show call may result in a failure.

    final class SampleRtbAdapter extends RtbAdapter implements MediationRewardedAd {

     private MediationRewardedAdCallback callback;
     private RewardedAd rewardedAd;

     ...

      @Override
      public void loadRewardedAd(
          MediationRewardedAdConfiguration adConfiguration,
          final MediationAdLoadCallback<MediationRewardedAd, MediationRewardedAdCallback> loadCallback) {

        // Load an ad. This mock example uses Google's SDK, but in practice
        // your adapter will load the ad using your ad network's SDK.
        RewardedAd.load(adConfiguration.getContext(),
            "ca-app-pub-3940256099942544/5224354917",
            new AdRequest.Builder().build(),
            new RewardedAdLoadCallback() {
    @Override
    public void onAdLoaded(@NonNull RewardedAd rewardedAd) {
    // When the ad loads, invoke the load success callback.
    callback = loadCallback.onSuccess(SampleRtbAdapter.this);
    }
    });
      }

      @Override
      public void showAd(Context context) {
        // In this mock example, your ad network requires an activity context, but
        // didn't receive one, making you unable to show the ad.
        if (!(context instanceof Activity)) {
          AdError error = new AdError(1, "Context must be an activity",
              "com.google.ads.mediation.sample");
          callback.onAdFailedToShow(error);
        }

        // This example shows Google SDK's callbacks, but it's likely your SDK
    // has similar presentation callbacks.
    rewardedAd.setFullScreenContentCallback(new FullScreenContentCallback() {
    @Override
    public void onAdShowedFullScreenContent() {
    // Your ad network SDK successfully showed the ad. Call onAdOpened().
    callback.onAdOpened();
    }
    @Override
    public void onAdFailedToShowFullScreenContent(AdError adError) {
    // Your ad network SDK failed to show the ad, invoke onAdFailedToShow.
    // In practice, you will map your SDK's error to an AdError.
    AdError error = new AdError(adError.getCode(), adError.getMessage(),
    adError.getDomain());
    callback.onAdFailedToShow(adError);
    }
    });


        rewardedAd.show((Activity) context, ...);
      }
    }