google_ads_helper 1.0.1 copy "google_ads_helper: ^1.0.1" to clipboard
google_ads_helper: ^1.0.1 copied to clipboard

A comprehensive Flutter plugin for Google Mobile Ads with easy integration, smart initialization, revenue tracking, and professional widgets.

Google Ads Helper Plugin #

A comprehensive Flutter plugin for Google Mobile Ads with easy integration, smart initialization, revenue tracking, and professional UI widgets.

Features #

Easy Integration - One-line initialization
Smart Loading - Only loads ads with provided IDs
Count-Based Control - Show interstitials every N calls
Auto-Reload - Automatically loads next ad after showing
Revenue Tracking - Built-in revenue calculation and tracking
Professional Widgets - Drop-in UI components
Automatic Retry - Handles ad loading failures gracefully
Debug Helpers - Development tools for testing
Production Ready - Comprehensive error handling

Installation #

Add this to your pubspec.yaml:

dependencies:
  google_ads_helper: ^1.0.0

Then run:

flutter pub get

Quick Start #

1. Initialize in main.dart #

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

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

  // Initialize for reward app (most common)
  await SimpleAdInitializer.initializeForRewardApp(
    rewardedAdUnitId: 'ca-app-pub-XXXXXXXX/XXXXXXXX', // Your real ID
    interstitialAdUnitId: 'ca-app-pub-XXXXXXXX/XXXXXXXX', // Your real ID
    // testDeviceIds: ['YOUR_TEST_DEVICE_ID'], // For testing
  );

  runApp(MyApp());
}

2. Show Ads Anywhere #

// Show rewarded ad
AdHelper.showRewarded(
  onRewardEarned: (reward) {
    print('User earned ${reward.amount} ${reward.type}');
    // Give user reward
  },
  onAdClosed: () => print('Ad closed'),
);

// Show interstitial (with count-based control)
AdHelper.showInterstitial(
  onInterstitialShown: () => print('Ad shown'),
  onAdClosed: () => print('Ad closed'),
);

3. Add Banner Ads #

// Simple banner widget
BannerAdWidget(
  height: 60,
  margin: EdgeInsets.all(10),
)

Initialization Options #

For Reward Apps #

await SimpleAdInitializer.initializeForRewardApp(
  rewardedAdUnitId: 'your-rewarded-id',
  interstitialAdUnitId: 'your-interstitial-id', // Optional
);

For Game Apps #

await SimpleAdInitializer.initializeForGameApp(
  interstitialAdUnitId: 'your-interstitial-id',
  rewardedAdUnitId: 'your-rewarded-id',
  bannerAdUnitId: 'your-banner-id', // Optional
);

Custom Initialization #

await SimpleAdInitializer.initializeWithYourAdIds(
  rewardedAdUnitId: 'your-rewarded-id',
  interstitialAdUnitId: 'your-interstitial-id',
  bannerAdUnitId: 'your-banner-id',
  nativeAdUnitId: 'your-native-id',
  testDeviceIds: ['test-device-id'],
  onAdLoaded: (adType) => print('$adType loaded'),
  onAdError: (error) => print('Error: $error'),
);

Interstitial Count Control #

The plugin has smart interstitial frequency control - ads only show every 3rd call by default:

// This will only show ad every 3rd call
AdHelper.showInterstitial(
  onInterstitialShown: () => print('Ad shown!'),
);

// Force show (bypass count)
AdHelper.showInterstitial(
  forceShow: true,
  onInterstitialShown: () => print('Forced ad!'),
);

// Configure frequency
AdHelper.setInterstitialFrequency(5); // Show every 5th call

// Check if next call will show ad
if (AdHelper.willInterstitialShowNext) {
  print('Next call will show ad!');
}

// Reset count manually
AdHelper.resetInterstitialCount();

Widgets #

BannerAdWidget(
  height: 60,
  margin: EdgeInsets.all(10),
  backgroundColor: Colors.grey[100],
)

Native Ad Widget #

NativeAdWidget(
  height: 200,
  margin: EdgeInsets.all(10),
  borderRadius: BorderRadius.circular(10),
)

Smart Ad Container #

SmartAdContainer(
  height: 200,
  preferredAdType: AdType.native,
  fallbackAdTypes: [AdType.banner],
)

Revenue Tracking #

// Track ad shows
AdRevenueTracker.trackAdShown(AdType.rewarded);

// Get revenue report
final report = AdRevenueTracker.getRevenueReport();
print('Total Revenue: ${report['estimatedRevenue']}');
print('User Rewards: ${report['userRewards']}');
print('App Profit: ${report['appProfit']}');

// Calculate specific revenue
double rewardedRevenue = AdHelper.calculateEstimatedRevenue(
  AdType.rewarded, 10, // 10 rewarded ads
);

Debug Helpers #

// Print ad status
AdDebugHelper.printAdStatus();

// Print revenue report
AdDebugHelper.printRevenueReport();

// Check ad availability
print('Ads ready: ${AdHelper.adsStatus}');
print('Ads loading: ${AdHelper.loadingStatus}');

Test Ad Unit IDs #

For testing, the plugin automatically uses Google's test IDs:

Ad Format Test ID
Banner ca-app-pub-3940256099942544/6300978111
Interstitial ca-app-pub-3940256099942544/1033173712
Rewarded ca-app-pub-3940256099942544/5224354917
Native ca-app-pub-3940256099942544/2247696110

Advanced Usage #

Ad Status Monitoring #

// Check if ads are ready
bool anyAdReady = AdHelper.hasAnyAdReady;
Map<String, bool> adStatus = AdHelper.adsStatus;
Map<String, bool> loadingStatus = AdHelper.loadingStatus;

print('Banner ready: ${adStatus['banner']}');
print('Interstitial ready: ${adStatus['interstitial']}');
print('Rewarded ready: ${adStatus['rewarded']}');
print('Native ready: ${adStatus['native']}');

// Check loading states
if (loadingStatus['rewarded'] == true) {
  print('Rewarded ad is currently loading...');
}

Manual Ad Loading #

// Load specific ad types manually
GoogleAdsHelper.instance.loadBannerAd();
GoogleAdsHelper.instance.loadInterstitialAd();
GoogleAdsHelper.instance.loadRewardedAd();
GoogleAdsHelper.instance.loadNativeAd();

// Load all configured ads
GoogleAdsHelper.instance.loadAllAds();

// Reload specific ad type
GoogleAdsHelper.instance.reloadBannerAd();
GoogleAdsHelper.instance.reloadInterstitialAd();

Advanced Interstitial Controls #

// Get current interstitial statistics
int currentCount = AdHelper.interstitialCallCount;
int frequency = GoogleAdsHelper.instance.interstitialShowEveryCount;
bool willShowNext = AdHelper.willInterstitialShowNext;

print('Interstitial calls: $currentCount/$frequency');
print('Will show on next call: $willShowNext');

// Set custom frequency (default is 3)
AdHelper.setInterstitialFrequency(5); // Show every 5th call
AdHelper.setInterstitialFrequency(1); // Show every call

// Reset count manually (useful for special events)
AdHelper.resetInterstitialCount();

// Force show regardless of count
AdHelper.showInterstitial(
  forceShow: true,
  onInterstitialShown: () => print('Forced interstitial shown!'),
);

Runtime Ad Configuration #

// Update ad unit IDs at runtime
GoogleAdsHelper.instance.updateAdUnitIds(
  bannerAdUnitId: 'ca-app-pub-XXXXXXXX/XXXXXXXX',
  interstitialAdUnitId: 'ca-app-pub-XXXXXXXX/XXXXXXXX',
  rewardedAdUnitId: 'ca-app-pub-XXXXXXXX/XXXXXXXX',
  nativeAdUnitId: 'ca-app-pub-XXXXXXXX/XXXXXXXX',
);

// Add new ad types later
await SimpleAdInitializer.addAdType(
  bannerAdUnitId: 'ca-app-pub-XXXXXXXX/XXXXXXXX',
);

Custom Ad Callbacks #

// Initialize with global callbacks
await GoogleAdsHelper.instance.initialize(
  rewardedAdUnitId: 'your-rewarded-id',
  interstitialAdUnitId: 'your-interstitial-id',
  onAdLoaded: (adType) {
    print('✅ $adType ad loaded successfully');
    // Update UI, show buttons, etc.
  },
  onAdError: (error) {
    print('❌ Ad error: $error');
    // Handle error, show fallback content
  },
  onAdShown: (adType) {
    print('📱 $adType ad shown');
    // Track analytics, pause game, etc.
  },
  onAdClosed: (adType) {
    print('🔒 $adType ad closed');
    // Resume game, update UI, etc.
  },
);

Revenue Tracking & Analytics #

// Track when ads are shown (call this in your ad callbacks)
AdRevenueTracker.trackAdShown(AdType.rewarded);
AdRevenueTracker.trackAdShown(AdType.interstitial);
AdRevenueTracker.trackAdShown(AdType.banner);
AdRevenueTracker.trackAdShown(AdType.native);

// Get individual ad counts
int rewardedCount = AdRevenueTracker.getAdCount(AdType.rewarded);
int interstitialCount = AdRevenueTracker.getAdCount(AdType.interstitial);
int totalAds = AdRevenueTracker.getTotalAdCount();

// Calculate revenue
double rewardedRevenue = AdHelper.calculateEstimatedRevenue(AdType.rewarded, rewardedCount);
double interstitialRevenue = AdHelper.calculateEstimatedRevenue(AdType.interstitial, interstitialCount);

// Calculate user rewards (what you pay to users)
double userRewards = AdHelper.calculateUserReward(AdType.rewarded, rewardedCount);

// Get comprehensive report
Map<String, dynamic> report = AdRevenueTracker.getRevenueReport();
print('Total Ads: ${report['totalAds']}');
print('Estimated Revenue: \$${report['estimatedRevenue'].toStringAsFixed(2)}');
print('User Rewards: \$${report['userRewards'].toStringAsFixed(2)}');
print('App Profit: \$${report['appProfit'].toStringAsFixed(2)}');

// Reset tracking (useful for daily/weekly reports)
AdRevenueTracker.reset();

Advanced Widget Usage #

// Banner with custom styling
BannerAdWidget(
  height: 60,
  adSize: AdSize.banner, // or AdSize.largeBanner, AdSize.mediumRectangle
  margin: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
  backgroundColor: Colors.grey[100],
)

// Native ad with custom appearance
NativeAdWidget(
  height: 250,
  margin: EdgeInsets.all(16),
  borderRadius: BorderRadius.circular(12),
)

// Smart container that adapts to available ads
SmartAdContainer(
  height: 200,
  preferredAdType: AdType.native,
  fallbackAdTypes: [AdType.banner], // Falls back if native not available
)

// Custom loading indicator
AdLoadingIndicator(
  adType: AdType.rewarded,
  customLoadingWidget: Column(
    mainAxisSize: MainAxisSize.min,
    children: [
      CircularProgressIndicator(color: Colors.blue),
      SizedBox(height: 8),
      Text('Loading reward...', style: TextStyle(color: Colors.blue)),
    ],
  ),
)

Debug & Development Tools #

// Print detailed ad status (development only)
AdDebugHelper.printAdStatus();
// Output:
// 🔍 Ad Status Debug Info:
// banner: ✅ Ready (State: AdState.loaded)
// interstitial: 🔄 Loading... (State: AdState.loading)
// rewarded: ❌ Failed/Not Loaded (State: AdState.failed)
// native: ✅ Ready (State: AdState.loaded)

// Print revenue report
AdDebugHelper.printRevenueReport();
// Output:
// 💰 Revenue Report:
// Total Ads Shown: 25
//   - Banner: 10
//   - Interstitial: 8
//   - Rewarded: 5
//   - Native: 2
// Estimated Revenue: $3.45
// User Rewards: $1.95
// App Profit: $1.50

// Get ad states programmatically
Map<String, AdState> states = AdHelper.adStates;
if (states['rewarded'] == AdState.loaded) {
  // Show rewarded button
} else if (states['rewarded'] == AdState.loading) {
  // Show loading indicator
} else {
  // Show "ad not available" message
}

Complete Integration Example #

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

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  // Initialize with comprehensive callbacks
  await SimpleAdInitializer.initializeForRewardApp(
    rewardedAdUnitId: 'ca-app-pub-XXXXXXXX/XXXXXXXX',
    interstitialAdUnitId: 'ca-app-pub-XXXXXXXX/XXXXXXXX',
    onAdLoaded: (adType) {
      print('🎉 $adType ad ready!');
    },
    onAdError: (error) {
      print('❌ Ad error: $error');
    },
  );
  
  // Set custom interstitial frequency
  AdHelper.setInterstitialFrequency(4); // Show every 4th call
  
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: AdvancedRewardScreen(),
    );
  }
}

class AdvancedRewardScreen extends StatefulWidget {
  @override
  _AdvancedRewardScreenState createState() => _AdvancedRewardScreenState();
}

class _AdvancedRewardScreenState extends State<AdvancedRewardScreen> {
  int coins = 100;
  int totalAdsWatched = 0;
  double totalEarnings = 0.0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Advanced Google Ads Helper'),
        actions: [
          IconButton(
            icon: Icon(Icons.info),
            onPressed: () => _showAdStatus(),
          ),
        ],
      ),
      body: Column(
        children: [
          // Banner ad with custom styling
          Container(
            decoration: BoxDecoration(
              color: Colors.grey[100],
              borderRadius: BorderRadius.circular(8),
            ),
            margin: EdgeInsets.all(16),
            child: BannerAdWidget(
              height: 60,
              backgroundColor: Colors.transparent,
            ),
          ),
          
          // Stats display
          Container(
            padding: EdgeInsets.all(16),
            margin: EdgeInsets.symmetric(horizontal: 16),
            decoration: BoxDecoration(
              gradient: LinearGradient(
                colors: [Colors.blue[100]!, Colors.blue[50]!],
              ),
              borderRadius: BorderRadius.circular(12),
            ),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children: [
                _buildStat('Coins', coins.toString()),
                _buildStat('Ads Watched', totalAdsWatched.toString()),
                _buildStat('Earnings', '\$${totalEarnings.toStringAsFixed(2)}'),
              ],
            ),
          ),
          
          SizedBox(height: 20),
          
          // Ad buttons with smart states
          Expanded(
            child: Padding(
              padding: EdgeInsets.symmetric(horizontal: 16),
              child: Column(
                children: [
                  // Rewarded ad button
                  _buildAdButton(
                    title: 'Watch Rewarded Ad',
                    subtitle: '+100 coins',
                    icon: Icons.play_circle_filled,
                    color: Colors.green,
                    isReady: AdHelper.adsStatus['rewarded'] ?? false,
                    isLoading: AdHelper.loadingStatus['rewarded'] ?? false,
                    onPressed: () => _showRewardedAd(),
                  ),
                  
                  SizedBox(height: 16),
                  
                  // Interstitial button with count info
                  _buildAdButton(
                    title: 'Complete Task',
                    subtitle: '+50 coins • ${_getInterstitialInfo()}',
                    icon: Icons.task_alt,
                    color: Colors.blue,
                    isReady: true, // Always available for tasks
                    isLoading: false,
                    onPressed: () => _completeTask(),
                  ),
                  
                  SizedBox(height: 16),
                  
                  // Force interstitial button
                  _buildAdButton(
                    title: 'Watch Interstitial (Bonus)',
                    subtitle: '+25 coins • Force show',
                    icon: Icons.video_library,
                    color: Colors.orange,
                    isReady: AdHelper.adsStatus['interstitial'] ?? false,
                    isLoading: AdHelper.loadingStatus['interstitial'] ?? false,
                    onPressed: () => _showBonusInterstitial(),
                  ),
                  
                  Spacer(),
                  
                  // Revenue report button
                  TextButton.icon(
                    onPressed: () => _showRevenueReport(),
                    icon: Icon(Icons.analytics),
                    label: Text('View Revenue Report'),
                  ),
                ],
              ),
            ),
          ),
          
          // Native ad at bottom
          Container(
            margin: EdgeInsets.all(16),
            decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(12),
              border: Border.all(color: Colors.grey[300]!),
            ),
            child: NativeAdWidget(
              height: 150,
              borderRadius: BorderRadius.circular(12),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildStat(String label, String value) {
    return Column(
      children: [
        Text(
          value,
          style: TextStyle(
            fontSize: 24,
            fontWeight: FontWeight.bold,
            color: Colors.blue[800],
          ),
        ),
        Text(
          label,
          style: TextStyle(
            fontSize: 12,
            color: Colors.blue[600],
          ),
        ),
      ],
    );
  }

  Widget _buildAdButton({
    required String title,
    required String subtitle,
    required IconData icon,
    required Color color,
    required bool isReady,
    required bool isLoading,
    required VoidCallback onPressed,
  }) {
    return Container(
      width: double.infinity,
      child: ElevatedButton(
        onPressed: isReady && !isLoading ? onPressed : null,
        style: ElevatedButton.styleFrom(
          backgroundColor: color,
          padding: EdgeInsets.all(16),
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(12),
          ),
        ),
        child: Row(
          children: [
            Icon(icon, size: 32, color: Colors.white),
            SizedBox(width: 16),
            Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    title,
                    style: TextStyle(
                      fontSize: 16,
                      fontWeight: FontWeight.bold,
                      color: Colors.white,
                    ),
                  ),
                  Text(
                    isLoading ? 'Loading...' : subtitle,
                    style: TextStyle(
                      fontSize: 12,
                      color: Colors.white70,
                    ),
                  ),
                ],
              ),
            ),
            if (isLoading)
              SizedBox(
                width: 20,
                height: 20,
                child: CircularProgressIndicator(
                  strokeWidth: 2,
                  valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
                ),
              ),
          ],
        ),
      ),
    );
  }

  String _getInterstitialInfo() {
    int count = AdHelper.interstitialCallCount;
    int frequency = GoogleAdsHelper.instance.interstitialShowEveryCount;
    
    if (AdHelper.willInterstitialShowNext) {
      return 'Ad will show!';
    } else {
      return '${frequency - count} more for ad';
    }
  }

  void _showRewardedAd() {
    AdHelper.showRewarded(
      onRewardEarned: (reward) {
        setState(() {
          coins += 100;
          totalAdsWatched++;
          totalEarnings += 0.35; // Estimated rewarded ad revenue
        });
        AdRevenueTracker.trackAdShown(AdType.rewarded);
        
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: Text('🎉 Earned 100 coins!'),
            backgroundColor: Colors.green,
          ),
        );
      },
      onAdNotReady: () {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text('⏳ Rewarded ad not ready yet')),
        );
      },
      onAdFailedToShow: () {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text('❌ Failed to show rewarded ad')),
        );
      },
    );
  }

  void _completeTask() {
    // Always complete the task
    setState(() {
      coins += 50;
    });
    
    // Try to show interstitial (respects count-based control)
    bool adShown = AdHelper.showInterstitial(
      onInterstitialShown: () {
        print('📱 Task completion interstitial shown');
      },
      onAdClosed: () {
        setState(() {
          totalAdsWatched++;
          totalEarnings += 0.15; // Estimated interstitial revenue
        });
        AdRevenueTracker.trackAdShown(AdType.interstitial);
      },
    );
    
    String message = adShown ? 
      '✅ Task completed! +50 coins (Ad shown)' : 
      '✅ Task completed! +50 coins';
      
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text(message)),
    );
  }

  void _showBonusInterstitial() {
    AdHelper.showInterstitial(
      forceShow: true, // Bypass count control
      onInterstitialShown: () {
        print('📱 Bonus interstitial shown');
      },
      onAdClosed: () {
        setState(() {
          coins += 25;
          totalAdsWatched++;
          totalEarnings += 0.15;
        });
        AdRevenueTracker.trackAdShown(AdType.interstitial);
        
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: Text('🎉 Bonus earned! +25 coins'),
            backgroundColor: Colors.orange,
          ),
        );
      },
      onAdNotReady: () {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text('⏳ Interstitial ad not ready')),
        );
      },
    );
  }

  void _showAdStatus() {
    final status = AdHelper.adsStatus;
    final loading = AdHelper.loadingStatus;
    
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: Text('Ad Status'),
        content: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            _buildStatusRow('Banner', status['banner']!, loading['banner']!),
            _buildStatusRow('Interstitial', status['interstitial']!, loading['interstitial']!),
            _buildStatusRow('Rewarded', status['rewarded']!, loading['rewarded']!),
            _buildStatusRow('Native', status['native']!, loading['native']!),
            SizedBox(height: 16),
            Text('Interstitial: ${AdHelper.interstitialCallCount}/${GoogleAdsHelper.instance.interstitialShowEveryCount}'),
          ],
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(context),
            child: Text('OK'),
          ),
        ],
      ),
    );
  }

  Widget _buildStatusRow(String name, bool isReady, bool isLoading) {
    String status = isLoading ? '🔄 Loading' : (isReady ? '✅ Ready' : '❌ Failed');
    return Padding(
      padding: EdgeInsets.symmetric(vertical: 2),
      child: Text('$name: $status'),
    );
  }

  void _showRevenueReport() {
    final report = AdRevenueTracker.getRevenueReport();
    
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: Text('Revenue Report'),
        content: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text('Total Ads: ${report['totalAds']}'),
            Text('Banner Ads: ${report['bannerAds']}'),
            Text('Interstitial Ads: ${report['interstitialAds']}'),
            Text('Rewarded Ads: ${report['rewardedAds']}'),
            Text('Native Ads: ${report['nativeAds']}'),
            Divider(),
            Text('Estimated Revenue: \$${report['estimatedRevenue'].toStringAsFixed(2)}'),
            Text('User Rewards: \$${report['userRewards'].toStringAsFixed(2)}'),
            Text('App Profit: \$${report['appProfit'].toStringAsFixed(2)}'),
          ],
        ),
        actions: [
          TextButton(
            onPressed: () {
              AdRevenueTracker.reset();
              Navigator.pop(context);
              ScaffoldMessenger.of(context).showSnackBar(
                SnackBar(content: Text('Revenue tracking reset')),
              );
            },
            child: Text('Reset'),
          ),
          TextButton(
            onPressed: () => Navigator.pop(context),
            child: Text('OK'),
          ),
        ],
      ),
    );
  }
}

Platform Setup #

Android Configuration #

Add the following to your android/app/src/main/AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    
    <!-- Internet permissions for ads -->
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    
    <application
        android:label="your_app_name"
        android:name="${applicationName}"
        android:icon="@mipmap/ic_launcher">
        
        <!-- Add your AdMob App ID -->
        <meta-data
            android:name="com.google.android.gms.ads.APPLICATION_ID"
            android:value="ca-app-pub-XXXXXXXXXXXXXXXX~XXXXXXXXXX"/>
        
        <!-- MainActivity and other configurations... -->
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize">
            <!-- Intent filters and other activity config... -->
        </activity>
        
        <!-- Don't delete the meta-data below.
             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />
    </application>
</manifest>

Important Notes:

  • Replace ca-app-pub-XXXXXXXXXXXXXXXX~XXXXXXXXXX with your actual AdMob App ID
  • Your AdMob App ID is different from Ad Unit IDs (it ends with ~ followed by 10 digits)
  • Find your App ID in the AdMob console under App settings

iOS Configuration #

Add the following to your ios/Runner/Info.plist:

<dict>
    <!-- Other plist entries... -->
    
    <!-- Add your AdMob App ID -->
    <key>GADApplicationIdentifier</key>
    <string>ca-app-pub-XXXXXXXXXXXXXXXX~XXXXXXXXXX</string>
    
    <!-- App Transport Security (allow ads) -->
    <key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
    </dict>
    
    <!-- SKAdNetwork for iOS 14+ attribution -->
    <key>SKAdNetworkItems</key>
    <array>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>cstr6suwn9.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>4fzdc2evr5.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>2fnua5tdw4.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>ydx93a7ass.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>5a6flpkh64.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>p78axxw29g.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>v72qych5uu.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>ludvb6z3bs.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>cp8zw746q7.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>3sh42y64q3.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>c6k4g5qg8m.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>s39g8k73mm.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>3qy4746246.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>f38h382jlk.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>hs6bdukanm.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>v4nxqhlyqp.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>wzmmz9fp6w.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>yclnxrl5pm.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>t38b2kh725.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>7ug5zh24hu.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>9rd848q2bz.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>y5ghdn5j9k.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>n6fk4nfna4.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>v9wttpbfk9.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>n38lu8286q.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>47vhws6wlr.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>kbd757ywx3.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>9t245vhmpl.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>eh6m2bh4zr.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>a2p9lx4ktl.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>22mmun2rn5.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>4468km3ulz.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>2u9pt9hc89.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>8s468mfl3y.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>klf5c3l5u5.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>ppxm28t8ap.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>ecpz2srf59.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>uw77j35x4d.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>pwa73g5rt2.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>mlmmfzh3r3.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>578prtvx9j.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>4dzt52r2t5.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>e5fvkxwrpn.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>8c4e2ghe7u.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>zq492l623r.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>3rd42ekr43.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>3s53sq3u65.skadnetwork</string>
        </dict>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>f73kdq92p3.skadnetwork</string>
        </dict>
    </array>
</dict>

Important Notes:

  • Replace ca-app-pub-XXXXXXXXXXXXXXXX~XXXXXXXXXX with your actual AdMob App ID
  • The SKAdNetwork list above includes major ad networks for better monetization
  • This configuration is required for iOS 14+ ad attribution

Getting Your AdMob App ID #

  1. Go to AdMob Console
  2. Select your app or create a new one
  3. Go to "App settings"
  4. Copy your App ID (format: ca-app-pub-XXXXXXXXXXXXXXXX~XXXXXXXXXX)
  5. Use this App ID in both Android and iOS configurations

Minimum SDK Requirements #

  • Flutter SDK: >=3.3.3 <4.0.0
  • Google Mobile Ads: ^5.2.0
  • Android: minSdkVersion 21
  • iOS: 12.0+

Build Configuration #

For Android, ensure your android/app/build.gradle has:

android {
    compileSdkVersion 34
    
    defaultConfig {
        minSdkVersion 21
        targetSdkVersion 34
        // other configurations...
    }
}

For iOS, ensure your ios/Podfile has:

platform :ios, '12.0'

Getting Your Ad Unit IDs #

  1. Create an AdMob account
  2. Add your app to AdMob
  3. Create ad units for each format you want
  4. Replace test IDs with your real ad unit IDs

License #

MIT License - see LICENSE file for details.

Support #

8
likes
130
points
19
downloads

Publisher

unverified uploader

Weekly Downloads

A comprehensive Flutter plugin for Google Mobile Ads with easy integration, smart initialization, revenue tracking, and professional widgets.

Homepage

Documentation

Documentation
API reference

License

MIT (license)

Dependencies

flutter, google_mobile_ads

More

Packages that depend on google_ads_helper

Packages that implement google_ads_helper