Shipping notes

AdMob says “No ad to show” on your brand new app. Here is why, and how long it actually lasts.

Linking your store listing is only half of it — and the console never tells you that. This is the two-gate process spelled out, plus the day-by-day timeline from a real launch.

Short version

A new AdMob app sits in a state called limited ad serving and receives close to zero inventory until Google verifies it. Clearing it takes two separate steps, and the console only ever shows you the next one, so it reads like a single task. After both are done you still wait for Google’s crawler. On my launch that wait was five more days. Near-zero fill in your first week is the expected state, not a bug you can debug your way out of.

The symptom

Real ad unit ids. No errors in the log. Everything wired correctly. Every single request comes back No ad to show, and you get maybe one impression a day — on your own phone.

Then you swap in the test ad unit ids and they fill instantly, every time. Which is exactly the observation that convinces you your integration is fine and the problem must be somewhere stranger. I spent two days there. The integration was fine. The problem was account-side, and none of it is visible from the SDK.

This is engine-independent. I hit it in Unity, but everything below is console-side and applies the same to native Android, native iOS, Flutter or anything else.

What is actually happening

A brand new app in AdMob is placed in limited ad serving. Advertisers do not bid meaningfully on unverified inventory, so you get a trickle instead of a fill rate. Lifting it requires two things, and the console shows them one at a time, as a single line of status text that changes underneath you.

Gate 1 — link the app to its store listing

App settings → App store details → Add. Two traps here:

Gate 2 — verify the app with app-ads.txt

Verification wants an app-ads.txt file, and it is specific about where:

Then you wait, and there is no button that helps

This is the part I could not find written down anywhere, and the reason I am writing this post.

Even with the file live, correct, and on the right domain, nothing moves until Google’s crawler picks it up. The console says up to 7 days. Check for updates does not force a crawl — it re-reads whatever Google already has. There is no appeal to file, no support ticket that speeds it up, and nothing in your build to change.

The measured timeline

Day 1 — store link added on both apps, app-ads.txt confirmed live on the correct domain and returning HTTP 200. Status stayed at limited ad serving.

Days 2–5 — single-digit impressions per day. No change, despite checking constantly.

Day 6 — both apps flipped to Ad serving enabled. I changed nothing in between. Same build, same ad units, no code change, no resubmission.

For scale, the week that followed the flip:

MetricFirst 7 days after serving was enabled
Requests812
Impressions488
Match rate88%

Before the flip that same number was in the single digits per day. So if you are staring at a match rate near zero in week one, the honest answer is that you are probably not doing anything wrong — you are early.

Two things worth planning around during that window

Your rewarded ad path will look broken to anyone watching

If you have a rewarded placement — continue after death, unlock a car, double a reward — the player taps Watch ad and nothing happens. Mine is designed to fall through to the non-reward outcome rather than block the game on ad availability, which I still think is correct behaviour. But to an observer it is indistinguishable from a dead button.

That matters more than it sounds, because the observers in your first week are exactly the people you cannot afford to confuse: store reviewers, the first players who write to you, and yourself while you are recording trailer footage. Keep the ad path out of demo videos until serving is enabled.

Do not replay your own ads to check they work

Once you are off test ids, watching your own live ads is invalid traffic, and it gets accounts suspended. “I was only testing” is not a defence, and there is no meaningful appeal. If you need to see a real ad unit behave on hardware, register the device first with RequestConfiguration.TestDeviceIds so your impressions are excluded.

One more source of confusion: two different “limited ad serving”

There are two unrelated states with almost the same name, and threads about them get mixed together constantly:

They have different causes and different fixes. Worth checking which console the warning is actually in before acting on advice written for the other one. Similarly, a policy violation and a serving limit are two separate rows: appealing the violation does not lift the limit, and clearing the limit does not resolve the violation.

Checklist, in order

  1. Publish the app and let the store listing go live.
  2. In AdMob, add the store listing by pasting the store URL, not by searching the package name.
  3. Note that the warning text changed rather than disappeared. You are halfway.
  4. Put app-ads.txt at the root of the developer website named on your store listing, with your publisher id line.
  5. Confirm it returns HTTP 200 from the outside, on the exact domain the listing points to.
  6. Wait. Expect several days. Do not change your build looking for a fix.
  7. Meanwhile: avoid the ad path in demo footage, and register your own device as a test device.
Slide2Go app icon

Slide2Go

All of the above came out of shipping this: a sliding block puzzle where dragging one block pushes every block it is touching, so a single drag can shift an entire row. Free on both stores, plays offline.