Flutter Prakash Ads (flutter_prakash_ads)

pub package Flutter Google Mobile Ads License Zero DI Policy Compliant Publisher

An enterprise-grade, policy-compliant, standalone Google Mobile Ads package for Flutter applications. Built with zero dependency-injection lock-in, reactive "Remove Ads" toggles, offline fallback house ads, unified analytics telemetry, and ready-to-use Agent Skills for autonomous AI integration.


📸 Showcase & Interactive Previews

1. Feed Integration & Banners 2. Rich Native Ad Templates 3. Rewarded Content & Medium Ads
Clean Feed with In-line Native Ad and Bottom Anchored Adaptive Banner Large Fluid Medium Native Ad Card with Policy Badge and Install CTA Gated Rewarded Video Ad Unlock Trigger and Sponsored Ad Unit
Anchored Adaptive Banner & Small Native Ad Fluid Medium Native Ad Template (350px) Gated Rewarded Video Trigger & Inline 300x250

🎥 Watch Full Video Demonstration (MP4)

The video walk-through demonstrates:

  • Instant App Open Ad cold-start transition without UI freezing.
  • 🔄 Smooth Adaptive Banner & Native Ad Rendering inline within scrollable feed lists.
  • 🎁 Rewarded Video Ad Flow unlocking gated content with coin/reward callbacks.
  • 🚫 Instant "Remove Ads" (Ad-Free Mode) hiding all mounted banners and native ads in real-time.
  • 🌐 Automatic Offline House Ad Fallback when connectivity is lost or fill fails.

✨ Features

  • 🛡️ Zero DI Lock-in: Fully standalone. Works out of the box with Riverpod, BLoC/Cubit, Provider, GetX, or vanilla Flutter without requiring injectable or get_it.
  • ⚙️ One-Line Production/Test Switching: Switch seamlessly between official Google test ads and production AdMob units using AdManager.setRealAds(...).
  • 💎 Reactive "Remove Ads" (IAP): Instantly hide and dispose all mounted banner and native ads across the widget tree with AdManager.setAdsEnabled(false).
  • 🎨 Custom / House Ads & Offline Fallbacks: Render promotional or offline ads (CustomAdModel) with asset/network images, custom badges, and centralized click routing (AdManager.onCustomAdClicked).
  • 📊 Unified Analytics Telemetry: Capture all lifecycle events (Loaded, Failed, Showed, Dismissed, Clicked, Impression, Paid / ILRD, Reward Earned) via AdManager.onAdEvent or AdManager.adEventStream for logging to Firebase Analytics, Adjust, AppsFlyer, etc.
  • 🤖 Agentic Coding Ready (SKILL.md): Includes official agent skill instructions in .agents/skills/flutter-prakash-ads/SKILL.md for AI pair programmers and autonomous coding assistants.
  • 📐 Anchored Adaptive Banners: Built-in SmartBannerAdView.getAnchoredAdaptiveAdSize(context) to maximize fill rates and eCPMs.
  • 🌐 Smart Network Awareness: Real-time network detection with seamless fallback widgets when offline or when AdMob fails to fill.
  • 👶 COPPA & Google Play Families Policy Ready: Configure child-directed treatment, age of consent, and content rating tags with AdManager.updateRequestConfiguration(...).
  • 🔒 GDPR / UMP Consent Ready: Built-in ConsentManager for EEA/UK GDPR compliance and privacy options revocation forms.
  • ⏱️ AdMob & Play Policy Guardrails:
    • Anti-Stacking Collision: Prevents App Open, Interstitial, and Rewarded ads from ever presenting simultaneously.
    • 4-Hour Max-Age Expiration: Automatically evicts stale cached impressions.
    • 30s Interstitial Throttling: Prevents rapid ad spam and user fatigue.
    • App Open Cold-Start & Background Guards: 4-second timeout deadline and 15-second background threshold.
    • CLS Prevention: Fixed dimensional bounding prevents Cumulative Layout Shifts and accidental clicks.

📱 Supported Ad Formats

Format Widget / Service Description
Banner SmartBannerAdView Adaptive / fixed banners with offline fallback and CLS protection
Native SmartNativeAdView Small (90px) & Medium (350px) native templates with fallback
Interstitial AdsService.showInterstitialAd Full-screen interstitial with 30s throttling & collision prevention
Rewarded Video AdsService.showRewardedAd Rewarded ad with verified server/client reward callbacks
Rewarded Interstitial AdsService.showRewardedInterstitialAd Rewarded interstitial format with reward completion callbacks
App Open AppOpenAdManager Policy-compliant cold-start & resume app open ads

🚀 Getting Started

1. Add Dependency

Add flutter_prakash_ads to your pubspec.yaml:

dependencies:
  flutter_prakash_ads: ^0.0.2

2. Platform Setup

Android (android/app/src/main/AndroidManifest.xml)

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

<manifest>
    <!-- Recommended Permissions -->
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="com.google.android.gms.permission.AD_ID"/>

    <application>
        <!-- AdMob App ID (Replace with your real Android App ID in production) -->
        <meta-data
            android:name="com.google.android.gms.ads.APPLICATION_ID"
            android:value="ca-app-pub-3940256099942544~3347511713"/>

        <!-- Optional: AdMob initialization and loading optimizations -->
        <meta-data
            android:name="com.google.android.gms.ads.flag.OPTIMIZE_INITIALIZATION"
            android:value="true"/>
        <meta-data
            android:name="com.google.android.gms.ads.flag.OPTIMIZE_AD_LOADING"
            android:value="true"/>
    </application>
</manifest>

iOS (ios/Runner/Info.plist)

Add GADApplicationIdentifier and recommended SKAdNetworkItems:

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

💡 Quick Start & Usage Examples

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

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

  // (Optional) Configure Production Ad Units:
  // AdManager.setRealAds(
  //   androidAppId: 'ca-app-pub-XXX~XXX',
  //   iosAppId: 'ca-app-pub-XXX~XXX',
  //   androidBanner: 'ca-app-pub-XXX/XXX',
  //   iosBanner: 'ca-app-pub-XXX/XXX',
  //   androidInterstitial: 'ca-app-pub-XXX/XXX',
  //   iosInterstitial: 'ca-app-pub-XXX/XXX',
  //   androidRewarded: 'ca-app-pub-XXX/XXX',
  //   iosRewarded: 'ca-app-pub-XXX/XXX',
  //   androidNative: 'ca-app-pub-XXX/XXX',
  //   iosNative: 'ca-app-pub-XXX/XXX',
  //   androidAppOpen: 'ca-app-pub-XXX/XXX',
  //   iosAppOpen: 'ca-app-pub-XXX/XXX',
  // );

  // 1. Request GDPR/UMP Consent
  final consentResult = await AdManager.requestConsent();

  // 2. Initialize AdMob and App Open Ads if allowed by consent
  if (consentResult.canRequestAds) {
    await AdManager.instance.initialize();
    await AdManager.instance.initializeAppOpenAd();
  }

  runApp(const MyApp());
}

2. Display Adaptive / Standard Banner Ads

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

class MyBannerPage extends StatelessWidget {
  const MyBannerPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Banner Ad Example')),
      body: const Center(child: Text('Content Area')),
      bottomNavigationBar: const SafeArea(
        child: SmartBannerAdView(
          adSize: AdSize.banner, // or use default anchored adaptive
          showOfflineFallback: true,
        ),
      ),
    );
  }
}

3. Display Native Ads (Small & Medium Templates)

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

// Small Native Ad (90px height)
const SmartNativeAdView(
  templateType: TemplateType.small,
  cornerRadius: 12.0,
);

// Medium Native Ad (350px height)
const SmartNativeAdView(
  templateType: TemplateType.medium,
  cornerRadius: 12.0,
);

4. Full-Screen Interstitial & Rewarded Ads

final adsService = AdsServiceImpl();

// 1. Preload Interstitial
adsService.loadInterstitialAd();

// 2. Show Interstitial (with 30s policy throttling & collision lock)
adsService.showInterstitialAd(
  onAdDismissedFullScreenContent: () {
    // Navigate to next screen
  },
);

// 3. Show Rewarded Video Ad
adsService.showRewardedAd(
  onUserEarnedReward: (ad, reward) {
    print('User earned ${reward.amount} ${reward.type}');
  },
);

5. Impression-Level Ad Revenue (ILRD / tROAS) Telemetry

Capture exact impression revenue values for analytics providers (Firebase, Adjust, AppsFlyer, Singular):

AdManager.onAdEvent((event) {
  if (event.isPaid) {
    print('Paid Event: ${event.format.name} earned ${event.revenueValue} ${event.currencyCode}');
  }
});

6. Reactive In-App Purchase ("Remove Ads") Toggle

When a user purchases an ad-free subscription or lifetime unlock:

// Globally hide and dispose all mounted banners and native ads instantly
AdManager.setAdsEnabled(false);

📱 Example Application

A complete showcase application demonstrating Clean Architecture, BLoC/Cubit, Injectable DI, offline fallback promotions, and every ad format is located in the example/ directory:

cd example
flutter pub get
dart run build_runner build --delete-conflicting-outputs
flutter run

For full details, see example/README.md.


👨‍💻 Author & Publisher

Developed and published by Prakash Bahadur Chand:


📄 License

This project is licensed under the MIT License - see the LICENSE file for details.