Skip to main content

AdMob SDK Integration (iOS)

Quick setup for AdMob ad monetization on iOS with RevenueCat

AIAsk AIChatGPTClaude
⚠️Beta Feature - Opt-in Required

This feature is currently in beta. To enable it, visit the Ads page in your RevenueCat dashboard to opt in.

The RevenueCat AdMob integration for iOS provides helper methods that wrap standard AdMob ad loading calls. Use loadAndTrack methods to automatically track all ad events.

Installation

Add the AdMob integration package via Swift Package Manager:

.package(url: "https://github.com/RevenueCat/purchases-ios-admob", from: "5.0.0")

Then add the RevenueCatAdMob product to your target.

📘SPM Dependency Note

If your project depends on RevenueCat via SPM, use the purchases-ios-spm package (not purchases-ios). The adapter declares this dependency correctly, but if you add RevenueCat separately, make sure both resolve from the same purchases-ios-spm repository to avoid duplicate package errors.

Quick Start

1. Import the Module

@_spi(Experimental) import RevenueCatAdMob

2. Replace Load Calls with loadAndTrack

Replace standard AdMob load calls with loadAndTrack methods:

// Before
InterstitialAd.load(with: adUnitID, request: Request()) { ad, error in
ad?.fullScreenContentDelegate = self
self.interstitialAd = ad
}

// After
InterstitialAd.loadAndTrack(
withAdUnitID: adUnitID,
request: Request(),
placement: "level_complete",
fullScreenContentDelegate: self
) { ad, error in
self.interstitialAd = ad
}

Supported Ad Formats

The integration supports all major AdMob ad formats:

FormatMethodAd Type
BannerBannerView.loadAndTrack(request:placement:)BannerView
InterstitialInterstitialAd.loadAndTrack(withAdUnitID:...)InterstitialAd
RewardedRewardedAd.loadAndTrack(withAdUnitID:...)RewardedAd
Rewarded InterstitialRewardedInterstitialAd.loadAndTrack(withAdUnitID:...)RewardedInterstitialAd
App OpenAppOpenAd.loadAndTrack(withAdUnitID:...)AppOpenAd
NativeAdLoader.loadAndTrack(_:placement:)NativeAd

Implementation Examples

@_spi(Experimental) import RevenueCatAdMob

let bannerView = BannerView(adSize: AdSize(size: CGSize(width: 320, height: 50), flags: 0))
bannerView.adUnitID = "ca-app-pub-3940256099942544/2435281174"

bannerView.loadAndTrack(
request: Request(),
placement: "home_banner"
)

Pass delegate and/or paidEventHandler via the loadAndTrack overload:

bannerView.loadAndTrack(
request: Request(),
placement: "home_banner",
delegate: self,
paidEventHandler: { adValue in
// Your custom paid event handling
}
)

Interstitial Ads

@_spi(Experimental) import RevenueCatAdMob

class MyViewController: UIViewController, FullScreenContentDelegate {
private var interstitialAd: InterstitialAd?

func loadInterstitial() {
InterstitialAd.loadAndTrack(
withAdUnitID: "ca-app-pub-3940256099942544/4411468910",
request: Request(),
placement: "level_complete",
fullScreenContentDelegate: self
) { [weak self] ad, error in
if let error { return }
self?.interstitialAd = ad
}
}

func showInterstitial() {
interstitialAd?.present(from: self)
}
}

Rewarded Ads

@_spi(Experimental) import RevenueCatAdMob

func loadRewardedAd() {
RewardedAd.loadAndTrack(
withAdUnitID: "ca-app-pub-3940256099942544/1712485313",
request: Request(),
placement: "bonus_coins",
fullScreenContentDelegate: self
) { [weak self] ad, error in
if let error { return }
self?.rewardedAd = ad
}
}

func showRewardedAd() {
rewardedAd?.present(from: self) {
// User earned reward
}
}

Rewarded Interstitial Ads

@_spi(Experimental) import RevenueCatAdMob

func loadRewardedInterstitialAd() {
RewardedInterstitialAd.loadAndTrack(
withAdUnitID: "ca-app-pub-3940256099942544/6978759866",
request: Request(),
placement: "between_levels",
fullScreenContentDelegate: self
) { [weak self] ad, error in
if let error { return }
self?.rewardedInterstitialAd = ad
}
}

func showRewardedInterstitialAd() {
rewardedInterstitialAd?.present(from: self) {
// User earned reward
}
}

App Open Ads

@_spi(Experimental) import RevenueCatAdMob

func loadAppOpenAd() {
AppOpenAd.loadAndTrack(
withAdUnitID: "ca-app-pub-3940256099942544/5575463023",
request: Request(),
placement: "app_launch",
fullScreenContentDelegate: self
) { [weak self] ad, error in
if let error { return }
self?.appOpenAd = ad
}
}

Native Ads

@_spi(Experimental) import RevenueCatAdMob

let adLoader = AdLoader(
adUnitID: "ca-app-pub-3940256099942544/3986624511",
rootViewController: self,
adTypes: [.native],
options: nil
)
adLoader.delegate = self

adLoader.loadAndTrack(
Request(),
placement: "feed",
nativeAdDelegate: self
)

Placement Parameter

The placement parameter identifies where ads appear in your app and is used for reporting and segmentation in Ad Charts.

Use consistent, descriptive names like "home_banner" or "level_complete_interstitial". Avoid dynamic values or timestamps.

Events Tracked Automatically

The loadAndTrack methods automatically track:

  • Ad Loaded - Ad successfully loads
  • Ad Displayed - Ad impression is recorded
  • Ad Opened - User clicks the ad
  • Ad Revenue - Ad generates revenue (via AdMob's paid event handler)
  • Ad Failed to Load - Ad fails to load

All events are captured from AdMob's callbacks with no additional code required.

Delegate Handling

Pass delegates to loadAndTrack methods rather than assigning them afterward. Reassigning delegates after calling loadAndTrack will break event tracking.

// ✅ Correct
InterstitialAd.loadAndTrack(
withAdUnitID: adUnitID,
request: Request(),
placement: "level_complete",
fullScreenContentDelegate: self
) { ad, error in }

// ❌ Don't do this
ad?.fullScreenContentDelegate = self // Overwrites tracking

Requirements

  • Minimum iOS version: iOS 15.0+
  • RevenueCat SDK: purchases-ios 5.0.0+
  • AdMob SDK: Google Mobile Ads SDK 12.0.0+
  • Swift only: This adapter does not expose Objective-C entrypoints. Use RevenueCat's base AdTracker APIs directly for Objective-C integrations.

View Your Data

See the Ad Monetization overview for details on where your ad data appears in the dashboard.

Optional: Make Charts More Readable

By default, your ad charts will display ad unit IDs like ca-app-pub-3940256099942544/2435281174. To see human-readable names instead:

→ Connect your Google AdMob account to automatically sync ad unit names to RevenueCat. This enhances chart readability without requiring any code changes.

Troubleshooting

Testing Your Integration

Before troubleshooting, verify your events are being tracked:

  1. Run your app in debug mode
  2. Navigate to the Ads page in your RevenueCat dashboard
  3. Toggle on "Sandbox data"
  4. Trigger some ads in your app
  5. Check that events appear in the sandbox events table

Events from debug builds are automatically marked as sandbox. This lets you verify your integration without affecting production data.

Note on event timing: Ad events are not synced to the dashboard in real-time. The SDK batches and sends events periodically. If you've triggered several ads and don't see events immediately, try putting your app in the background and bringing it back to the foreground to trigger a sync. This is normal behavior and doesn't indicate an integration issue.

Events not appearing in Charts

  1. Verify you've opted in via the Ads page in your RevenueCat dashboard
  2. Check that you're using loadAndTrack methods (not standard AdMob methods)
  3. Ensure placement parameter is provided
  4. Verify ads are actually loading and showing (check AdMob callbacks)
  5. Use the sandbox data view (above) to confirm events are being received

Compilation errors

Make sure you've added the SPI import:

@_spi(Experimental) import RevenueCatAdMob

Next Steps