Test Your Custom GMA Adapter (Android)
Learn how to verify if your custom GMA adapter is working as expected by following the instructions in this article.
For instructions on setting up the custom GMA adapter, see "Implement a Custom GMA Adapter for Android".
If you encounter an error, see the "Troubleshooting" section below.
End-to-End Testing with a Proxy Tool
Use a proxy tool such as Charles, mitmproxy, or HTTP Toolkit to confirm the envelope reaches Google's ad server in the outgoing request.
The table below lists what you can verify in this process.
| Check | Confirms |
|---|---|
Envelope retrieve API returns 200 | Your ATS API layer works |
collectSignals() logs a non-empty signal | Your adapter works |
GAM request contains a3p with your FQCN and envelope | Full path to Open Bidding works |
1. Record a Baseline Envelope
Log the signal your adapter will pass from YourEnvelopeManager.getEnvelope or app debug output:
- Expected FQCN:
com.yourcompany.yourapp.ads.YourRtbAdapter - Expected signal: <envelope27 or envelope19 string>
2. Set up the proxy
- Point the test device at your proxy and install the proxy's SSL certificate on the device.
- In the proxy, enable SSL proxying for
*.doubleclick.net. - Start recording before you load an ad.
3. Initialize Mobile Ads and Load an Ad
Call load() inside the MobileAds.initialize() callback. We recommend doing this for testing or for the first ad request. If you call an ad load before initialization completes, your adapter may not run on that first request and a3p may be missing.
The typical sequence in your app should be as follows:
-
YourEnvelopeManager.getEnvelope(...) // envelope ready
-
MobileAds.initialize(context) { status ->
here
// load INSIDE this callback -
collectSignals() → outgoing request → a3p
Load the ad inside the init callback, keeping the following in mind:
- Do not call
RewardedInterstitialAd.load()(oradView.loadAd(), etc.) before theMobileAds.initialize()callback fires. For later ad loads in the same session, after init has completed once, you may callload()without wrapping ininitialize()again. - You do not call
collectSignals()yourself. GMA SDK invokes it when you call*.load()after adapters are initialized.
MobileAds.initialize(activity) { status ->
// Confirm your adapter initialized (optional but useful for debugging)
Log.d("Ads", "Adapter: ${status.adapterStatusMap["com.yourcompany.yourapp.ads.YourRtbAdapter"]}")
val adRequest = AdManagerAdRequest.Builder().build()
RewardedInterstitialAd.load(
activity,
"/your-network-code/your-ad-unit", // GAM unit with your custom event registered
adRequest,
object : RewardedInterstitialAdLoadCallback() {
override fun onAdLoaded(ad: RewardedInterstitialAd) {
// a3p was sent in the outgoing request during load
}
override fun onAdFailedToLoad(error: LoadAdError) {
// Outgoing request may still exist — check proxy tool
}
}
)4. Find and decode a3p
a3pThe a3p parameter is sent in the outgoing request from your app to Google, not in the response. In your proxy tool, look for a GET or POST request to:
securepubads.g.doubleclick.netpubads.g.doubleclick.net(path often includes/gampad/ads)
In the request's query string, find the a3p parameter. Its value is URL-safe Base64 (uses - and _ instead of + and /). For example:
https://pubads.g.doubleclick.net/gampad/ads?iu=/12345/your-ad-unit&...&a3p=CjEqL2NvbS5...long-string...&...
Decode on macOS Terminal
Decode the a3p value itself as so:
A3P='paste_the_a3p_value_here'
echo -n "$A3P" | tr '_-' '/+' | openssl base64 -d -A 2>/dev/null | stringsPass criteria
| In decoded output | Expected |
|---|---|
| Your adapter FQCN | For example, com.yourcompany.yourapp.ads.YourRtbAdapter. |
| Envelope signal | Matches the baseline envelope recorded in step 1. |
Old SDK class (com.liveramp.ats.LRAtsMediationAdapter) | Absent |
If verification fails, refer to the table below.
| Symptom | Likely cause |
|---|---|
No a3p in request | Ad not yet loaded, Secure Signals not enabled in GAM, or ad unit not using your custom event. |
a3p present but envelope missing | collectSignals() returned empty or called onFailure. |
| No doubleclick request after load | load() called before MobileAds.initialize() finished, or load() not called. |
| FQCN missing or wrong | GAM Class name does not match your Kotlin/Java class. |
| FQCN present but envelope missing | collectSignals() returned empty or onFailure. |
Troubleshooting
| Symptom | Likely cause |
|---|---|
Adapter missing from adapterStatusMap | GAM Class name does not match your adapter FQCN. |
ClassNotFoundException at runtime | Typo in GAM, or ProGuard removed your adapter class. |
onFailure in collectSignals() | No envelope from your ATS API layer — not an initialize() issue. |
Empty onSuccess("") | Response had no type 27 or type 19 envelope. |
LRAtsMediationAdapter still appears | SDK still on classpath, or GAM still points to the old class name. |