AdMob & Meta ads, end to end
Your app sells a few seconds of screen space, many times a day. AdMob runs the sale: it asks Google's advertisers and Meta's advertisers (plus others) what that moment is worth, shows the highest bidder's ad, counts the impression and pays you. This guide walks through every piece of that chain from a developer's side.
Code uses Kotlin and the GMA Next-Gen SDK, which Google made its preferred Android SDK in July 2026. Legacy SDK equivalents are noted where they differ.
Contents
The short version
AdMob is two things at once
An ad network (it sells your inventory to Google's advertisers) and a mediation platform (it runs an auction that other networks, like Meta, can bid into).
Meta Audience Network is a bidder
Meta's advertisers buy space in other apps through it. Inside AdMob, Meta competes through bidding only. Waterfall support ended in 2021.
You add two dependencies
The Google Mobile Ads SDK plus the Meta mediation adapter (which pulls in Meta's SDK). No Meta-specific ad code is needed; you load AdMob ad units as usual.
Two payouts, two dashboards
AdMob pays for Google demand. Meta pays its share directly through your Meta Business payout account. Each reports its own numbers.
Everything that goes wrong in practice falls into one of five buckets: setup (app-ads.txt, app verification, mapping Meta placements), consent (a missing GDPR message or partner list), code (initialising late, loading on demand instead of preloading), policy (accidental clicks, disruptive interstitials) and expectations (eCPM varies wildly by country and format). Each has its own section below.
What changed recently
Most tutorials online predate these changes. If a guide shows play-services-ads as the only option or a Meta waterfall setup, it is out of date.
- Meta Audience Network becomes bidding-only. The adapter drops waterfall support from v6.12.0.0.Meta
- AdMob requires app-ads.txt verification for new apps before they can fully serve ads; existing apps rolled in through 2025.AdMob
- Google retires Privacy Sandbox on Android (Topics, Protected Audience, Attribution Reporting, SDK Runtime). The Advertising ID (GAID) stays.Platform
- India notifies the DPDP Rules, 2025, with core consent obligations phased in over 18 months.Privacy
- GMA Next-Gen SDK enters open beta: a Kotlin rewrite with background initialisation and ad preloading.AdMob
- Legacy SDK 25.0.0: large anchored adaptive banners, removal of old mediation callbacks; 23.x deprecated.AdMob
- Legacy SDK 22.x reaches sunset.AdMob
- Next-Gen SDK becomes Google's preferred Android SDK; the legacy 25.x line gets a retirement schedule.AdMob
- September 2026: best time to build new integrations on Next-Gen.
- DPDP consent notices and data-principal rights apply in India, including verifiable parental consent for users under 18.Privacy
- Legacy SDK deprecated: ads still serve, Google support ends.AdMob
- Legacy SDK sunset: ads may stop serving and outdated-SDK warnings can block app releases.AdMob
The ad marketplace
Mobile advertising is a two-sided market. Advertisers bring budgets; publishers (you) bring attention. Ad platforms sit in the middle, match the two in milliseconds, and take a cut.
Who is who
| Role | Examples | What they want from you |
|---|---|---|
| Advertiser | Game studios, fintech, e-commerce, other apps | Real users who install, buy or remember the brand. Fraudulent or accidental clicks cost them money, which is why policies are strict. |
| Demand-side platform | Google Ads, DV360, Meta Ads Manager | Nothing directly. They decide which of your impressions to buy using the signals your request carries (device, country, app category, consent state, ad ID). |
| Ad network / exchange | AdMob network, Meta Audience Network, AppLovin, Unity, Pangle… | A correctly integrated SDK or adapter, a verified app (app-ads.txt), and clean traffic. |
| Mediation platform | AdMob mediation (also AppLovin MAX, Unity LevelPlay) | Ad units, mediation groups and partner mappings configured in its dashboard. It decides which network fills each request. |
| Publisher | You | Owns the app, the ad placements, user consent and policy compliance. Gets paid. |
How AdMob and Meta fit together
You have three realistic setups. The difference is whether Meta and Google compete for the same impression.
AdMob gives you
- Google's advertiser demand (Google Ads app campaigns, AdX, DV360)
- Mediation: ad units, mediation groups, bidding partners, A/B tests
- Consent tooling (User Messaging Platform) and Ad Inspector
- Reporting, Firebase linking, monthly payments
Meta Audience Network gives you
- Meta's advertisers, who target using Facebook/Instagram data
- Often strong prices on interstitial, rewarded and native in many markets
- Its own dashboard (Monetization Manager), app review and payouts
- Nothing to code beyond the adapter dependency and a network config
Ad formats
Format choice decides both revenue and how users feel about your app. Full-screen formats pay more per impression and carry most of the policy risk.
| Format | What it is | Meta bids? | Relative eCPM | Put it | Watch out |
|---|---|---|---|---|---|
| Banner | Rectangular strip anchored top or bottom, or inline in scrolling content. Use adaptive sizes; SDK 25 added large anchored adaptive banners. | Yes | Persistent screens users stay on | Never next to buttons or overlapping content. Refresh is automatic (set in AdMob). | |
| Native | You receive assets (headline, image, icon, CTA) and render them in your own layout. Meta also supports native banner. | Yes | Feeds, lists, results screens | Must show the "Ad" badge and AdChoices; Meta requires a MediaView for impressions to count. | |
| App open | Full-screen ad shown when the user brings the app to the foreground. | No | Warm starts, behind your splash | Don't show on the very first launch; cap frequency. | |
| Interstitial | Full-screen ad the user closes. Static or video. | Yes | Natural breaks: level end, after a task completes | Not on app launch/exit, not mid-action, not after every tap. Must be closable. | |
| Rewarded interstitial | Full-screen ad that offers a reward, shown at a break without the user asking first. | Yes | Level end with bonus offer | Tell the user what they'll get before it plays. | |
| Rewarded | User opts in to watch an ad in exchange for a reward (coins, a life, premium content). | Yes | "Watch to get X" buttons | Grant the reward only in the reward callback; use server-side verification for anything valuable. |
Relative eCPM is a typical ordering, not a promise. Actual prices vary by country, season (Q4 is highest), audience and app category, often by 5–20× between markets.
Life of an ad request
What actually happens between your app launching and a rupee (or cent) landing in your account. This order matters: consent gates initialisation, initialisation gates signals, and signals decide whether Meta can bid at all.
Step by step, in plain words
- Consent (1–2). The UMP SDK checks the user's region. In the EEA, UK, Switzerland and US states with privacy laws it may show a consent or opt-out message you configured in AdMob. The result is a stored consent string that later requests carry.
- Initialise (3–4).
MobileAds.initialize()starts Google's SDK and every mediation adapter on the classpath. The Meta adapter initialises Meta's SDK. Next-Gen runs this on a background thread. - Request (5–7). You ask for an ad on a specific ad unit ID. The SDK bundles device and app signals: ad ID (if permitted), country, OS, app version, consent, and each bidding adapter's token.
- Auction (8–11). AdMob sends bid requests to bidding partners, including Meta, collects bids, compares them with Google's own demand and any waterfall sources, and returns the winner's ad.
- Show (12–13). With preloading the ad waits in a pool until you call
show(). If Meta won, the adapter renders Meta's creative using Meta's SDK. - Count and pay (14–16). The impression is recorded when the ad actually renders. Clicks and video completions are tracked. The paid event reports the estimated value, which you can forward to analytics.
The whole request-to-ad round trip happens in well under a couple of seconds on a good network, but it is never instant. That is why full-screen ads should be preloaded before the moment you want to show them, never requested at that moment.
Bidding vs waterfall
Two ways a mediation platform can decide who fills an impression. Meta only supports the second.
eCPM floors
A minimum price. AdMob offers optimised floors for its own demand. Floors too high cut fill; too low and you undersell. Start with Google-optimised floors.
Mediation groups
Rules that say "for these ad units, in these countries, on this platform, use these sources." Split by country tier only when you have enough traffic per group.
Bidding partners
Each needs its adapter in your app, a signed partnership in AdMob, and a mapping (Meta: placement ID per ad unit).
Metrics and money
Revenue is a chain of rates. Every drop in the chain is a place to look when numbers disappoint.
The funnel (example numbers)
Show rate drops when you preload ads that are never shown (user leaves before the break). Low show rate is a code problem; low fill is a demand or setup problem.
Formulas you'll use every week
Revenue estimator
Replace the example inputs with numbers from your AdMob report (Reports → Mediation, grouped by format).
How you get paid
| AdMob | Meta Audience Network | |
|---|---|---|
| Who pays | Google, for Google demand and bidding sources paid through AdMob | Meta, directly, not through AdMob |
| Where to set up | AdMob → Payments | Meta Business Suite / Monetization Manager → payout settings |
| Payment threshold | $100 for USD accounts (equivalent amounts in other currencies) | Minimum payout applies; confirm the current amount in Meta's Business Help Center |
| Cycle | Monthly. Last month's earnings finalise early in the month; if your balance is above the threshold, payment goes out around the 21st | Monthly, on Meta's own schedule |
| Verification | Identity and address (mailed PIN) once earnings reach $10 | Business details and tax information before payouts |
| Numbers of record | AdMob's impression counts | Meta's own counts; expect small differences from AdMob's view |
Foreign ad income has income-tax and GST implications, and US-sourced earnings may need tax forms (such as W-8BEN) in both dashboards. I'm not a tax advisor, so confirm your treatment with a chartered accountant.
Account setup
Most "ads not showing" problems are dashboard problems, not code problems. Do these in order.
Get the Play listing ready
AdMob verifies apps against their store listing. Publish the app (or prepare the listing) and set a developer website in Play Console → Store settings. That domain will host app-ads.txt.
Create the AdMob app and ad units
- AdMob → Apps → Add app → link it to the Play listing. Note the App ID (
ca-app-pub-…~…). - Create one ad unit per placement (e.g.
home_banner,level_end_interstitial,extra_life_rewarded). Note each ad unit ID (ca-app-pub-…/…). Separate units give you per-placement reports and controls.
- AdMob → Apps → Add app → link it to the Play listing. Note the App ID (
Publish app-ads.txt and verify
Host a plain-text file at
https://yourdomain.com/app-ads.txt(domain root, not a subfolder). Then AdMob → App settings → Verify app. Apps can't fully serve ads until verification and the app readiness review pass.app-ads.txtcopy exact lines from each dashboard# Google AdMob (your publisher ID) google.com, pub-XXXXXXXXXXXXXXXX, DIRECT, f08c47fec0942fa0 # Meta Audience Network (line shown in Monetization Manager) facebook.com, YOUR_META_ID, DIRECT, c3e20eee3f780d68
Configure privacy messages
AdMob → Privacy & messaging. Create a European regulations (GDPR) message and a US state regulations message. The UMP SDK shows whatever you publish here, so there's no consent UI to design yourself.
Set up AdMob payments
Add payee name and address (must match your bank), tax information, and a bank account once you cross the thresholds. Verify the mailed PIN when it arrives.
Set up Meta Audience Network
- Create a Meta Business account, open Monetization Manager and create a property for your app with the Android platform and package name.
- Choose Google AdMob as your mediation platform.
- Create a placement for each AdMob ad unit you want Meta to bid on, in the matching format. Note each placement ID.
- Add Meta's line to app-ads.txt, and set up payout and tax details. Meta reviews properties before live ads serve.
Connect Meta inside AdMob
- AdMob → Mediation → create (or edit) a mediation group for Android and the format; add your ad units.
- Under Bidding, add Meta Audience Network and accept the bidding partnership agreement.
- Map each AdMob ad unit to its Meta placement ID.
- Privacy & messaging → add Meta to the ad partners lists for both GDPR and US state regulations. Skip this and Meta can't bid on those users.
Complete Play Console declarations
App content → Ads (contains ads: yes), Advertising ID declaration, Target audience, and Data safety including what the Google and Meta SDKs collect (both publish guidance for this form).
Code integration
Versions below are current as of September 2026. Check the release notes before copying: adapter versions track Meta SDK versions and move often.
1 · Dependencies
dependencies { implementation("com.google.android.libraries.ads.mobile.sdk:ads-mobile-sdk:1.4.0") implementation("com.google.android.ump:user-messaging-platform:<latest>") // Meta bidding adapter — also brings in Meta's Audience Network SDK implementation("com.google.ads.mediation:facebook:6.22.0.0") } // Keep the legacy SDK out of a Next-Gen build (adapters can pull it in) configurations.configureEach { exclude(group = "com.google.android.gms", module = "play-services-ads") exclude(group = "com.google.android.gms", module = "play-services-ads-lite") }
dependencies { implementation("com.google.android.gms:play-services-ads:25.4.0") implementation("com.google.android.ump:user-messaging-platform:<latest>") implementation("com.google.ads.mediation:facebook:6.22.0.0") }
2 · Manifest and network config
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <!-- Added automatically by the ads SDK. Child-directed apps must remove it with tools:node="remove". --> <uses-permission android:name="com.google.android.gms.permission.AD_ID" /> <application android:networkSecurityConfig="@xml/network_security_config"> <!-- AdMob App ID (note the ~). UMP reads it from here. --> <meta-data android:name="com.google.android.gms.ads.APPLICATION_ID" android:value="ca-app-pub-XXXXXXXXXXXXXXXX~YYYYYYYYYY" /> </application> </manifest>
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<!-- Meta's SDK serves cached media from localhost. Android 9+ blocks
cleartext by default, so allow it for 127.0.0.1 only. -->
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">127.0.0.1</domain>
</domain-config>
</network-security-config>If you already have a network security config, merge this domain block into it instead of replacing the file.
3 · Consent first, then initialise
Gather consent before any ad request. Call canRequestAds() right away too, because consent from a previous session is usually still valid and you shouldn't make returning users wait.
class MainActivity : AppCompatActivity() { private lateinit var consentInformation: ConsentInformation private val adsInitStarted = AtomicBoolean(false) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) consentInformation = UserMessagingPlatform.getConsentInformation(this) val params = ConsentRequestParameters.Builder().build() consentInformation.requestConsentInfoUpdate(this, params, { UserMessagingPlatform.loadAndShowConsentFormIfRequired(this) { formError -> // formError is null on success; log it otherwise if (consentInformation.canRequestAds()) initializeAds() } }, { requestError -> // Network failure etc. Fall through to the check below. }) // Returning users: consent from last session may already allow ads if (consentInformation.canRequestAds()) initializeAds() } private fun initializeAds() { if (adsInitStarted.getAndSet(true)) return CoroutineScope(Dispatchers.IO).launch { MobileAds.initialize( this@MainActivity, InitializationConfig.Builder("ca-app-pub-XXXXXXXXXXXXXXXX~YYYYYYYYYY").build() ) { // All adapters (including Meta) have reported in. Start preloading. startPreloading(INTERSTITIAL_UNIT) } } } }
Add a Privacy settings entry in your app's settings screen when consentInformation.privacyOptionsRequirementStatus == REQUIRED, and open UserMessagingPlatform.showPrivacyOptionsForm(activity) { … } from it. Users must be able to change their choice later.
4 · Load and show ads
private fun startPreloading(adUnitId: String) { val request = AdRequest.Builder(adUnitId).build() InterstitialAdPreloader.start(adUnitId, PreloadConfiguration(request)) } // Call at a natural break, e.g. after a level ends private fun showInterstitial(activity: Activity, adUnitId: String) { val ad = InterstitialAdPreloader.pollAd(adUnitId) ?: return // none ready: just continue ad.adEventCallback = object : InterstitialAdEventCallback { override fun onAdImpression() { /* counted */ } override fun onAdDismissedFullScreenContent() { /* resume the app */ } override fun onAdFailedToShowFullScreenContent(error: FullScreenContentError) { } } ad.show(activity) }
private fun showRewarded(activity: Activity, adUnitId: String) { val ad = RewardedAdPreloader.pollAd(adUnitId) if (ad == null) { showNoAdAvailableMessage(); return } // Optional: server-side verification for valuable rewards ad.setServerSideVerificationOptions( ServerSideVerificationOptions.Builder().setCustomData(userId).build() ) ad.show(activity) { rewardItem -> grantReward(rewardItem.amount) // the only safe place to grant } }
<!-- layout --> <com.google.android.libraries.ads.mobile.sdk.banner.AdView android:id="@+id/adView" android:layout_width="wrap_content" android:layout_height="wrap_content" /> // Kotlin val adSize = AdSize.getLargeAnchoredAdaptiveBannerAdSize(activity, 360) val request = BannerAdRequest.Builder(BANNER_UNIT, adSize).build() adView.loadAd(request, object : AdLoadCallback<BannerAd> { override fun onAdLoaded(ad: BannerAd) { } override fun onAdFailedToLoad(adError: LoadAdError) { /* collapse the slot */ } }) // onDestroy (adView.parent as? ViewGroup)?.removeView(adView) adView.destroy()
private var interstitial: InterstitialAd? = null fun loadInterstitial(context: Context) { InterstitialAd.load(context, INTERSTITIAL_UNIT, AdRequest.Builder().build(), object : InterstitialAdLoadCallback() { override fun onAdLoaded(ad: InterstitialAd) { interstitial = ad } override fun onAdFailedToLoad(error: LoadAdError) { interstitial = null } }) } fun showInterstitial(activity: Activity) { interstitial?.show(activity) interstitial = null loadInterstitial(activity) // one ad = one show; load the next }
Rules of thumb for code
- Never block app start on ads. Initialise in the background.
- Preload full-screen ads; an ad object shows once.
- Handle "no ad" as a normal path: skip the break, hide the banner slot.
- Retry failed loads with backoff, not in a tight loop.
- Destroy banners and native ads with their screen to avoid leaks.
Meta-specific code notes
- No Meta ad code: you only ever reference AdMob ad unit IDs.
- Native: use a
MediaViewfor the main media, or Meta won't count impressions. - Native extras:
FacebookMediationAdapter.KEY_SOCIAL_CONTEXT_ASSETingetExtras(). - Adapter needs API 23+ and Kotlin 1.9+ (v6.22.0.1 and later).
Testing
Clicking or repeatedly viewing real ads on your own device is the fastest way to get ad serving limited or your account disabled. Use test ad units during development and register every team device as a test device.
Google's test IDs
| Type | Test ID |
|---|---|
| App ID | ca-app-pub-3940256099942544~3347511713 |
| Banner (adaptive) | ca-app-pub-3940256099942544/9214589741 |
| Interstitial | ca-app-pub-3940256099942544/1033173712 |
| Rewarded | ca-app-pub-3940256099942544/5224354917 |
| Rewarded interstitial | ca-app-pub-3940256099942544/5354046379 |
| Native | ca-app-pub-3940256099942544/2247696110 |
| App open | ca-app-pub-3940256099942544/9257395921 |
Test IDs only exercise Google demand. To test Meta, use your real ad units on a registered test device, as below. Keep IDs in buildConfigField per build type so release builds can never ship test IDs.
Testing Meta through AdMob
Register the device in AdMob
AdMob → Settings → Test devices. Pick a gesture (shake or flick) to open Ad Inspector on that device.
Turn on test mode in Meta
Monetization Manager → your property → testing. The Facebook app must be installed and logged in on the test device. Meta's own testing guide also lets you register device IDs.
Force a Meta win in Ad Inspector
Open Ad Inspector → your ad unit → single ad source testing → "Meta Audience Network (Bidding)". Load an ad and confirm the adapter status is green and a Meta test creative renders.
Test consent from outside Europe
Use
ConsentDebugSettingswithDEBUG_GEOGRAPHY_EEAand your hashed device ID (printed in Logcat) to see the GDPR form. CallconsentInformation.reset()between runs.Switch Meta test mode off before release
Test mode left on means no revenue from Meta.
Privacy and consent
Consent decides whether an ad is personalised, limited, or not requested at all, and it decides which partners may bid. Getting it wrong costs revenue in the best case and fines in the worst.
canRequestAds(). Outside regulated regions it returns true immediately and no form is shown. Inside them, the answer depends on what the user chose.| Regime | Applies to | What it means for your ads | Meta-specific |
|---|---|---|---|
| GDPR / UK GDPR | Users in the EEA, UK, Switzerland | Consent via the IAB TCF framework, shown by UMP. Without consent, Google can serve limited ads; many partners can't bid at all. | Meta isn't on the IAB Global Vendor List. Consent reaches it through Google's Additional Consent spec, so Meta must be in your GDPR ad partners list. |
| US state laws | California and other states with privacy laws | Users can opt out of "sale/sharing". UMP shows the opt-out message; Google applies restricted data processing for its demand. | Google's setting doesn't flow through to Meta. Follow Meta's data processing options (Limited Data Use) guidance yourself. |
| India DPDP Act | Users in India | From 13 May 2027: clear notice, consent for processing, withdrawal as easy as giving, grievance contact, and verifiable parental consent for under-18s. Plan your notice now. | Covers data you and your SDK partners process about Indian users; review both SDKs' disclosures. |
| Children (COPPA, Play Families) | Apps aimed at, or also used by, children | Tag requests as child-directed / under age of consent, use only Play's Families self-certified ad SDKs for child traffic, and remove the AD_ID permission for child-only apps. | The adapter maps the age-restricted setting to Meta's mixed-audience flag. Check whether Meta is allowed for your audience before enabling it. |
The Advertising ID (GAID)
- The
AD_IDpermission is required for apps targeting Android 13+ to read the ID; the ads SDK adds it for you, and you must complete the Advertising ID declaration in Play Console. - Users can delete their ad ID. The SDK then receives zeros; ads still serve but usually earn less.
- Play policy forbids linking the ad ID to persistent identifiers (Android ID, IMEI, email) for ad purposes without explicit consent.
- Privacy Sandbox on Android was retired in October 2025, so there is no replacement API to migrate to. The ad ID plus consent remain the model.
Policies and invalid traffic
Three rulebooks apply at once: AdMob program policies, Meta Audience Network policies, and Google Play's ads policy. Advertisers pay for real attention, so anything that inflates impressions or clicks is treated as fraud, even if accidental.
Do
- Show full-screen ads at natural breaks the user expects.
- Keep banners clearly separated from buttons and game controls.
- Label native ads with "Ad" and keep AdChoices visible.
- Make rewarded ads opt-in, with the reward stated up front.
- Cap frequency (AdMob ad unit settings plus pacing in code).
- Keep a real, content-rich screen around every ad.
Don't
- Click your own ads, or ask anyone to ("support us by clicking").
- Show interstitials on app launch, on exit, or right after a tap the user meant for something else.
- Show full-screen ads that can't be closed after 15 seconds (Play policy), or ads when your app isn't in the foreground.
- Place ads on screens with no content, or stack multiple ads over content.
- Offer rewards for clicking an ad or installing the advertised app.
- Buy cheap traffic (bots, incentivised installs) to lift impressions.
What enforcement looks like
| Signal | What happened | What to do |
|---|---|---|
| Ad serving limited | AdMob is assessing traffic quality (common for new accounts) or detected invalid activity. Fill drops sharply. | Check placements for accidental clicks, remove test clicks, review traffic sources. Limits often lift on their own as quality is confirmed. |
| Policy violation | A specific app or page breaks a rule. Ads may be restricted on that app. | Fix the issue in a new release, then request review in the Policy center. |
| Deductions | Earnings from invalid traffic are removed at month close. | Treat it as a warning; find the spike in reports by country and ad unit. |
| Meta placement disabled | Meta enforces its own integrity rules independently. | Check alerts in Monetization Manager; appeal there. |
Optimisation and reporting
Earn more per user
- Rewarded placements users actually want (extra life, hints, unlocks) usually beat more interstitials.
- Enable bidding with Meta plus a few other networks strong in your users' countries.
- Switch to (large) anchored adaptive banners.
- Run AdMob A/B experiments on floors and mediation setups before rolling out.
- Expect Q4 highs and a January dip; don't react to seasonal swings.
Measure the right thing
- Link AdMob to Firebase: ad revenue shows up next to retention and in-app purchases.
- Forward the paid event's ad value to your attribution/analytics tool if you run user-acquisition campaigns.
- Track ARPDAU and day-7 retention. Extra ads that lose users lose money.
- Watch show rate per ad unit; a falling show rate means wasted preloads.
Which report answers which question
| Question | Where |
|---|---|
| How much did each network earn? | AdMob → Reports → Mediation, broken down by ad source |
| Is Meta bidding and winning? | Mediation report, ad source = Meta Audience Network (bidding): bid requests, bids, win rate |
| What does Meta say I earned? | Monetization Manager → performance (this is what Meta pays on) |
| Why didn't this single request fill? | Ad Inspector on a test device: per-source status and error |
| Do ads hurt retention? | Firebase / Google Analytics with AdMob linked |
Troubleshooting
| Symptom | Likely causes | Fix |
|---|---|---|
| Test ads work, real ads don't | App not verified (app-ads.txt), readiness review pending, ad unit created minutes ago, account payment info incomplete | Check App settings status; new ad units can take up to an hour to serve; confirm app-ads.txt is at the domain root |
| "No fill" errors | Low demand in the user's country, strict floors, consent denied in EEA, ad serving limit | Treat as normal; retry with backoff; lower or remove manual floors; review consent rate |
| Meta never wins | Adapter missing from the build, Meta not added under Bidding, wrong or unmapped placement ID, not in GDPR/US partner lists, Meta property not approved or payout not set | Ad Inspector → check the Meta adapter initialised; recheck mapping and partner lists; check Monetization Manager alerts |
| Meta test ads don't appear | Facebook app not installed or not logged in; test mode off; not using single ad source testing | Follow the Meta testing steps above |
| Meta video stuck or blank | Cleartext blocked for localhost cache | Add the 127.0.0.1 network security config |
| Consent form never shows | You're outside regulated regions; message not published in AdMob; stale stored consent | Debug geography + test device hash; publish the message; reset() |
| Slow start or ANRs | Initialising or loading on the main thread; loading several full-screen ads at launch | Initialise in the background; preload one ad per format; defer banners until first screen renders |
| AdMob and Meta revenue don't match | Each counts impressions on its own side; time zones and finalisation differ | Small gaps are normal. Investigate only persistent gaps above a few percent |
| Build fails with duplicate classes | Legacy and Next-Gen SDKs both on the classpath | Add the exclude block from the dependencies step |
Launch checklist
0 of 0 doneTicks are saved in this browser only.
Glossary
- Ad unit
- An AdMob placement with its own ID (
ca-app-pub-…/…), format and settings. The thing your code requests. - Placement (Meta)
- Meta's equivalent of an ad unit. Mapped one-to-one to an AdMob ad unit for bidding.
- Mediation
- Letting one platform choose among several ad networks for each request.
- Mediation group
- AdMob rule set: which ad units, countries and sources compete together.
- Adapter
- A small library that translates between the Google Mobile Ads SDK and another network's SDK.
- Bidding
- Real-time auction where each network prices the specific impression. Also called in-app header bidding.
- Waterfall
- Legacy method: ask networks one at a time in a fixed order by expected eCPM.
- Signals / bidder token
- Data an adapter generates on-device so its network can bid server-to-server.
- eCPM
- Effective revenue per 1,000 impressions, whatever the advertiser actually paid for.
- Fill rate
- Share of ad requests that returned an ad.
- Show rate
- Share of returned ads that were actually displayed.
- ARPDAU
- Average revenue per daily active user.
- Floor
- Minimum eCPM you'll accept for an impression.
- app-ads.txt
- IAB standard file listing who is authorised to sell your app's inventory. Blocks spoofing; required by AdMob.
- UMP
- Google's User Messaging Platform SDK. Shows GDPR and US state privacy messages you design in AdMob.
- TCF / AC string
- IAB Transparency & Consent Framework consent string, plus Google's Additional Consent string for vendors outside the IAB list, like Meta.
- LDU
- Meta's Limited Data Use flag for US state privacy laws.
- GAID
- Google Advertising ID. Resettable, deletable device ID for ads.
- SSV
- Server-side verification: AdMob calls your server when a rewarded ad completes, so rewards can't be faked client-side.
- IVT
- Invalid traffic: clicks or impressions that aren't genuine user interest. Deducted from earnings.
- Ad Inspector
- In-app debug overlay showing each request, each source's result and errors on test devices.
Sources
- Next-Gen SDK as the preferred SDK for Android (Jul 2026)
- Announcing the GMA Next-Gen SDK (Jan 2026)
- Android Google Mobile Ads SDK 25.0.0
- Set up GMA Next-Gen SDK
- Integrate Meta Audience Network with bidding (Next-Gen)
- Integrate Meta Audience Network with bidding (legacy)
- Next-Gen interstitial ads
- Next-Gen rewarded ads
- Next-Gen banner ads
- UMP SDK for Next-Gen
- AdMob bidding FAQ
- Bidding ad sources that require setup
- Verify your app with app-ads.txt
- About app readiness
- AdMob payment thresholds
- About Audience Network payments (Meta)
- Update on plans for Privacy Sandbox technologies
- Legacy Mobile Ads SDK retirement timeline (PPC Land)
- DPDP Rules, 2025 (PIB)
- DPDP Rules implementation timeline