Muse AI docs
v2.0.0
Live demoConsole demo Get help
● Monetise · AdMob, Unity Ads, ironSource LevelPlay

Ads.
Your ids, your networks, off by default.

The app can show banner, interstitial, native, app-open and rewarded ads from AdMob, Unity Ads or ironSource LevelPlay, from one network or a waterfall per format. Each network is your own publisher account. No ad id of the author ships: only Google's public AdMob test ids, which you replace.

Test ids onlytool/check_ad_ids.shGoogle consent form (UMP)AdMob SSV optionalUnity / LevelPlay rewards capped

01What ships in the code

An ad id tells a network whose app is showing the ad and who gets paid. The source contains no real ad id, so you put in your own.

IdWhere it livesWhat ships
AdMob app id, Androidandroid/app/src/main/AndroidManifest.xml, com.google.android.gms.ads.APPLICATION_IDGoogle's test app id ca-app-pub-3940256099942544~3347511713
AdMob app id, iOSios/Runner/Info.plist, GADApplicationIdentifierGoogle's test app id ca-app-pub-3940256099942544~1458002511
AdMob ad unit idsConsole → AdMob idsEmpty. Debug builds fall back to Google's test units; a release build with an empty unit shows no ad.
Unity Ads game ids and unitsConsole → Unity Ads idsEmpty; test mode only in debug builds
ironSource LevelPlay app keys and unitsConsole → ironSource LevelPlay idsEmpty

Google publishes the test ids for exactly this use: Android test ads, iOS test ads. The web demo shows simulated, labelled "DEMO AD" placeholders and contacts no network.

02Where ad credentials are handled

No ad credential of the author is compiled into the app, the backend or the console, as a default or as a fallback. Every id you enter travels one way only:

  1. You enter itin the console (AdMob ids, Unity Ads ids, ironSource LevelPlay ids). The console stores it and writes it to the Firestore document config/public, field ads.admob, ads.unity or ads.ironsource (schema).
  2. The app reads itfrom GET /v1/config when it starts (app/lib/data/models/ads_config.dart) and hands it to the network SDK (app/lib/ads/native_adapters.dart).
  3. An empty fieldmeans: in a debug build, Google's published test unit (AdMob) or test mode (Unity Ads); in a release build, no ad of that format. There is no other fallback.
CredentialDefault in the shipped code
AdMob app id (native files)Google's public test app id, ca-app-pub-3940256099942544~…, which earns nothing
AdMob unit ids (12 fields)Empty string
Unity Ads game ids and units (8 fields)Empty string; no Unity id in AndroidManifest.xml or Info.plist
ironSource LevelPlay app keys and units (8 fields)Empty string; no LevelPlay key in the native files
AdMob reporting credentialsEmpty; optional, stored encrypted in config/private

Check it yourself: tool/check_ad_ids.sh (below) searches the app for any AdMob id that is not Google's test id and for Unity or LevelPlay keys in the native configuration. A search of the whole download for ca-app-pub- finds only Google's test publisher 3940256099942544.

03Check that no foreign id ships

From app/:

tool/check_ad_ids.sh            # fails if any non-test ad id is hard-coded
tool/check_ad_ids.sh --release  # also fails while the AdMob app id is still Google's test id

Terminal: macOS or Linux as shown; on Windows use WSL or Git Bash (how).

On the shipped source the first command prints PASS no real ad ids are hard-coded with a note that the AdMob app id is Google's test id. Run the --release form before every store build: it must pass once you put your own app id in.

04Step 1 · Put your AdMob app id in the app

  1. Get itAdMob → Apps → your app → App settings → App ID (ca-app-pub-…~…). One for Android, one for iOS (click path).
  2. AndroidReplace the value of com.google.android.gms.ads.APPLICATION_ID in AndroidManifest.xml.
  3. iOSReplace the string after GADApplicationIdentifier in Info.plist.
  4. Console tooEnter the same two app ids in Console → AdMob ids, so the Status check "Ad ids set for what is switched on" can confirm them.

The app id must be in the native files because Google's SDK reads it when the app starts, before any setting arrives. If you never show AdMob ads, you may keep the test id; --release then fails as a reminder.

05Step 2 · Enter the unit ids and choose the networks

  1. Ad unit idsConsole → the page of your network: banner, interstitial, rewarded, native and app-open units for Android and iOS (Unity Ads and LevelPlay have banner, interstitial and rewarded only). Where to find them: AdMob, Unity Ads, LevelPlay.
  2. Unity and LevelPlay need a rewarded unitThe app uses Unity Ads or LevelPlay only when the game id / app key and the rewarded unit are set for the platform.
  3. One network or a waterfallConsole → Ads → How ads are filled: "One network" uses the network you select for every format; "Waterfall per format" tries the listed networks in order (one per line, first tried first). Exact rules and an example: Waterfall.

The three id pages of the console. Every field starts empty; fill only the networks and formats you use.

Console page AdMob ids with empty fields for the Android and iOS app ids and the banner and interstitial units
Console → AdMob ids: Android and iOS app id, then banner, interstitial, rewarded, native and app-open units per platform
Console page Unity Ads ids with empty fields for the Android and iOS game ids and the banner and interstitial units
Console → Unity Ads ids: game id per platform, then banner, interstitial and rewarded units
Console page ironSource LevelPlay ids with empty fields for the Android and iOS app keys and the banner and interstitial units
Console → ironSource LevelPlay ids: app key per platform, then banner, interstitial and rewarded units

06Waterfall: the exact network names

In waterfall mode each format has its own list on Console → Ads, one network per line, tried from the top. The console accepts exactly these names (upper or lower case):

WriteNetworkFormats it can serve in the app
admobGoogle AdMobbanner, interstitial, rewarded, native, appOpen
unityUnity Adsbanner, interstitial, rewarded
ironsourceironSource LevelPlaybanner, interstitial, rewarded

A valid setup that prefers AdMob and falls back to the other two:

Console fieldLines
Waterfall: banneradmob
unity
ironsource
Waterfall: interstitialadmob
ironsource
Waterfall: rewardedadmob
Waterfall: nativeadmob
Waterfall: app openadmob

The console writes it to config/public as:

"ads": {
  "enabled": true,
  "mode": "waterfall",
  "network": "admob",
  "waterfall": {
    "banner": ["admob", "unity", "ironsource"],
    "interstitial": ["admob", "ironsource"],
    "rewarded": ["admob"],
    "native": ["admob"],
    "appOpen": ["admob"]
  }
}

What happens with a typo

Nothing fails silently and nothing throws. A line that is not valid is skipped, the rest of the list is kept, and Console → Status, check App config written to Firestore, turns red with the reason, for example:

LineStatus message
admobbWaterfall banner line 1 "admobb" skipped: unknown network (admob, unity, ironsource).
unity in the native listWaterfall native line 1 "unity" skipped: unity has no native format in the app.
admob twiceWaterfall banner line 2 "admob" skipped: listed twice.

If every line of a format is skipped, the app uses the network selected in Network (one-network mode) for that format. In the app a network that has no ad (no fill) or reports an error is passed over, and the next one in the list is tried; when none fills, nothing is shown.

Console Ads page with the Show ads master switch, How ads are filled, the one-network selection and the banner waterfall list with admob
Console → Ads: master switch Show ads, How ads are filled, the one-network choice and the waterfall lists (read-only demo console)

07Step 3 · Switch on placements

PlacementConsole fieldDefault
App-open adApp-open adoff
Banner on the home screenBanner on the home screenoff
Banner in the galleryBanner in the image galleryoff
Native ad in the assistant listNative ad after every n assistants0 = off
InterstitialInterstitial after every n messages; Seconds between two interstitials (minimum 30, default 120)0 = off; never shown while an answer streams
RewardedRewarded ad unlocks extra messages / Rewarded ad unlocks an imageoff

Then turn on the master switch Show ads and save. Users on a plan with "No ads" and Remove ads users never see ads.

09Rewarded ads and server-side verification

A rewarded ad gives the user one extra message or one image after they watch it. How the reward is confirmed depends on the network:

NetworkHow the reward is confirmed
AdMob, SSV off (default)The app reports the completed ad; the backend issues a single-use reward token (valid 10 minutes).
AdMob, SSV on (optional)The backend issues the token only after AdMob's signed callback for that ad has arrived.
Unity Ads, ironSource LevelPlayTrusted from the app. Muse AI has no server-side verification for these networks; the app reports the completed ad and the backend issues the token.
Unverified rewards are capped

Every rewarded unlock, verified or not, counts against Free: extra messages unlocked by a rewarded ad per day (Console → Limits, default 3 per user). With Unity Ads or LevelPlay a modified app could claim rewards without watching ads, up to that daily cap. Keep the cap low, or serve rewarded ads with AdMob and switch SSV on.

Switch on AdMob SSV

  1. AdMobAdMob → your rewarded ad unit → Server-side verification → callback URL <API_BASE_URL>/v1/rewarded/ssv → Verify URL → Save (click path).
  2. ConsoleAds → Rewarded ads: server-side verification (AdMob SSV) on, Save.
  3. Only AdMob for rewardedWith SSV on, every rewarded unlock waits for AdMob's callback. Use it only when AdMob serves all rewarded ads (one network AdMob, or AdMob alone in the rewarded waterfall); a Unity or LevelPlay rewarded ad would then never be confirmed.
  4. How it worksThe app sets the ad's SSV user_id to the user's id and custom_data to a random nonce. The backend checks the callback's signature with Google's published keys. Until the callback has arrived, the app's request answers 404 not_found ("The reward is not confirmed yet. Try again in a few seconds.") and retries.

10Common ad problems

Ads do not show although the setup looks right

Go through these in order; the first one that fails is usually the cause.

  1. Status pageConsole → Status, check Ad ids set for what is switched on. It names every id a release build still needs, for example "Release builds show no ad without these ids — AdMob: androidBanner, iosBanner", and says "Ads are on but every placement is off" when no placement is switched on.
  2. Master switch and placementConsole → Ads: Show ads on, and the placement itself on (banner on home, interstitial every n messages, and so on). Save.
  3. The app has the new settingsThe app reads the configuration when it starts, and the API caches it for 60 seconds. Close the app fully and open it again.
  4. The user may see no adsUsers on a plan with "No ads" and users who bought Remove ads never see ads. Test with a free account.
  5. Interstitial timingAn interstitial needs the set number of messages and the minimum seconds since the last one (default 120), and never appears while an answer is streaming.
  6. Release build with an empty unitA release build has no test fallback: an empty unit id means no ad of that format.
  7. Unity Ads or LevelPlayThey are used only when the game id / app key and the rewarded unit are set for that platform.
  8. The network has no ad yetNew ad units and accounts often show no fill for hours, and AdMob serves limited ads until your app and account are reviewed and app-ads.txt is verified. Consent matters too: in the EEA and UK a user who has not answered the consent form gets no personalised ads.
  9. Device logRun the debug build with flutter run and read the device log (Android Studio Logcat or the Xcode console). The network SDKs print their own load errors there, for example AdMob's "Ad failed to load" with an error code (3 = no fill). An exception inside an adapter is logged under muse_ai as ad admob:, ad unity: or ad ironsource:.

Test ids shipped in a release build

  • AdMob app id: the native files ship Google's test app id. A store build with it shows no paid ads. Run tool/check_ad_ids.sh --release from app/ before every store build; it fails while the test app id is still there.
  • Unit ids: test units are used only in debug builds (kDebugMode); a release build never falls back to them. So a release build shows test ads only if someone typed a test unit into the console. Check the three id pages: no value may start with ca-app-pub-3940256099942544.
  • Unity Ads: test mode is on only in debug builds. Make sure test mode is not forced for your game id in the Unity dashboard's testing settings.
  • Never test with your own live ads in a release build; add your phone as a test device in each network instead.

SSV callbacks never arrive

With Rewarded ads: server-side verification on, the app shows the rewarded ad, then asks the backend for the reward up to 8 times, 2 seconds apart. If AdMob's callback has not arrived by then, the user gets no reward.

  1. Callback URLAdMob → the rewarded ad unit → Server-side verification: exactly <API_BASE_URL>/v1/rewarded/ssv, over HTTPS, reachable from the internet (not localhost, not an emulator). Press Verify URL: the backend answers 200 to AdMob's test.
  2. Console switchConsole → Ads → Rewarded ads: server-side verification (AdMob SSV) on and saved. Without it the callback answers 404 "Server-side verification is not enabled."
  3. Right ad unitThe SSV URL is set per ad unit. The unit in Console → AdMob ids → rewarded must be the one that has the callback.
  4. Only AdMobUnity Ads and LevelPlay never send AdMob callbacks. With SSV on, the rewarded waterfall must be admob only.
  5. LogsFirebase console → Functions → Logs for /v1/rewarded/ssv: no request at all = AdMob cannot reach the URL; 400 Invalid signature or AdMob SSV keys unavailable = the function cannot load Google's verifier keys (check outbound network).
  6. DelayAdMob usually calls within seconds, but it can be slower on new ad units. Test on a real device with a test device id, not in the web demo (SSV is off in demo mode).

More answers: Troubleshooting → rewarded ads.

11Ad revenue in the console

Ad revenue is "not measured" unless you connect AdMob reporting (Console → Ad revenue reporting: AdMob publisher id and AdMob API OAuth credentials) and pull finished days on the Revenue centre page, or record payouts by hand with a reference (the way to record Unity Ads and LevelPlay income). Nothing is estimated.

12Network approval

Each network reviews your app and account before serving real ads, and pays under its own terms and thresholds. While you wait, keep testing with test ads; never click your own live ads.