AdMob ads diagnosis
When ads don't show, do not jump to editing code. The config is often
correct and the cause is account-side or environment-side. Debug in order.
Steps
1. Verify the config matches the AdMob console (2 min, no code change)
Check all of these against the user's AdMob account:
- Package name ( → for Expo, or the
applicationId in ) must equal the package the
was created for (check in the file,
and the app ID ).
- App ID in the app config (Expo: →
android.config.googleMobileAdsAppId
or via the plugin) must equal the
AdMob app ID (the form).
- Unit IDs in the ads config file (e.g. ) must equal the ad
unit IDs from the console (the form), per platform and per format
(banner/interstitial/rewarded/app open).
Wrong package or wrong
is a hard mismatch; wrong app
ID or unit IDs also are. All four being right means config is fine — move to
step 2.
2. Read the actual error (adb logcat on the real device)
Device must be connected (
) and the app installed. Open the app
and capture the ad errors:
bash
adb logcat | grep -iE "ads|admob|banner|interstitial"
The error code tells you which side is broken:
| Error code | Meaning | Where the problem is |
|---|
| () | Ad request is valid; Google has no ad to serve | AdMob account side — account not yet approved/active, or ad units not live. NOT a code bug |
| () | Request malformed | Check unit ID + request setup |
| () | Unit ID wrong | Fix the ads config unit ID |
| () | No network | Device connectivity |
is the classic "real ads don't show" answer: package, app ID
and unit IDs are all correct and consent is passed (a banner that mounts and
requests is proof consent gated correctly). The fix is in the
AdMob
console (account approval / ad unit status), not in code. New accounts take
~24h–2 weeks to start filling.
3. Check the TEST_ADS flag and consent gate
Most apps gate real vs test ads with a flag (e.g.
in a config
file). It decides everything:
- — every format uses Google's official test unit IDs
on both platforms; the UMP consent gate is skipped (test ads are
non-personalized, they always fill, and AdMob never limits the account for
test activity). Use this for dev/verification.
- (production ship) — real unit IDs are used; the UMP
consent flow ( → ) gates ad requests on
EEA/UK. On a non-EEA device (e.g. VN) consent auto-passes, so consent is
rarely the cause of missing ads.
If a user expects visible ads while
but the account is not
approved, the result is NO_FILL (step 2). Switching back to
is a quick
way to confirm the pipeline works end-to-end while the account is pending.
4. If code actually needs changing
Only change code when step 2 shows an
error or step 1 shows a
mismatch. After any change: run the project's typecheck + relevant tests
(tests that lock the TEST_ADS true/false paths are common), then rebuild the
app.
Completion criterion: you can state, with evidence (config table + error
code from logcat), whether the problem is code-side (fixed) or account-side
(AdMob console action needed, no code change possible).
Reference
- Google's official test ad unit IDs are documented in the AdMob docs; apps
usually keep them in next to the production IDs.
- Consent re-review UI often lives in Settings when the UMP flow requires it.
- Expo: is usually committed, while the
folder is NOT committed (regenerated by on every build).