Manual Integration
Track ad events from any mediation platform that provides ILRD
This feature is currently in beta. To enable it, visit the Ads page in your RevenueCat dashboard to opt in.
For apps using mediation platforms that provide impression-level revenue data (ILRD), you can manually track ad events by calling the AdTracker methods from your ad SDK callbacks.
Overview
Manual integration gives you full control over ad event tracking and works with any mediation platform that supports ILRD, including:
- AppLovin MAX
- ironSource
- Unity Ads
- Or any custom mediation setup
The integration involves hooking into your mediation platform's callbacks and calling the appropriate AdTracker methods.
How It Works
- Your mediation platform fires a callback (e.g., ad loaded, ad displayed, revenue generated)
- You call the corresponding AdTracker method with the event data
- RevenueCat records the event and makes it available in Charts
Prerequisites
- SDK Version:
- Android:
purchases-android8.0.0+ - iOS:
purchases-ios5.0.0+
- Android:
- ILRD Support: Your mediation platform must provide impression-level revenue data
- Experimental API: Ad monetization APIs are marked as experimental
Android Integration
1. Access the AdTracker
import com.revenuecat.purchases.ExperimentalPreviewRevenueCatPurchasesAPI
import com.revenuecat.purchases.Purchases
@OptIn(ExperimentalPreviewRevenueCatPurchasesAPI::class)
val adTracker = Purchases.sharedInstance.adTracker
2. Import Event Types
import com.revenuecat.purchases.ads.events.types.*
3. Track Events from Mediation Callbacks
All track methods follow a similar pattern. Here are the two main examples:
Track Ad Loaded
Call when an ad successfully loads:
@OptIn(ExperimentalPreviewRevenueCatPurchasesAPI::class)
fun onAdLoaded(ad: YourAdType) {
adTracker.trackAdLoaded(
AdLoadedData(
networkName = ad.networkName, // e.g., "Google Ads"
mediatorName = AdMediatorName.APP_LOVIN, // or custom: AdMediatorName.fromString("YourMediator")
adFormat = AdFormat.REWARDED, // BANNER, INTERSTITIAL, etc.
placement = "home_screen", // Your custom placement ID
adUnitId = ad.adUnitId, // Ad unit identifier
impressionId = ad.impressionId // Unique impression ID
)
)
}
Track Ad Revenue
Call when your mediation platform reports revenue for an impression:
@OptIn(ExperimentalPreviewRevenueCatPurchasesAPI::class)
fun onAdRevenue(ad: YourAdType, revenue: Double, currency: String) {
adTracker.trackAdRevenue(
AdRevenueData(
networkName = ad.networkName,
mediatorName = AdMediatorName.APP_LOVIN,
adFormat = AdFormat.REWARDED,
placement = "home_screen",
adUnitId = ad.adUnitId,
impressionId = ad.impressionId,
revenueMicros = (revenue * 1_000_000).toLong(), // Convert to micros
currency = currency, // e.g., "USD"
precision = AdRevenuePrecision.EXACT // Or ESTIMATED, PUBLISHER_DEFINED
)
)
}
Other Track Methods
The remaining methods follow the same pattern as trackAdLoaded:
trackAdDisplayed(AdDisplayedData)- Call when ad impression is recorded (ad shown on screen)trackAdOpened(AdOpenedData)- Call when user clicks/taps the adtrackAdFailedToLoad(AdFailedToLoadData)- Call when ad fails to load (doesn't requirenetworkNameorimpressionId)
See the Event Data Reference section below for complete parameter details.
iOS Integration
1. Access the AdTracker
@_spi(Experimental) import RevenueCat
let adTracker = Purchases.shared.adTracker
2. Track Events from Mediation Callbacks
All track methods follow a similar pattern. Here are the two main examples:
Track Ad Loaded
Call when an ad successfully loads:
@_spi(Experimental)
func onAdLoaded(ad: YourAdType) {
Purchases.shared.adTracker.trackAdLoaded(.init(
networkName: ad.networkName, // e.g., "Google Ads"
mediatorName: .appLovin, // or custom: .init(value: "YourMediator")
adFormat: .rewarded, // .banner, .interstitial, etc.
placement: "home_screen", // Your custom placement ID
adUnitId: ad.adUnitId, // Ad unit identifier
impressionId: ad.impressionId // Unique impression ID
))
}
Track Ad Revenue
Call when your mediation platform reports revenue for an impression:
@_spi(Experimental)
func onAdRevenue(ad: YourAdType, revenue: Double, currency: String) {
Purchases.shared.adTracker.trackAdRevenue(.init(
networkName: ad.networkName,
mediatorName: .appLovin,
adFormat: .rewarded,
placement: "home_screen",
adUnitId: ad.adUnitId,
impressionId: ad.impressionId,
revenueMicros: Int64(revenue * 1_000_000), // Convert to micros
currency: currency, // e.g., "USD"
precision: .exact // Or .estimated, .publisherDefined
))
}
Other Track Methods
The remaining methods follow the same pattern as trackAdLoaded:
trackAdDisplayed(_:)- Call when ad impression is recorded (ad shown on screen)trackAdOpened(_:)- Call when user clicks/taps the adtrackAdFailedToLoad(_:)- Call when ad fails to load (doesn't requirenetworkNameorimpressionId)
See the Event Data Reference section below for complete parameter details.
Event Data Reference
Common Parameters
All event types share these common parameters:
| Parameter | Type | Description | Required |
|---|---|---|---|
networkName | String | Ad network that served the ad (e.g., "Google Ads", "Meta Audience Network") | No (null allowed) |
mediatorName | AdMediatorName | Your mediation platform | Yes |
adFormat | AdFormat | Type of ad | Yes |
placement | String | Your custom placement identifier | No (null allowed) |
adUnitId | String | Ad unit identifier from mediation platform | Yes |
impressionId | String | Unique identifier for this ad instance | Yes (except for failed events) |
AdFormat Values
Use the predefined constants:
AdFormat.BANNER- Banner adsAdFormat.INTERSTITIAL- Full-screen interstitial adsAdFormat.REWARDED- Rewarded video adsAdFormat.REWARDED_INTERSTITIAL- Rewarded interstitial adsAdFormat.NATIVE- Native adsAdFormat.APP_OPEN- App open adsAdFormat.OTHER- Other ad formats
Or create a custom format: AdFormat.fromString("your_format")
AdMediatorName Values
Predefined mediators:
AdMediatorName.AD_MOB- Google AdMobAdMediatorName.APP_LOVIN- AppLovin MAX
For other mediators: AdMediatorName.fromString("YourMediator")
AdRevenuePrecision Values
Indicates the precision of revenue data:
AdRevenuePrecision.EXACT- Exact revenue value from the networkAdRevenuePrecision.ESTIMATED- Estimated by the mediation platformAdRevenuePrecision.PUBLISHER_DEFINED- Custom publisher-defined valueAdRevenuePrecision.UNKNOWN- Precision unknown
Revenue in Micros
The revenueMicros parameter expects revenue in micros (millionths of the currency unit):
// Example: $1.50 USD
val revenue = 1.50
val revenueMicros = (revenue * 1_000_000).toLong() // 1,500,000
Best Practices
Placement Naming
Use consistent, descriptive placement names:
- ✅ Good:
"home_banner","level_complete_interstitial","bonus_coins_rewarded" - ❌ Avoid:
"ad1","test", timestamps, or dynamic values
Impression IDs
- Use unique IDs provided by your mediation platform
- The same impression ID should be used across all events for a single ad instance (loaded → displayed → opened → revenue)
Error Handling
Track failed ad loads to understand fill rate issues:
adTracker.trackAdFailedToLoad(
AdFailedToLoadData(
mediatorName = AdMediatorName.fromString("YourMediator"),
adFormat = AdFormat.REWARDED,
placement = "home_screen",
adUnitId = adUnitId,
mediatorErrorCode = errorCode // Include platform error code
)
)
When to Track Each Event
| Event | When to Call |
|---|---|
trackAdLoaded | After ad successfully loads in memory |
trackAdDisplayed | When ad impression is recorded (ad shown on screen) |
trackAdOpened | When user clicks/taps the ad |
trackAdRevenue | When mediation platform reports ILRD for the impression |
trackAdFailedToLoad | When ad request fails |
Example Projects
Complete working examples are available:
- Android: purchases-android/examples/admob-sample - Shows AdMob integration patterns
- iOS: purchases-ios/Examples/AdMobIntegrationSample - Shows AdMob integration patterns
While these examples use AdMob's helper methods, they demonstrate the event tracking patterns that apply to manual integration with any mediation platform.
View Your Data
See the Ad Monetization overview for details on where your ad data appears in the dashboard.
Troubleshooting
Testing Your Integration
Before troubleshooting, verify your events are being tracked:
- Run your app in debug mode
- Navigate to the Ads page in your RevenueCat dashboard
- Toggle on "Sandbox data"
- Trigger some ads in your app
- 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.
Events not appearing in Charts
- Verify you've opted in via the Ads page in your RevenueCat dashboard
- Check that you're calling the correct
track*methods with all required parameters - Ensure
impressionIdis unique for each ad instance - Verify your mediation platform is providing ILRD callbacks
- Check that
revenueMicrosis calculated correctly (multiply by 1,000,000) - Use the sandbox data view (above) to confirm events are being received
Revenue values seem incorrect
- Ensure you're converting to micros:
(revenue * 1_000_000).toLong() - Verify the currency code is correct (e.g., "USD", "EUR")
- Check that the revenue value from your mediation platform is already in the correct currency unit
Next Steps
- Review the example projects for complete implementations
- View your ad data in Ad Charts
- Learn about AdMob Integration (Android) for simplified integration with Google AdMob