teads_flutter

Teads video advertising and content recommendations in one Flutter plugin, with a single Dart API for iOS and Android.

Placement Dart API What it is
Feed FeedPlacement SmartFeed — a self-paginating recommendations feed
Media (InRead) MediaPlacement Video/display ad rendered inline in your content
Banner BannerPlacement Banner slot, with runtime dark-mode toggling
Interstitial InterstitialPlacement Fullscreen ad: preload, then present. Not a widget
Recommendations Recommendations.fetch Recommendation data — you build the list UI

Media Native is not supported.

Documentation: the full guide — installation, every placement, events, privacy and consent, troubleshooting — is at developers.teads.com. The API reference is on pub.flutter-io.cn.

Requirements

Flutter / Dart 3.44+ / 3.12+
iOS deployment target 15.0+, CocoaPods
Android minSdk 24, compileSdk 36, NDK 27.1.12297006+, JDK 17 or 21; Kotlin 2.2.20+, AGP 8.11.1+, Gradle 8.14.3+

Installation

flutter pub add teads_flutter

Android

  1. Add the Teads Maven repository, in android/build.gradle (allprojects { repositories { … } }) or in android/settings.gradle's dependencyResolutionManagement if your project centralizes repositories:

    maven { url "https://teads.jfrog.io/artifactory/SDKAndroid-maven-prod" }
    
  2. Declare an AdMob application ID in AndroidManifest.xml. This is required even if you don't use AdMob: the native SDK depends on play-services-ads, which crashes at app start without one.

    <meta-data
        android:name="com.google.android.gms.ads.APPLICATION_ID"
        android:value="ca-app-pub-3940256099942544~3347511713" /> <!-- Google's sample ID; use your own if you monetize through AdMob -->
    
  3. Pin the NDK in android/app/build.gradle:

    android {
        ndkVersion = "27.1.12297006" // or newer
    }
    

No ProGuard/R8 rules are needed; the plugin ships its own.

iOS

Set platform :ios, '15.0' in ios/Podfile, then pod install. TeadsSDK is resolved from the CocoaPods trunk automatically.

To request the IDFA, add a usage description to ios/Runner/Info.plist — without it iOS denies the request without prompting:

<key>NSUserTrackingUsageDescription</key>
<string>Allows us to show you more relevant ads.</string>

Usage

Configure the SDK once, before creating any placement:

import 'package:flutter/material.dart';
import 'package:teads_flutter/teads_flutter.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await TeadsSdk.configure('YOUR_APP_KEY');
  runApp(const MyApp());
}

Then place ads in your widget tree. Placements size themselves — don't wrap them in a fixed-height box.

MediaPlacement(
  config: MediaPlacementConfig(
    pid: 84242,
    articleUrl: 'https://example.com/article/123',
  ),
  onReady: () => debugPrint('Ad ready'),
  onFailed: (error) => debugPrint('Failed: ${error.reason}'),
)

FeedPlacement(
  config: FeedPlacementConfig(
    widgetId: 'MB_1',
    installationKey: 'NANOWDGT01',
    articleUrl: 'https://example.com/article/123',
  ),
)

Interstitial is created, loaded and shown imperatively; Recommendations returns data for you to render. See the Integration Guide for every placement.

iOS App Tracking Transparency: call TeadsPrivacy.requestTrackingAuthorization() from your first screen, not before runApp. On a physical device the prompt's completion never fires while no UI is on screen, so awaiting it early hangs the app on a white screen. It returns null on Android, meaning "not applicable".

Things to know

  • The widget ID selects the format. Pointing Banner or Interstitial at a Feed widget ID (such as MB_1) serves a feed, which looks like a broken placement.
  • Feed's widgetIndex is a coordination key, not a position. A placement with a widgetIndex other than 0 waits for a widgetIndex: 0 placement on the same page; if there is none, the ad never loads.
  • Recommendations.registerClick reports the click. Call it when the user actually taps a recommendation, never ahead of time.
  • Recommendations need an AdChoices icon. Show a clickable AdChoices icon above your recommendations list that opens await Recommendations.adChoicesUrl, plus the per-item disclosure icon on paid items. Both are required to ship. Recommendations.setTestRtb(true) forces paid items for testing, and only works with TeadsSdk.setTestMode(true) also set — remove both before release.
  • Always dispose() an InterstitialPlacement. It holds a native WebView.
  • Use one live BannerPlacement at a time. The native SDK's test-display setting is process-wide, so the most recently created banner wins.
  • Android emulator can't load the Feed? Emulators often fail to resolve the feed's asset domain. Boot the emulator with -dns-server 8.8.8.8,8.8.4.4.

Trying it out

These public test IDs serve demo creatives with no live campaign:

Placement widgetId installationKey articleUrl
Feed MB_1 NANOWDGT01 https://mobile-demo.outbrain.com/
Banner MB_10 NANOWDGT01 https://mobile-demo.outbrain.com/
Interstitial INT_MW_1 NANOWDGT01 https://mobile-demo.outbrain.com

Media uses pid: 84242; Recommendations uses widget ID SDK_1. The example/ app wires up every placement with these defaults.

Testing your integration

TeadsSdk, TeadsPrivacy and Recommendations expose injectable interfaces, and test doubles live in a separate import so they never ship in your production code:

import 'package:teads_flutter/teads_flutter_mocks.dart';

Known limitations

  • Media Native is not supported.
  • One live BannerPlacement at a time (see above).

Support

Integration questions go to your Teads Partner Manager; see Support.

License

Apache License 2.0 — see LICENSE and NOTICE. The license covers this plugin's source only; the native TeadsSDK (iOS) and tv.teads.sdk.android:sdk (Android) binaries it depends on are distributed separately under their own terms.

Contributing

This plugin is developed by Teads. Teads developers: start from docs/development.md in the source repository.

Libraries

teads_flutter
Flutter SDK for Teads in-app ad formats.
teads_flutter_mocks
Test doubles for package:teads_flutter's injectable interfaces.