Google Ad Manager and AdMob mediation
This article shows you how to deliver Teads ads — Media, Banner and Interstitial — in a Flutter app through AdMob or Google Ad Manager (GAM) mediation.
Your app requests ads with Google's google_mobile_ads plugin; AdMob then calls Teads through the native Teads adapter on each platform. There is no Dart-side Teads API involved — you add the native adapters to the Android and iOS projects and configure custom events in the AdMob or GAM dashboard.
The plugin's example app, shipped with the teads_flutter package, includes working AdMob Banner, Interstitial and Media screens.
Prerequisites
google_mobile_adsintegrated per Google's Flutter quick start, including the AdMob app ID inAndroidManifest.xmlandInfo.plist— the Google Mobile Ads SDK requires it- The platform requirements in Getting Started
- A Teads placement set up by your publisher manager
Installation
Android
Add the adapter to android/app/build.gradle, at the same version as the Teads SDK the plugin depends on. It resolves from the Teads Maven repository, which the plugin registers for your build (see the installation note if your app declares repositories in settings.gradle):
dependencies {
implementation("tv.teads.sdk.android:admobadapter:6.2.3@aar") { transitive = true }
}
iOS
How you add the adapter depends on which dependency manager your app uses for plugins.
Swift Package Manager (Flutter's default since 3.44):
- In Xcode, open the Runner project → Package Dependencies → add
https://github.com/teads/TeadsSDK-iOSwith Up to Next Major Version from 6.2.2. The plugin pinsTeadsSDKto an exact version from the same package (6.2.2 today), so a requirement that excludes that version conflicts with the pin and Swift Package Manager fails to resolve. An open range follows the plugin when its pin moves. - Link the
TeadsAdMobAdapterproduct to the Runner target. - Register the adapter.
TeadsAdMobAdapter pod with Swift Package ManagerThe pod depends on the TeadsSDK pod, while the plugin brings TeadsSDK in as a Swift package — the app would embed TeadsSDK.framework twice and fail to build with Multiple commands produce …/TeadsSDK.framework.
CocoaPods: add the pod to ios/Podfile at 6.2.2, the version of TeadsSDK the plugin pins (the adapter pod requires that exact TeadsSDK), then pod install:
pod 'TeadsAdMobAdapter', '6.2.2'
Register the adapter (iOS)
Required with Swift Package Manager. The Google Mobile Ads SDK instantiates the adapter's classes by name from your dashboard configuration, so nothing in your code references them and the linker can strip them — the app runs normally while Teads never serves. Call TeadsAdMobMediation.register() in ios/Runner/AppDelegate.swift, before the Google Mobile Ads SDK starts:
import TeadsAdMobAdapter
// In application(_:didFinishLaunchingWithOptions:),
// before GeneratedPluginRegistrant.register(with: self):
TeadsAdMobMediation.register()
See the iOS AdMob guide for how to diagnose a stripped build.
Define the custom events
In the AdMob dashboard (custom event docs) or in Google Ad Manager, add Teads as a custom event on the ad unit's mediation group, one per platform:
| Format | Android class name | iOS class name | Parameter |
|---|---|---|---|
| Media | tv.teads.adapter.admob.TeadsAdapter | GADMAdapterTeadsBanner | Teads placement ID (PID) |
| Banner | tv.teads.adapter.admob.TeadsAdapter | GADMAdapterTeadsBanner | JSON string (below) |
| Interstitial | tv.teads.adapter.admob.TeadsInterstitialAdapter | GADMAdapterTeadsInterstitial | JSON string (below) |
Only Media takes a PID. For Banner and Interstitial the parameter is a JSON string with the three required keys articleUrl, widgetId and installationKey, exactly as in the native guides (Android · iOS):
{"articleUrl":"https://example.com/article","widgetId":"INT_APP_1","installationKey":"NANOWDGT01"}
Production values come from your account manager.
Formats
Request ads with google_mobile_ads as usual. Initialize it once at startup, next to TeadsSdk.configure:
await MobileAds.instance.initialize();
Media
AdMob hosts Teads Media through a banner-shaped view that acts as a proxy for the Media placement. Request a medium rectangle:
BannerAd(
adUnitId: 'YOUR_MEDIA_AD_UNIT_ID',
size: AdSize.mediumRectangle,
request: const AdRequest(),
listener: BannerAdListener(
onAdLoaded: (ad) {
if (!mounted) {
ad.dispose();
return;
}
setState(() => _mediaAd = ad as BannerAd);
},
onAdFailedToLoad: (ad, error) => ad.dispose(),
),
).load();
Banner
BannerAd(
adUnitId: 'YOUR_BANNER_AD_UNIT_ID',
size: AdSize.banner,
request: const AdRequest(),
listener: BannerAdListener(
onAdLoaded: (ad) {
if (!mounted) {
ad.dispose();
return;
}
setState(() => _bannerAd = ad as BannerAd);
},
onAdFailedToLoad: (ad, error) => ad.dispose(),
),
).load();
Render a loaded BannerAd with AdWidget(ad: ad) inside a SizedBox of the requested size, wrapped in a ClipRect — the mediated creative's native view doesn't reliably clip itself to the requested size, so without it the creative can draw outside its box. dispose() the ad with your State.
ClipRect(
child: SizedBox(
width: ad.size.width.toDouble(),
height: ad.size.height.toDouble(),
child: AdWidget(ad: ad),
),
)
Interstitial
Load the ad ahead of time, keep it, and show it at a natural break in your app — not straight from onAdLoaded. Dispose it when it is dismissed and when showing fails.
InterstitialAd? _interstitial;
void _load() {
InterstitialAd.load(
adUnitId: 'YOUR_INTERSTITIAL_AD_UNIT_ID',
request: const AdRequest(),
adLoadCallback: InterstitialAdLoadCallback(
onAdLoaded: (ad) {
if (!mounted) {
ad.dispose();
return;
}
_interstitial = ad;
},
onAdFailedToLoad: (error) => debugPrint('Interstitial failed: ${error.message}'),
),
);
}
// Call at a natural break, e.g. between levels or after an article.
void _showAtNaturalBreak() {
final ad = _interstitial;
if (ad == null) return;
_interstitial = null;
ad.fullScreenContentCallback = FullScreenContentCallback(
onAdDismissedFullScreenContent: (ad) => ad.dispose(),
onAdFailedToShowFullScreenContent: (ad, error) => ad.dispose(),
);
ad.show();
}
Also dispose() any ad you are still holding in your State's dispose().
For per-format mediation settings on the native side (page URL, ad resizing, event listeners), see the native guides: Android · iOS.
Checklist
- ✅ Adapters added on both platforms, at the plugin's Teads SDK version
- ✅ iOS:
TeadsAdMobAdapterfrom the Swift package (not the pod) with SPM, plusTeadsAdMobMediation.register() - ✅ Custom events defined for each format and platform
- ✅ Test a Release build on a device — adapter stripping only shows up in optimised builds
- ✅ Ensure you comply with privacy legal requirements (GDPR/CCPA/GPP)
- ✅ Comply with app-ads.txt