Compose Multiplatform AdMob SDK for Android and iOS
Six AdMob formats on Android and iOS behind one Kotlin API — suspend functions, StateFlow, and UMP consent wired into initialization.
Supported formats
Hover or focus a format to see where its ad region lands on screen.
- BannerInline rectangular ad anchored inside Compose layout.
- InterstitialFull-screen ad shown at a natural transition point.
- RewardedFull-screen ad that grants a reward on completion.
- Rewarded interstitialFull-screen rewarded ad shown at a natural transition point.
- App-openFull-screen ad shown when the app returns to the foreground.
- NativeCompose-rendered ad built from a typed layout DSL and pooled across screens.
Quick start
Section titled “Quick start”The integration has two required lines: one Maven dependency in commonMain, and one initialization call at the root of the app that gathers consent and starts Mobile Ads in a single step. The full setup — version catalogs, the Gradle plugin, Kotlin/Native test linking, the iOS-only Info.plist keys, and the doctorIos check — lives in the Quickstart guide.
kotlin { sourceSets { commonMain.dependencies { implementation("dev.avinya.ads:admob-cmp:1.1.0") } }}// commonMain — initialize once at the rootadManager.gatherConsentAndInitialize( AdConfig( androidAppId = TestAdIds.ANDROID_APP_ID, iosAppId = TestAdIds.IOS_APP_ID, testMode = true, ))On iOS, the production ordering is UMP consent, then ATT tracking authorization, then initialize with ConsentMode.InitializeOnlyIfAlreadyAllowed. See the iOS setup guide for the two Swift Package Manager package URLs and the three Info.plist keys.
Capability comparison
Comparison of admob-cmp against the basic-ads Compose Multiplatform ads library, with the public documentation snapshot dated 31 July 2026.
| Capability | AdMob CMP | basic-ads |
|---|---|---|
| Banner ads | Yes | Yes |
| Interstitial ads | Yes | Yes |
| Rewarded ads | Yes | Yes |
| Rewarded interstitial ads | Yes | Yes |
| App-open ads | Yes | Not offered |
| Native ads | Yes | Not offered |
| Native ad layout DSL and pooling | adLayout {} plus NativeAdPool max-size accounting | Not applicable |
| UMP consent inside initialization | gatherConsentAndInitialize, three consent strategies, privacy-options form | Consent request |
| iOS ATT ordering | tracking authorization between consent and initialize | Not documented |
| Paid and revenue events | AdEvent.Paid with AdValue and ResponseInfo | Not documented |
| Mediation adapter hooks | AdInitializationHook at three initialization points | Not documented |
| Kotlin/Native test linking | Published dev.avinya.ads.admob-cmp Gradle plugin | Not addressed |
| Generated API reference | Yes | Yes |
| Maven Central publication | Yes | Yes |
Comparison verified on 31 July 2026 from the public documentation of both projects. "Not documented" here means that basic-ads' public documentation does not describe this capability; it is a statement about documentation coverage, not a judgement on the basic-ads maintainer. basic-ads is the older and larger project in this space and was the earlier publisher of a generated API reference for a Compose Multiplatform ads library. Corrections are welcome — please open an issue on GitHub.
Why this exists
Putting ads into a Compose Multiplatform app meant leaving Compose. The Google Mobile Ads SDKs are Android and iOS libraries with callback-based APIs, so the shared module ended up holding an expect/actual seam, two sets of platform glue, and a consent flow bolted on afterwards.
Samples and libraries already covered this ground, and they helped. What was still wanted was ads shaped like the rest of a Compose Multiplatform codebase: composables for the ad surfaces, suspend functions and StateFlow for the lifecycle, and consent gathered as part of initialization rather than as a step to remember.
So it was built inside an app that was being written, then extracted once the shape had settled. The APIs here are the ones that had to hold up on real screens: a native ad pool with max-size accounting, retry and cache behaviour with the numbers written down, and an iOS ordering — consent, then tracking authorization, then initialize — that the library sequences for you.
Compatibility and ordering
- Kotlin
- 2.3.20
- Compose Multiplatform
- 1.11.1
- Android
- minSdk 26
- iOS
- deployment target 15.0
The Kotlin klib does not promise binary compatibility across minor versions; re-resolve the klib when you bump the SDK.
Consent, ATT, and initialize sequence
Platform support matrix
| Format | Android — GMA Next-Gen, API 26+ | iOS — GMA 13.x, iOS 15+ | Notes |
|---|---|---|---|
| Banner | Supported | Supported | Anchored adaptive, inline adaptive, fixed and fluid; collapsible on both platforms |
| Interstitial | Supported | Supported | TTL'd FIFO cache, 1 hour |
| Rewarded | Supported | Supported | RewardEarned event |
| Rewarded interstitial | Supported | Supported | Same controller shape as Rewarded |
| App-open | Supported | Supported | AppOpenAdCoordinator, cooldowns, blocking; cache TTL 4 hours |
| Native | Supported | Supported | adLayout DSL and pooling on both; iOS renders through UIKit |
| Capability | Android | iOS | Notes |
|---|---|---|---|
| UMP consent and privacy-options form | Supported | Supported | canRequestAds gates every request on both platforms |
| App Tracking Transparency | Not applicable | Supported | Android has no ATT: adManager.tracking always reports AdTrackingAuthorization.NotApplicable, and the AD_ID manifest permission governs the advertising id there instead |
| Mediation adapters | Supported | Supported | No adapters are bundled; add the ones you need |
| Paid and revenue events | Supported | Supported | AdEvent.Paid carries AdValue and response info |
| Native video events | Not available | Supported — five events | iOS emits VideoStarted, VideoPlayed, VideoPaused, VideoEnded and VideoMuted through GADVideoControllerDelegate. The Android GMA Next-Gen SDK exposes no equivalent callback surface on NativeAd, so Android emits none. This is an upstream SDK gap, not an admob-cmp omission — do not rely on native video events for cross-platform logic. |
| immersiveMode, customClickGesture, publisherProvidedId, categoryExclusions, skipUninitializedAdapters | Supported | Silently ignored | Android-only request options |
| customTargeting, placementId | Supported | Supported | Mapped on both platforms; placementId maps to placementID on iOS |
Roadmap
- Swift Package Manager dependency import
- Gated on four unmet upstream conditions (swiftPMDependencies); Maven-consumer propagation remains an open unknown and the project refuses to depend on an Alpha build-tool feature.
- Native video events on Android
- Blocked on the upstream SDK. iOS exposes GADVideoControllerDelegate with five video events; no equivalent Android callback surface is available.