Skip to main content

google_admob_sdk 0.0.9 copy "google_admob_sdk: ^0.0.9" to clipboard
google_admob_sdk: ^0.0.9 copied to clipboard

A Flutter plugin for Google Mobile Ads (AdMob) with centralized Ad Unit ID management, load duration metrics, adKey tracking, and pre-built ad widgets & managers.

Google AdMob SDK for Flutter (google_admob_sdk) #

A comprehensive, production-ready Flutter SDK wrapper for Google Mobile Ads (google_mobile_ads) with built-in Ad Unit ID management per platform, load time performance tracking, Firebase Analytics integration, customizable ProgressIndicators, and pre-built ad widgets & managers.


Features #

  • ⚑ Easy Initialization: Initialize Google Mobile Ads with custom or test configuration in a single line, including COPPA / GDPR-K (ageRestrictedTreatment) and content rating (maxAdContentRating).
  • 🎯 Ad ID Management: Centralized AdIdConfig for Android & iOS supporting 6 ad types (Banner, Interstitial, Rewarded, Rewarded Interstitial, App Open, Native) with fallback to Google official test IDs.
  • πŸ“Š Performance & Event Analytics: Built-in AdAnalyticsLogger supporting FirebaseAdLogger, ConsoleAdLogger, or custom loggers to track ad load duration (ms), impressions, clicks, and load failures with adKey tracking (key_<ad_type>).
  • πŸ–ΌοΈ Adaptive & Collapsible Banner Ads: BannerAdWidget.adaptive(...) auto-calculates full device-width anchored adaptive size, plus collapsiblePlacement: CollapsiblePlacement.bottom (yielding 2x–4x eCPM boost with smart collapsible overlay).
  • 🎬 Interstitial Ad Manager: InterstitialAdManager.shared singleton, Frequency Capping (minShowInterval, canShow), and showAdSafely(...) with countdown warning dialog to prevent accidental clicks (High CTR / Invalid Traffic penalty protection).
  • 🎁 Rewarded Ad Manager & SSV: RewardedAdManager.shared and showAdSafely(...) with Server-Side Verification (ServerSideVerificationOptions) preventing reward fraud.
  • πŸ† Rewarded Interstitial Ad Manager: RewardedInterstitialAdManager.shared with safe frequency capping, SSV, and preloaded lifecycle management.
  • πŸšͺ App Open Ad & Automated Reactor: AppOpenAdManager.shared with built-in ad expiration check (4 hours max age) and AppLifecycleReactor for automated background-to-foreground ad triggers.
  • 🎨 Native Ad Widget & Cache Pool: NativeAdWidget with keepAlive: true and NativeAdPool cache to prevent impression spam (24-34 imp/user) in ListView/TabBarView, plus Figma presets (cls, mediaView, interstitial), custom layouts, and fullscreen native dialogs.
  • 🀝 Bidding & Mediation Setup: Out-of-the-box support and native configuration guides for AppLovin, Unity Ads, Pangle, Meta Audience Network, and Mintegral.

Getting Started #

1. Add Dependency #

Add google_admob_sdk to your pubspec.yaml:

dependencies:
  flutter:
    sdk: flutter
  google_admob_sdk:
    path: ../google_admob_sdk # Or git / pub package path

2. Platform Configuration #

Android Setup (AndroidManifest.xml)

Add your AdMob App ID inside the <application> tag:

<manifest>
    <application>
        <meta-data
            android:name="com.google.android.gms.ads.APPLICATION_ID"
            android:value="ca-app-pub-3940256099942544~3347511713"/> <!-- Test App ID -->
    </application>
</manifest>

iOS Setup (Info.plist)

Add GADApplicationIdentifier to ios/Runner/Info.plist:

<key>GADApplicationIdentifier</key>
<string>ca-app-pub-3940256099942544~1458002511</string> <!-- Test App ID -->
<key>SKAdNetworkItems</key>
<array>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>cstr6suwn9.skadnetwork</string>
    </dict>
</array>

Usage #

1. SDK Initialization #

Initialize GoogleAdmobSdk in your main() function:

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

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await GoogleAdmobSdk.initialize(
    config: AdIdConfig(
      android: const PlatformAdIds(
        bannerId: 'ca-app-pub-xxx/android_banner',
        interstitialId: 'ca-app-pub-xxx/android_interstitial',
        rewardedId: 'ca-app-pub-xxx/android_rewarded',
        rewardedInterstitialId: 'ca-app-pub-xxx/android_rewarded_interstitial',
        appOpenId: 'ca-app-pub-xxx/android_app_open',
        nativeId: 'ca-app-pub-xxx/android_native',
      ),
      ios: const PlatformAdIds(
        bannerId: 'ca-app-pub-xxx/ios_banner',
        interstitialId: 'ca-app-pub-xxx/ios_interstitial',
        rewardedId: 'ca-app-pub-xxx/ios_rewarded',
        rewardedInterstitialId: 'ca-app-pub-xxx/ios_rewarded_interstitial',
        appOpenId: 'ca-app-pub-xxx/ios_app_open',
        nativeId: 'ca-app-pub-xxx/ios_native',
      ),
    ),
    logger: FirebaseAdLogger(), // Log performance metrics to Firebase Analytics
    enableConsoleLog: true,     // Print ad load duration and events in debug console
    maxAdContentRating: MaxAdContentRating.g, // Optional: Content rating (g, pg, t, ma)
    ageRestrictedTreatment: TagForChildDirectedTreatment.no, // Optional: COPPA / Child-directed
  );

  runApp(const MyApp());
}

2. Banner Ad Widget (Adaptive & Collapsible) #

2.1. Standard Banner with Custom ProgressIndicator:

BannerAdWidget(
  adKey: 'home_bottom_banner',
  screenName: 'scrHome',
  adPlacement: 'scrHome',
  adUnitName: 'Banner_Home',
  adSize: AdSize.banner,
  // Custom ProgressIndicator widget
  progressIndicator: CircularProgressIndicator(
    color: Colors.blueAccent,
    strokeWidth: 3.0,
  ),
  onAdLoaded: (ad) => print('Banner Loaded'),
  onAdFailedToLoad: (error) => print('Banner Failed: $error'),
)

2.2. Anchored Adaptive & Collapsible Banner (2x–4x eCPM Boost):

// Auto-calculates device width anchored adaptive size and requests a collapsible overlay
BannerAdWidget.adaptive(
  adKey: 'home_bottom_collapsible_banner',
  screenName: 'scrHome',
  collapsiblePlacement: CollapsiblePlacement.bottom, // Expandable overlay on initial load
  onAdLoaded: (ad) => print('High-eCPM Collapsible Banner Loaded'),
)

3. Native Ad Widget & Fullscreen Dialog #

Embed NativeAdWidget with built-in presets (mediaView, cls, interstitial, small, dark) or custom styling:

// Using Preset (Blue CTA #1A90FF, 10px rounded corners)
NativeAdWidget(
  adKey: 'feed_native_ad',
  screenName: 'scrHome',
  adPlacement: 'scrHome',
  adUnitName: 'Native_Home',
  templatePreset: NativeTemplatePreset.mediaView,
  height: 320,
  margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
  decoration: BoxDecoration(
    color: Colors.white,
    borderRadius: BorderRadius.circular(10.0),
    boxShadow: const [
      BoxShadow(color: Color(0x0F000000), blurRadius: 8, offset: Offset(0, 2)),
    ],
  ),
)

```dart
// 1. Built-in Presets (Auto-links to native Android XML layouts matching Figma designs):
// - NativeTemplatePreset.cls: CTA button #1A90FF on the RIGHT, MediaView on TOP (Figma Node 70:6183)
// - NativeTemplatePreset.mediaView: CTA button #1A90FF on TOP, MediaView in MIDDLE (Figma Node 70:6182)
// - NativeTemplatePreset.interstitial: Large format layout (Figma Node 70:6181)
NativeAdWidget(
  adKey: 'feed_native_ad',
  templatePreset: NativeTemplatePreset.cls,
  height: 320,
)

// 2. Custom Layout Builder in Flutter (rearrange surrounding elements freely):
NativeAdWidget(
  adKey: 'feed_native_ad',
  templatePreset: NativeTemplatePreset.cls,
  height: 320,
  header: const Text('Sponsored'),
  showCloseButton: true,
  onClose: () => print('Closed'),
  layoutBuilder: (context, adView) {
    return Column(
      children: [
        adView,
        const Text('Tap to view details'),
      ],
    );
  },
)

// 3. Fullscreen Native Interstitial Dialog (Figma Ads Interstitial node 70:6181):
showNativeAdInterstitialDialog(
  context: context,
  adKey: 'native_interstitial_dialog',
  screenName: 'scrInterstitialDialog',
);

// 4. In ListView / PageView (keepAlive: true prevents impression spam on scroll):
ListView.builder(
  itemCount: 20,
  itemBuilder: (context, index) {
    if (index % 5 == 0) {
      return NativeAdWidget(
        adKey: 'feed_native_ad',
        keepAlive: true, // Default: true. Retains state and prevents reload on scroll
        cacheKey: 'feed_native_$index', // Optional: cache in NativeAdPool
        templatePreset: NativeTemplatePreset.cls,
        height: 320,
      );
    }
    return ListTile(title: Text('Item $index'));
  },
);

// 5. 100% Custom Native XML/XIB Layout via factoryId:
NativeAdWidget(
  adKey: 'custom_native_factory',
  factoryId: 'my_custom_factory', // Registered in Android MainActivity / iOS AppDelegate
  height: 300,
)

Registering Custom Native Ad Factory in Android (MainActivity.kt):

import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugins.googlemobileads.GoogleMobileAdsPlugin
import io.flutter.plugins.googlemobileads.NativeAdFactory // TOP-LEVEL INTERFACE in google_mobile_ads 9.x

class MainActivity : FlutterActivity() {
    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        GoogleMobileAdsPlugin.registerNativeAdFactory(
            flutterEngine,
            "my_custom_factory",
            MyCustomNativeAdFactory(layoutInflater)
        )
    }

    override fun cleanUpFlutterEngine(flutterEngine: FlutterEngine) {
        GoogleMobileAdsPlugin.unregisterNativeAdFactory(flutterEngine, "my_custom_factory")
        super.cleanUpFlutterEngine(flutterEngine)
    }
}

πŸ“– Comprehensive Guide: For complete step-by-step XML layouts, drawables, and iOS Swift setup, see doc/CUSTOM_NATIVE_LAYOUTS.md.


4. Interstitial Ad (Shared Instance & Safe Show) #

Use InterstitialAdManager.shared to load and present interstitial ads across your entire app, with built-in Frequency Capping (3-minute cooldown) and Countdown Notice to prevent accidental clicks and invalid traffic penalties:

// Use the shared instance across the whole app
final interstitialManager = InterstitialAdManager.shared;

// 1. Preload Interstitial Ad with Databuckets tracking parameters
await interstitialManager.loadAd(
  adKey: 'level_complete_interstitial',
  screenName: 'scrLevelComplete',
  adPlacement: 'scrLevelComplete',
  adUnitName: 'Inter_LevelPass',
  sessionNumber: 1,
);

// 2. Safely present with cooldown check & warning countdown overlay:
// - Checks if cooldown elapsed (minShowInterval default 180s)
// - Shows brief countdown notice ("Ad starting shortly") before full-screen takeover
// - Always triggers onCompleted so game/app flow is never blocked
// - Fully customizable via countdownTitle, countdownSubtitle, or countdownConfig
await interstitialManager.showAdSafely(
  context: context,
  adKey: 'level_complete_interstitial',
  checkCooldown: true,
  showWarningCountdown: true,
  countdownDuration: const Duration(milliseconds: 1200),
  countdownTitle: 'Ad starting shortly',
  countdownSubtitle: 'Please wait a moment...',
  onCompleted: () {
    // Proceed to next level or resume gameplay
  },
);

5. Rewarded Ad & Rewarded Interstitial Ad (with Server-Side Verification) #

Use RewardedAdManager.shared or RewardedInterstitialAdManager.shared to ensure preloaded rewarded ads are not lost when switching screens. Use ServerSideVerificationOptions to protect against reward fraud:

// Use the shared instance across screens
final rewardedManager = RewardedAdManager.shared;

// Optional: Set Server-Side Verification (SSV) callback metadata
rewardedManager.setServerSideVerificationOptions(
  ServerSideVerificationOptions(
    userId: 'user_12345',
    customData: 'bonus_gold_pack',
  ),
);

await rewardedManager.loadAd(
  adKey: 'extra_lives_rewarded',
  screenName: 'scrShop',
  adPlacement: 'scrShop',
  adUnitName: 'Rewarded_ExtraLives',
);

// Present safely
await rewardedManager.showAdSafely(
  context: context,
  adKey: 'extra_lives_rewarded',
  onUserEarnedReward: (ad, reward) {
    print('User earned: ${reward.amount} ${reward.type}');
  },
  onCompleted: () {
    print('Rewarded flow finished');
  },
);

6. App Open Ad & Automatic Background-to-Foreground Reactor #

Use AppOpenAdManager.shared for app startup or resume ads. Use AppLifecycleReactor to automate background-to-foreground display:

final appOpenManager = AppOpenAdManager.shared;

// Load ad on app launch
await appOpenManager.loadAd(
  adKey: 'app_launch_open_ad',
  screenName: 'scrSplash',
);

// Automate background-to-foreground ad presentation safely
final reactor = AppLifecycleReactor(
  appOpenAdManager: appOpenManager,
  minBackgroundDuration: const Duration(seconds: 15), // Prevent trigger on quick app switch
  minShowInterval: const Duration(minutes: 5),        // Cooldown between app open ads
  canShowAd: () => !isNavigatingPayment,              // Custom bypass condition
);
reactor.listenToAppStateChanges();

Databuckets Data Tracking Plan (Sheet "41") #

google_admob_sdk automatically measures ad performance and logs events fully compliant with the Databuckets Tracking Plan (Sheet 41):

Universal IAA Events #

Event Name Trigger Main Parameters Logged
iaa_request When ad load request starts ad_request_id, ad_format, ad_unit_name, ad_unit_id, ad_mediation, screen_name, session_number
iaa_loaded When ad load succeeds ad_request_id, ad_format, ad_unit_name, ad_unit_id, ad_mediation, screen_name, is_load: 1, load_time
iaa_fail_load When ad load fails ad_request_id, ad_format, ad_unit_name, ad_unit_id, ad_mediation, screen_name, is_load: 0, error_code, error_message
iaa_impression When ad impression occurs ad_request_id, ad_format, ad_unit_name, ad_unit_id, ad_mediation, ad_placement, screen_name, currency, value
iaa_fail_show When ad show fails ad_request_id, ad_format, ad_unit_name, ad_unit_id, ad_placement, screen_name, error_code, error_message
iaa_click When user clicks ad ad_request_id, ad_format, ad_unit_name, ad_unit_id, ad_mediation, ad_placement, screen_name
iaa_complete When full-screen ad ends ad_request_id, ad_format, ad_unit_name, ad_unit_id, ad_placement, screen_name, end_type (done/quit), duration_ad

Parameter Reference #

Note

Format for screen_name & ad_placement: Values representing screen names must strictly follow lowerCamelCase starting with the scr prefix (e.g., scrHome, scrOnboard, scrSplash, scrLevelComplete, scrShop).

When you pass an adKey parameter (e.g. 'home_bottom_banner'), the SDK automatically passes both ad_key and dynamic key_<ad_type> parameters to Firebase Analytics:

Parameter Name in Analytics Value Example Description
ad_key 'home_bottom_banner' Generic ad placement key
key_banner 'home_bottom_banner' Type-specific key for Banner ads
key_interstitial 'level_complete_interstitial' Type-specific key for Interstitial ads
key_rewarded 'extra_lives_rewarded' Type-specific key for Rewarded ads
key_rewardedInterstitial 'bonus_stage_rewarded_interstitial' Type-specific key for Rewarded Interstitial ads
key_appOpen 'app_launch_open_ad' Type-specific key for App Open ads
key_native 'feed_native_ad' Type-specific key for Native ads

AdMob Quality, Show Rate & Match Rate Protection Architecture #

To ensure your app never suffers from low Match Rates (Fill Rate), dropped Show Rates (< 50%), or account-level Invalid Traffic penalties, the SDK includes enterprise-grade guardrails:

1. Ad TTL & Expiration Auto-Invalidation (60 Minutes) #

Google AdMob terms dictate that fullscreen ads expire within 60 minutes (4 hours for App Open). Displaying stale ads results in dropped impressions or policy penalties. All managers (InterstitialAdManager, RewardedAdManager, RewardedInterstitialAdManager, AppOpenAdManager) automatically check isAdAvailable and dispose expired ads immediately:

// Check if ad is available and not expired (within 60m)
if (InterstitialAdManager.shared.isAdAvailable) {
  // Safe to present
}

2. Exponential Backoff & Circuit Breaker (AdRetryPolicy) #

Aggressive ad requests after No-Fill (ERROR_CODE_NO_FILL = 3) can ruin your Ad Unit's Quality Score. The SDK uses an exponential retry strategy (2s $\rightarrow$ 4s $\rightarrow$ 8s $\rightarrow$ 16s $\rightarrow$ 60s) and automatically trips a Circuit Breaker when consecutive failures occur:

// Managers automatically manage retryPolicy
final retryPolicy = InterstitialAdManager.shared.retryPolicy;
print('Is circuit breaker open: ${retryPolicy.isCircuitOpen}');

3. Smart Auto-Reload & Delay Capping #

Eliminate Orphan Preloads (ads loaded upon dismissal that are abandoned when the user leaves the app):

// Globally configure in GoogleAdmobSdk.initialize:
await GoogleAdmobSdk.initialize(
  enableAutoReload: true,
  autoReloadDelay: const Duration(seconds: 5), // Gives user time before preloading next ad
);

4. Realtime AdMob Health Monitor (AdHealthMonitor) #

Diagnose your app's live Match Rate, Show Rate, and CTR during testing and release:

// Access live diagnostic metrics
final health = GoogleAdmobSdk.instance.healthMonitor;
print(health.summary());
// Output:
// AdMob Health Summary:
//   Requests: 12 | Loaded: 10 | Failed: 2
//   Impressions: 8 | Clicks: 1
//   Match Rate: 83.3% | Show Rate: 80.0% | CTR: 12.5%

AdMob Mediation & Bidding (AppLovin, Meta, Mintegral, Unity Ads, Pangle) #

The SDK fully supports third-party ad networks (Mediation Adapters) via Google Mobile Ads Bidding & Waterfall mediation. No Dart code changes are requiredβ€”all mediation adapters hook directly into the underlying Google Mobile Ads SDK lifecycle.

Caution

Why is Bidding Reporting 0.00% Bids in AdMob Dashboard? If your Mediation report shows 0.00% Bids for Unity Ads, AppLovin, or Pangle: The native mediation adapter binaries were not added to your host app's build.gradle.kts (Android) and Podfile (iOS). In-app Bidding requires native SDK binaries in the compiled binary so Google AdMob can request real-time bids. Add the snippets below to enable Bidding immediately:

Android Configuration (android/app/build.gradle.kts): #

dependencies {
    // Google Mobile Ads Mediation Adapters
    implementation("com.google.ads.mediation:applovin:13.1.0.0")
    implementation("com.google.ads.mediation:facebook:6.19.0.0")
    implementation("com.google.ads.mediation:mintegral:16.9.71.0")
    implementation("com.google.ads.mediation:unity:4.13.2.0")
    implementation("com.google.ads.mediation:pangle:6.4.0.6.0")
}

iOS Configuration (ios/Podfile): #

target 'Runner' do
  # Google Mobile Ads Mediation Adapters
  pod 'GoogleMobileAdsMediationAppLovin'
  pod 'GoogleMobileAdsMediationFacebook'
  pod 'GoogleMobileAdsMediationMintegral'
  pod 'GoogleMobileAdsMediationUnity'
  pod 'GoogleMobileAdsMediationPangle'
end

πŸ‘‰ For complete step-by-step setup, Maven repositories, ProGuard rules, SKAdNetworkItems, and Ad Inspector verification, see: doc/MEDIATION_SETUP_GUIDE.md

0
likes
160
points
479
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A Flutter plugin for Google Mobile Ads (AdMob) with centralized Ad Unit ID management, load duration metrics, adKey tracking, and pre-built ad widgets & managers.

Repository (GitLab)
View/report issues

Topics

#ads #admob #advertising #monetization #analytics

License

MIT (license)

Dependencies

firebase_analytics, firebase_core, flutter, google_mobile_ads

More

Packages that depend on google_admob_sdk

Packages that implement google_admob_sdk