Skip to main content

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.


Sample App

The plugin's example app, shipped with the teads_flutter package, includes working AdMob Banner, Interstitial and Media screens.

Prerequisites​

  • google_mobile_ads integrated per Google's Flutter quick start, including the AdMob app ID in AndroidManifest.xml and Info.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):

  1. In Xcode, open the Runner project → Package Dependencies → add https://github.com/teads/TeadsSDK-iOS with Up to Next Major Version from 6.2.2. The plugin pins TeadsSDK to 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.
  2. Link the TeadsAdMobAdapter product to the Runner target.
  3. Register the adapter.
Do not use the TeadsAdMobAdapter pod with Swift Package Manager

The 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:

FormatAndroid class nameiOS class nameParameter
Mediatv.teads.adapter.admob.TeadsAdapterGADMAdapterTeadsBannerTeads placement ID (PID)
Bannertv.teads.adapter.admob.TeadsAdapterGADMAdapterTeadsBannerJSON string (below)
Interstitialtv.teads.adapter.admob.TeadsInterstitialAdapterGADMAdapterTeadsInterstitialJSON 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();
The slot is fixed at 300x250 from Dart

The page URL and ad resizing are Teads adapter settings that live on the native side. The Flutter app cannot pass the page URL or resize the slot, so a mediated Media ad stays in its 300x250 slot. To set them, configure the adapter natively: Android · iOS.

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: TeadsAdMobAdapter from the Swift package (not the pod) with SPM, plus TeadsAdMobMediation.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