Skip to content

Latest commit

 

History

History
429 lines (329 loc) · 9.23 KB

File metadata and controls

429 lines (329 loc) · 9.23 KB

📱 AdMob Implementation Summary

🎯 Quick Overview

Project: Memory Card Game
Ads Integrated: 5 out of 6 AdMob formats
Status: ✅ Production-ready (with test IDs)


📊 Implemented Ad Formats

1️⃣ Banner Ad 📰

Status: ✅ Implemented
Location: Top & Bottom của HomePage
Manager: banner_ad_manager.dart
Widget: banner_ad_widget.dart

Implementation:

// Reusable widget
const BannerAdWidget()

// Placed in:
- HomePage top
- HomePage bottom

Characteristics:

  • ✅ Always visible during gameplay
  • ✅ Non-intrusive, small size (50px height)
  • ✅ Preloaded on page init
  • ✅ Auto-refresh by AdMob
  • 💰 eCPM: Low but consistent

User Experience:

  • Minimal disruption
  • Passive income stream
  • Users quickly ignore them

2️⃣ Interstitial Ad 📺

Status: ✅ Implemented
Location: Between levels & replay
Manager: interstital_ad_manager.dart

Usage Points:

// 1. Next Level
void _nextLevel() {
  _adManager.showAd(
    onAdDismissed: () {
      // Continue to next level
    },
  );
}

// 2. Play Again
void _onPlayAgain() {
  _adManager.showAd(
    onAdDismissed: () {
      _resetGame();
    },
  );
}

Characteristics:

  • ✅ Full-screen ad
  • ✅ Natural break points
  • ✅ High engagement
  • ✅ Cooldown logic to prevent spam
  • 💰 eCPM: High

User Experience:

  • Expected at level transitions
  • Skipable after 5 seconds
  • Not intrusive due to natural timing

3️⃣ Rewarded Ad 🎁

Status: ✅ Implemented
Location: Help feature in HomePage
Manager: reward_ad_manager.dart

Usage:

void _useHelp() {
  // Show dialog first
  showDialog(...);
  
  // User confirms
  _rewardAdManager.showAd(
    onUserEarnedReward: () {
      // Give reward: auto-flip matching pair
      _executeHelp(card1, card2);
    },
    onAdNotReady: () {
      // Show error message
    },
  );
}

Reward:

  • Auto-flip 1 matching pair
  • Doesn't count towards move limit
  • Helps complete difficult levels

Characteristics:

  • ✅ User opt-in (choice)
  • ✅ Clear value proposition
  • ✅ Must watch full ad
  • ✅ Reward guaranteed after completion
  • 💰 eCPM: Very High

User Experience:

  • User controls when to watch
  • Clear benefit explained upfront
  • Fair exchange (ad for help)

4️⃣ App Open Ad 🚪

Status: ✅ Implemented
Location: App foreground resume
Manager: app_open_ad_manager.dart (Global instance in main.dart)

Implementation:

// In main.dart
final appOpenAdManager = AppOpenAdManager(); // Global

class _MyAppState extends State<MyApp> 
    with WidgetsBindingObserver {
  
  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.resumed) {
      appOpenAdManager.showAdIfAvailable();
    }
  }
}

Smart Cooldown Logic:

// Don't show if:
- Another ad was shown in last 4 hours
- User just watched rewarded/interstitial ad

Characteristics:

  • ✅ Monetizes returning users
  • ✅ Shows when app resumes from background
  • ✅ 4-hour cooldown
  • ✅ Doesn't interrupt active sessions
  • 💰 eCPM: Medium-High

User Experience:

  • Only when returning to app
  • Not shown after other ads (smart!)
  • Feels natural, not spammy

5️⃣ Native Ad 🎨

Status: ✅ Implemented
Location: LevelSelectionPage
Manager: native_ad_manager.dart

Implementation:

// In LevelSelectionPage
Container(
  height: 120,  // Small, non-intrusive
  child: ClipRRect(
    borderRadius: BorderRadius.circular(12),
    child: AdWidget(ad: _nativeAd!),
  ),
)

Placement:

  • Between level grid and play button
  • Center of screen
  • Blends with UI design

Characteristics:

  • ✅ Customizable appearance
  • ✅ Blends into app UI
  • ✅ Less disruptive than banner
  • ✅ Better CTR than banner
  • 💰 eCPM: Medium

User Experience:

  • Looks like part of the app
  • Natural placement
  • Not jarring or annoying

❌ Not Implemented

6️⃣ Rewarded Interstitial Ad 💰

Status: ❌ Not Implemented
Reason: Not necessary - already have both Interstitial & Rewarded

When to use:

  • "Continue" feature after losing
  • Unlock premium features
  • Skip timers

Why we don't need it:

  • Current monetization is sufficient
  • Too many ad types can hurt UX
  • Interstitial + Rewarded covers all use cases

📈 Ad Placement Strategy

User Journey with Ads

1. App Launch
   └─> (No ad - good first impression)

2. IntroPage
   └─> (No ad - quick intro)

3. LevelSelectionPage
   ├─> 📱 Native Ad (120px, blends in)
   └─> Select level

4. HomePage - Playing
   ├─> 📰 Banner Ad (Top)
   ├─> 📰 Banner Ad (Bottom)
   ├─> [Optional] 🎁 Rewarded Ad (Help button)
   └─> Game over

5. Game Over
   ├─> Win → 📺 Interstitial Ad → Next Level
   └─> Lose → 📺 Interstitial Ad → Retry

6. App Background → Foreground
   └─> 🚪 App Open Ad (if cooldown passed)

Frequency Control

Ad Type Frequency Cooldown
Banner Always visible None (persistent)
Interstitial Per level transition After each ad shown
Rewarded User-triggered None (opt-in)
App Open On app resume 4 hours + after other ads
Native On page load None (static)

💰 Monetization Estimates

Revenue Potential (Approximate)

Ad Type CPM Range Priority Use Case
Rewarded $10-$40 ⭐⭐⭐⭐⭐ High value, opt-in
Interstitial $5-$15 ⭐⭐⭐⭐ Natural breaks
App Open $3-$10 ⭐⭐⭐ Re-engagement
Native $2-$8 ⭐⭐⭐ Blend well
Banner $0.50-$3 ⭐⭐ Low but consistent

Note: Actual eCPM varies by:

  • Geographic location
  • User demographics
  • App category
  • Ad quality
  • Fill rate

🎯 Best Practices Implemented

✅ What We Did Right

  1. No Ad Spam

    • Cooldown logic for App Open Ad
    • Natural break points for Interstitial
    • User choice for Rewarded
  2. Proper Disposal

    @override
    void dispose() {
      _adManager.dispose();
      super.dispose();
    }
  3. Error Handling

    • Graceful fallback when ads fail to load
    • User feedback for ad not ready
  4. Test IDs During Development

    • All current IDs are Google test IDs
    • Safe to test without policy violations
  5. Preloading

    • Ads load in initState()
    • Ready when needed
    • Minimal wait time for users
  6. Callbacks

    • All ad managers support callbacks
    • Actions continue after ads dismiss
    • Proper lifecycle management

🔄 Migration to Production

Steps to Go Live

  1. Get Real Ad Unit IDs from AdMob Console

    • Create app in AdMob
    • Create ad units for each format
    • Copy Ad Unit IDs
  2. Update constants.dart

    // Replace test IDs
    static String get bannerAdUnitId => Platform.isAndroid
        ? 'ca-app-pub-YOUR_ID/BANNER_ID'
        : 'ca-app-pub-YOUR_ID/BANNER_ID_IOS';
  3. Test on Real Devices

    • Verify all ads load
    • Check ad placement
    • Test user flow
  4. Monitor Performance

    • Check AdMob dashboard
    • Watch fill rates
    • Optimize placement if needed

📊 Ad Unit IDs Reference

Current (Test IDs)

class AdConstants {
  // Banner
  static String get bannerAdUnitId => Platform.isAndroid
      ? 'ca-app-pub-3940256099942544/6300978111'  // Test
      : 'ca-app-pub-3940256099942544/2934735716'; // Test

  // Interstitial
  static String get interstitialAdUnitId => Platform.isAndroid
      ? 'ca-app-pub-3940256099942544/1033173712'  // Test
      : 'ca-app-pub-3940256099942544/4411468910'; // Test

  // Rewarded
  static String get rewardedAdUnitId => Platform.isAndroid
      ? 'ca-app-pub-3940256099942544/5224354917'  // Test
      : 'ca-app-pub-3940256099942544/1712485313'; // Test

  // App Open
  static String get appOpenAdUnitId => Platform.isAndroid
      ? 'ca-app-pub-3940256099942544/9257395921'  // Test
      : 'ca-app-pub-3940256099942544/5575463023'; // Test

  // Native
  static String get nativeAdUnitId => Platform.isAndroid
      ? 'ca-app-pub-3940256099942544/2247696110'  // Test
      : 'ca-app-pub-3940256099942544/3986624511'; // Test
}

⚠️ Important: These are Google's test IDs. Must replace before production!


🎓 Key Learnings

What Makes Our Implementation Good

  1. User-First Approach

    • Ads don't interrupt core gameplay
    • Rewarded ads offer real value
    • Clear timing for interstitials
  2. Technical Excellence

    • Clean architecture (services folder)
    • Proper lifecycle management
    • Reusable components
  3. Smart Monetization

    • Multiple revenue streams
    • High-value ad formats (Rewarded)
    • Strategic placement
  4. Scalable Code

    • Easy to add more ad placements
    • Centralized configuration
    • Consistent patterns

📚 Resources


Summary: Professional AdMob integration with 5 ad formats, user-friendly implementation, and production-ready architecture! 🚀