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 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 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.
Workflow of a bidding adapter
Initialization
A detailed flow of the entire request-response-rendering lifecycle of an adapter is shown below:
The adapter is responsible for the following portions of the workflow:
-
Steps 4-7: Initialize your adapter and call back Google Mobile Ads SDK 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 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.
Implementing the bidding adapter
To create a bidding adapter for Google Mobile Ads SDK, 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
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.
@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
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()
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.
Implement ad loading methods
Timeout: 10 seconds
If your bidder returns the winning bid, the Google Mobile Ads SDK 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 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()
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
.
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 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 can forward them to the publisher.
Adapters should invoke the following events when applicable:
reportAdClicked()
reportAdImpression()
onAdOpened()
onAdClosed()
onAdLeftApplication()
onRewarded()
onVideoStarted()
onVideoCompleted()
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.
The following example demonstrates how you would forward callbacks from your SDK's ad listener to Google Mobile Ads SDK:
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 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 then validates that your required native assets are displayed prior to recording an impression.
See the native required assets documentation for more information on how to specify additional required assets in the bid response.
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
or MediationRewardedAd
so that Google Mobile Ads SDK can ask your adapter to show the ad.
Google Mobile Ads SDK 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()
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
|
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 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
,
...
);
}
}