Measuring your revenue sources helps you understand the lifetime value of your users and grow your app business. This guide shows you how to set up ad revenue measurement for your platform.
After you've set up ad revenue measurement, you can then do any of the following:
-  Analyze user actions that contribute to the ad revenue generated by your app. 
-  Run experiments using Firebase A/B Testing to find what features drive improvements in your app ad revenue, or personalize ad experiences using Remote Config personalization . 
-  Create user audiences and tailor user experiences using Firebase Remote Config based on ad revenue levels. 
Before you begin
If you haven't already, make sure to complete the following tasks:
-  Set up your project and app as described in Get Started with Analytics . 
-  Make sure that you've linked your Firebase project to a Google Analytics account. 
-  Ensure that you've included in your app the Android SDK v17.6.0+ or the Apple platforms SDK v6.34.0+. 
Implementation
You can use Google Analytics 
to measure ad revenue generated from
displaying ads with monetization platforms, such as AdMob 
, AppLovin, and
ironSource. To measure ad revenue, you must log  ad_impression 
events 
whenever your user sees an advertisement in your app. These events contain
details such as the ad platform, source, currency, and value.
AdMob
If you are using the AdMob 
platform, link your AdMob 
app to Firebase and Analytics 
 
to enable automatic measurement of ad revenue. The Firebase SDK for Google Analytics 
automatically logs the ad_impression 
event whenever
your users see an ad impression.
Other ad monetization platforms
Platforms such as AppLovin and ironSource provide impression-level revenue data
that you can then use to log Google Analytics 
  ad_impression 
 
events.
The following sections show implementation examples for a few different ad monetization platforms.
AppLovin
Swift
func didPayRevenue ( _ impressionData : MAAd ?) { if let impressionData = impressionData { Analytics . logEvent ( AnalyticsEventAdImpression , parameters : [ AnalyticsParameterAdPlatform : "AppLovin" , AnalyticsParameterAdUnitName : impressionData . adUnitIdentifier , AnalyticsParameterAdFormat : impressionData . format , AnalyticsParameterValue : impressionData . revenue , AnalyticsParameterCurrency : "USD" , // All Applovin revenue is sent in USD AnalyticsParameterAdSource : impressionData . networkName , ]) } }
Objective-C
- ( void ) didPayRevenueForAd: ( MAAd * ) impressionData { [ FIRAnalytics logEventWithName : kFIREventAdImpression parameters : @{ kFIRParameterAdPlatform : @"AppLovin" , kFIRParameterAdSource : impressionData . networkName , kFIRParameterAdFormat : impressionData . format , kFIRParameterAdUnitName : impressionData . adUnitIdentifier , kFIRParameterCurrency : @"USD" , // All Applovin revenue is sent in USD kFIRParameterValue : impressionData . revenue } ]; }
Kotlin
override fun onAdRevenuePaid ( impressionData : MaxAd?) { impressionData ?. let { firebaseAnalytics = Firebase . analytics firebaseAnalytics . logEvent ( FirebaseAnalytics . Event . AD_IMPRESSION ) { param ( FirebaseAnalytics . Param . AD_PLATFORM , "appLovin" ) param ( FirebaseAnalytics . Param . AD_UNIT_NAME , impressionData . adUnitId ) param ( FirebaseAnalytics . Param . AD_FORMAT , impressionData . format . label ) param ( FirebaseAnalytics . Param . AD_SOURCE , impressionData . networkName ) param ( FirebaseAnalytics . Param . VALUE , impressionData . revenue ) param ( FirebaseAnalytics . Param . CURRENCY , "USD" ) // All Applovin revenue is sent in USD } } }
Java
@Override public void onAdRevenuePaid ( MaxAd impressionData ) { double revenue = impressionData . getRevenue (); // In USD mFirebaseAnalytics = FirebaseAnalytics . getInstance ( this ); Bundle params = new Bundle (); params . putString ( FirebaseAnalytics . Param . AD_PLATFORM , "appLovin" ); params . putString ( FirebaseAnalytics . Param . AD_SOURCE , impressionData . getNetworkName ()); params . putString ( FirebaseAnalytics . Param . AD_FORMAT , impressionData . getFormat (). getLabel ()); params . putString ( FirebaseAnalytics . Param . AD_UNIT_NAME , impressionData . getAdUnitId ()); params . putDouble ( FirebaseAnalytics . Param . VALUE , revenue ); params . putString ( FirebaseAnalytics . Param . CURRENCY , "USD" ); // All Applovin revenue is sent in USD mFirebaseAnalytics . logEvent ( FirebaseAnalytics . Event . AD_IMPRESSION , params ); }
Unity
// Attach callbacks based on the ad format(s) you are using MaxSdkCallbacks . Interstitial . OnAdRevenuePaidEvent += OnAdRevenuePaidEvent ; MaxSdkCallbacks . Rewarded . OnAdRevenuePaidEvent += OnAdRevenuePaidEvent ; MaxSdkCallbacks . Banner . OnAdRevenuePaidEvent += OnAdRevenuePaidEvent ; MaxSdkCallbacks . MRec . OnAdRevenuePaidEvent += OnAdRevenuePaidEvent ; private void OnAdRevenuePaidEvent ( string adUnitId , MaxSdkBase . AdInfo impressionData ) { double revenue = impressionData . Revenue ; var impressionParameters = new [] { new Firebase . Analytics . Parameter ( "ad_platform" , "AppLovin" ), new Firebase . Analytics . Parameter ( "ad_source" , impressionData . NetworkName ), new Firebase . Analytics . Parameter ( "ad_unit_name" , impressionData . AdUnitIdentifier ), new Firebase . Analytics . Parameter ( "ad_format" , impressionData . AdFormat ), new Firebase . Analytics . Parameter ( "value" , revenue ), new Firebase . Analytics . Parameter ( "currency" , "USD" ), // All AppLovin revenue is sent in USD }; Firebase . Analytics . FirebaseAnalytics . LogEvent ( "ad_impression" , impressionParameters ); }
ironSource
Swift
func impressionDataDidSucceed ( _ impressionData : ISImpressionData !) { Analytics . logEvent ( AnalyticsEventAdImpression , parameters : [ AnalyticsParameterAdPlatform : "ironSource" , AnalyticsParameterAdSource : impressionData . ad_network ?? "No ad_network" , AnalyticsParameterAdFormat : impressionData . ad_unit ?? "No ad_unit" , AnalyticsParameterAdUnitName : impressionData . instance_name ?? "No instance_name" , AnalyticsParameterCurrency : "USD" , AnalyticsParameterValue : impressionData . revenue ?? 0 , ]) }
Objective-C
- ( void ) impressionDataDidSucceed: ( ISImpressionData * ) impressionData { [ FIRAnalytics logEventWithName : kFIREventAdImpression parameters : @{ kFIRParameterAdPlatform : @"ironSource" , kFIRParameterAdSource : impressionData . ad_network , kFIRParameterAdFormat : impressionData . ad_unit , kFIRParameterAdUnitName : impressionData . instance_name , kFIRParameterCurrency : @"USD" , kFIRParameterValue : impressionData . revenue } ]; }
Kotlin
override fun onImpressionSuccess ( impressionData : ImpressionData ) { // The onImpressionSuccess will be reported when the rewarded video and interstitial ad is // opened. // For banners, the impression is reported on load success. Log.d(TAG, "onImpressionSuccess" + // impressionData) firebaseAnalytics = Firebase . analytics firebaseAnalytics . logEvent ( FirebaseAnalytics . Event . AD_IMPRESSION ) { param ( FirebaseAnalytics . Param . AD_PLATFORM , "ironSource" ) param ( FirebaseAnalytics . Param . AD_SOURCE , impressionData . adNetwork ) param ( FirebaseAnalytics . Param . AD_FORMAT , impressionData . adUnit ) param ( FirebaseAnalytics . Param . AD_UNIT_NAME , impressionData . instanceName ) param ( FirebaseAnalytics . Param . CURRENCY , "USD" ) param ( FirebaseAnalytics . Param . VALUE , impressionData . revenue ) } }
Java
@Override public void onImpressionSuccess ( ImpressionData impressionData ) { // The onImpressionSuccess will be reported when the rewarded video and interstitial ad is opened. // For banners, the impression is reported on load success. Log.d(TAG, "onImpressionSuccess" + impressionData); mFirebaseAnalytics = FirebaseAnalytics . getInstance ( this ); if ( impressionData != null ) { Bundle bundle = new Bundle (); bundle . putString ( FirebaseAnalytics . Param . AD_PLATFORM , "ironSource" ); bundle . putString ( FirebaseAnalytics . Param . AD_SOURCE , impressionData . getAdNetwork ()); bundle . putString ( FirebaseAnalytics . Param . AD_FORMAT , impressionData . getAdUnit ()); bundle . putString ( FirebaseAnalytics . Param . AD_UNIT_NAME , impressionData . getInstanceName ()); bundle . putString ( FirebaseAnalytics . Param . CURRENCY , "USD" ); bundle . putDouble ( FirebaseAnalytics . Param . VALUE , impressionData . getRevenue ()); mFirebaseAnalytics . logEvent ( FirebaseAnalytics . Event . AD_IMPRESSION , bundle ); } }
Unity
private void ImpressionSuccessEvent ( IronSourceImpressionData impressionData ) { if ( impressionData != null ) { Firebase . Analytics . Parameter [] AdParameters = { new Firebase . Analytics . Parameter ( "ad_platform" , "ironSource" ), new Firebase . Analytics . Parameter ( "ad_source" , impressionData . adNetwork ), new Firebase . Analytics . Parameter ( "ad_unit_name" , impressionData . getInstanceName ), new Firebase . Analytics . Parameter ( "ad_format" , impressionData . getAdUnit ), new Firebase . Analytics . Parameter ( "currency" , "USD" ), new Firebase . Analytics . Parameter ( "value" , impressionData . getRevenue ) }; Firebase . Analytics . FirebaseAnalytics . LogEvent ( "ad_impression" , AdParameters ); } }
Implementation considerations
To allow Google Ads 
to process your  ad_impression 
 
, make sure to include
both the currency 
and the value 
parameters (described below). Both
parameters should be as accurate as possible to prevent over-valuing or under-
valuing users.
Currency parameter
The currency 
parameter
( iOS+ 
| Android 
| Unity 
)
should be sent as a string in a three-letter ISO_4217 
format (for example, "USD" 
). Some ad monetization platforms omit currency,
which may require you to hardcode the parameter.
Value parameter
The value 
parameter
( iOS+ 
| Android 
| Unity 
)
should be sent using a dot as the decimal separator. You may need to transform
the values received from some platforms to fit the required format above. Some
platforms localize numerical formats and use commas as decimal separators. In
some cases, a platform may not send a value at all.
Additionally, the value should be a numerical type such as a double or long.
For example, 1000.01 
, 0.001 
and 1.00 
are all valid 
Validation
Google Analytics offers multiple features to validate your implementation throughout the development cycle.
-  DebugView 
 When first testing your implementation, use DebugView to see your testad_impressiondata in the console. When you select anad_impressionevent, you can review the parameters that you're sending in the Parameters panel (in the right-side of the screen). This helps you confirm that the correct information is being processed.
-  Realtime 
 Once you have deployed your app, use the Google Analytics Realtime report to confirm the implementation is working correctly. In the Realtime report, view the Event count by Event name card and select ad_impression to see the event and parameter details for the last 30 minutes.
-  BigQuery 
 Use BigQuery export to extract a sample of one or more days ofad_impressionevents. Use this extracted sample to look for issues, such as zero or not set values, and apply fixes to your code for any unhandled use cases.
Next steps
Visit your Analytics dashboard in the Firebase console or in your linked Analytics property in the Analytics console. Ad revenue is factored into metrics, such as Average Revenue Per User (ARPU) and Lifetime Value (LTV).

