Mediation and placements
more fill, every ad capped.
Version 3.1 can use several ad networks at once, either as a waterfall the app runs itself or through one mediator SDK. It also adds app-open, interstitial, banner, native and rewarded-interstitial placements. Every placement is off by default and capped in the console.
01Waterfall or mediator
Console → Mediation → How ads are filled. The app reads the choice from config/public.ads, so you can switch without a new build.
| Mode | What the app does | When to use it |
|---|---|---|
| Waterfall in the app (default) | For each ad format the app tries the networks in the order you list (ads.waterfall.<format>). When a network has no fill or returns an error, the app moves to the next one. A network without ids, or without that format, is skipped (app/lib/ads/ad_service.dart, tests in app/test/ad_policy_test.dart). | You have accounts with several networks and want a simple fallback without setting up mediation in a dashboard. |
| A mediator SDK | Every format goes to one SDK only: AdMob, AppLovin MAX or ironSource LevelPlay (Mediator setting). That SDK runs its own mediation or bidding. | You prefer bidding inside one network. Add the other networks in that mediator's own dashboard. That setup is done in the network's dashboard, not in this package. |
When a waterfall list is missing or empty, the app uses [ads.network], the single network you chose in 3.0 (AdMob unless you changed it). A fresh 3.1 console writes admob as every list's default.
Which network has which format
From NETWORK_FORMATS in admin/src/manifest.ts. The console only asks for the unit ids a network has. A waterfall line that names a network without that format is skipped and shown on the Status page.
| Format | AdMob | AppLovin MAX | Unity Ads | ironSource LevelPlay |
|---|---|---|---|---|
| Rewarded video | yes | yes | yes | yes |
| Interstitial | yes | yes | yes | yes |
| Banner | yes | yes | yes | yes |
| App open | yes | yes | no | no |
| Native | yes | yes | no | no (see note) |
| Rewarded interstitial | yes | no | no | no |
The app renders native ads with AdMob (Dart template) and AppLovin MAX (docs/CONTRACT-3.1.md §11). LevelPlay's SDK has native ads, but the app does not render them, so the console asks for no LevelPlay native unit ids. Put admob or applovin in the native waterfall.
02Set up a waterfall
- Enter the ids of each networkConsole → AdMob units, AppLovin MAX units, Unity Ads units, ironSource LevelPlay units. 3.1 adds the app-open, native and rewarded-interstitial unit fields where the network has that format.
- Order the networks per formatConsole → Mediation. Each Waterfall: … field takes one network per line, first tried first, using the names
admob,applovin,unity,ironsource. Example for rewarded videos:applovin admob unity - Set up rewarded-ad callbacks for every network in the listPoints are credited by whichever network calls back, so every network you use for rewarded videos needs its callback URL and secret (Callback URLs).
- Check the Status pageSkipped lines (unknown name, repeat, network without the format) are listed there.
03Placements and their defaults
Console → Ad placements. Every placement is off until you switch it on. The defaults and limits come from admin/src/manifest.ts and match docs/CONTRACT-3.1.md §1. Days are UTC.
| Placement | Setting | Default | Allowed |
|---|---|---|---|
| App open | App-open ad | off | |
| Seconds between two (minimum) | 240 | 30 to 86400 | |
| Most per day | 4 | 0 to 50 | |
| Interstitial | Interstitial between screens | off | |
| Every n-th natural break | 3 | 1 to 50 | |
| Seconds between two (minimum) | 120 | 30 to 3600 | |
| Most per day | 12 | 0 to 100 | |
| Banner | Banner | off | |
| On these screens | home, tasks, history | home, tasks, history, leaderboard, store, profile | |
| Native | Native ads in lists | off | Lists: history, tasks, store |
| After every n-th list item | 6 | 2 to 100 | |
| Most per list | 3 | 0 to 20 | |
| Rewarded interstitial | Rewarded interstitial after a game result | off | AdMob only |
| Points per view | 5 | 0 to 10000 | |
| Seconds between two (minimum) | 300 | 30 to 86400 | |
| Most per day | 6 | 0 to 100 |
Global caps
| Setting | Default | Allowed | Meaning |
|---|---|---|---|
| All full-screen ads: most per hour | 6 | 0 to 60 | App open, interstitial and rewarded interstitial together. Rewarded videos the user chooses are not counted. |
| No full-screen ads in the first seconds of a user's first session | 120 | 0 to 3600 | Counted from launch, on the first app session of the install only. |
| No non-rewarded ads for VIP users | on | VIP users and users who bought remove-ads see no app-open, interstitial, banner, native or rewarded-interstitial ads. Rewarded videos stay available because the user starts them. |
These counters live on the device (app/lib/ads/ad_policy.dart). The rewarded-interstitial limits are also checked on the server when the app asks for an ad session.
A cap of 0 means none, everywhere: most per day = 0 means that placement shows nothing that day, all full-screen ads: most per hour = 0 means no app-open, interstitial or rewarded-interstitial ads at all, and native: most per list = 0 means no native ads. The app (ad_policy.dart), the server's rewarded-interstitial cap (requestAdSession) and the web demo apply the same rule. Rewarded videos the user starts are not affected by these caps. To stop a placement, you can also simply switch it off.
04When each placement shows
From docs/CONTRACT-3.1.md §11 and app/lib/ads/ad_policy.dart:
- App open shows when the app comes back to the foreground. It never shows right after another full-screen ad, a store sheet or the in-app browser.
- Interstitial shows at a natural break (a game result, leaving a quiz, closing the mystery box) once every n-th break breaks have passed and the caps allow it.
- Banner shows at the bottom of the screens you pick.
- Native ads appear inside the history, tasks and store lists.
- Rewarded interstitial is offered after a game result, behind an intro screen (below).
Console → Ads still has Interstitial every n-th screen change and Banner on the home screen. The app uses them only when the matching 3.1 placement is absent from config/public. A 3.1 console always writes the placements, so use Ad placements from now on.
05The rewarded-interstitial intro rule
AdMob's rewarded-ads policy requires an introductory screen before a rewarded interstitial: it must offer a visible "no" option and give the user enough time to opt out. Skipping must not get in the way of normal use. Read the policy: AdMob policies for ad units that offer rewards.
How the app does it (RewardedIntroScreen in app/lib/ui/widgets/ad_widgets.dart):
- Intro screenAfter a game result the app shows the reward (points per view), a 5-second countdown and a No thanks button.
- Skip"No thanks" closes the screen. The offer then waits seconds between two before it can appear again. A skip does not count as a show.
- WatchWhen the countdown ends, the ad plays. Points are credited only by the network's server-side callback, like a rewarded video. The server checks most per day and seconds between two (
requestAdSessionwith placementrewardedInterstitial). Credits use ledger typerewardedInterstitial.
Do not remove the intro screen or hide the "No thanks" button. Do not add text that pushes users to watch (for example "watch to support us"). The policy forbids it.
06Turning placements on
- Turn on one placement at a time and watch your retention on Revenue and growth before you add the next.
- Ad networks and stores penalise disruptive ads. Keep the global hourly cap and the first-session grace.
- Every network in a waterfall must be allowed in your consent setup. Add it to the ad partners list of your AdMob GDPR message (Consent).