I had apps with ads distributed in 177 countries, including the EEA (EU member states), the UK, and Switzerland.
And I hadn’t implemented UMP (User Messaging Platform, AdMob’s consent management tool) at all.
Neither ConsentInformation nor ConsentForm appeared anywhere in the code. The ad-loading code just called a bare AdRequest().
What’s the problem
To serve AdMob ads, Google’s policies require you to obtain consent from users in the EEA, the UK, and Switzerland. It’s the screen that lets users choose whether their personal data may be used for advertising purposes.
If you keep serving ads in those regions without it, in the worst case your AdMob account gets suspended. The nasty part is that if you run multiple apps under the same AdMob account, even the apps that aren’t in violation go down with it. I was running 3 apps on the same account.
Why I didn’t notice
I had assumed that consent to the terms of service and ad consent (CMP) were the same thing.
My app already had a screen at launch asking users to agree to the terms of service and privacy policy. It also had a screen asking for location permission. In my head, “consent is handled.”
But these two are completely different things.
- Consent to the terms of service / privacy policy → consent about the conditions for using the app
- UMP (CMP) → consent about using personal data to serve ads
Doing the former is no substitute for the latter. I only caught this misunderstanding because I happened to be running multiple apps in parallel and compared one app’s implementation against another’s. If I’d only been looking at a single app, I probably would never have noticed.
Couldn’t I just drop the EEA from distribution?
That crossed my mind for a second, but in my case it wasn’t an option.
One of the apps was submitted to an overseas development contest, and the rules had judges install the app on their own devices to evaluate it. Where the judges are located is up to the contest; I have no control over it. Dropping the EEA from distribution risked judges there being unable to install the app.
In other words, with “narrow distribution to dodge the problem” off the table, there was no path other than implementing UMP.
What I implemented
Using Google’s UMP SDK, I set things up like this:
- Created a new
ConsentServicethat fetches consent status at launch - The ad-loading code returns
nulland shows no ads if consent hasn’t been obtained (fail-closed) - Added “Ad privacy settings” to the settings screen, but shown only to users in the EEA (regions not covered stay as before)
I narrowed the approach down to two principles.
- Fail-closed: if consent status can’t be confirmed, err on the side of not showing ads. Never pick “it’s probably fine” and show them anyway
- Don’t change the experience in Japan: users outside the covered regions see nothing new, same as before
After implementing it, flutter analyze reported zero errors, and I didn’t add any new dependency packages (the SDK was already included in the existing AdMob-related package). The build size grew by only about 8.73KB, which is negligible in practice.
What I learned after releasing
It isn’t over the moment you release. Until the update passes review, you’re technically still in violation. During the few days of waiting for review, there’s nothing you can do.
One more thing: when you run multiple apps at once, there’s a period where “apps that are fixed” and “apps that aren’t yet” exist side by side. Fixing 1 of 3 doesn’t remove the risk if the other 2 still have the same hole. Instead of fixing them one at a time, you need to check across all apps the moment you find the problem.
Summary
- Consent to the terms of service and consent for ad serving (UMP/CMP) are different things. Doing one doesn’t substitute for the other
- If multiple apps share the same AdMob account, one app’s violation can spill over to all of them
- Sometimes you can’t work around it by narrowing distribution countries (e.g., when you need to reach judges or overseas users)
- The implementation itself needed no new dependencies. Noticing late is the bigger risk