You can set a placement name for each ad unit (for example, “Rewarded VideoLevels”, “INTER_levelEnd”, or “RewardedVideoCoinStore”). This can help you gather statistics for different placement categories. The following snippets show you how to set the placement name for different ad formats.
For banners and MRECs you must set the placement name before you load the banner or MREC.
adView.setPlacement( "«placement»" );
adView.loadAd();adView.setPlacement( "«placement»" )
adView.loadAd()interstitial.showAd( "«placement»" );interstitial.showAd( "«placement»" )rewardedAd.showAd( "«placement»" );rewardedAd.showAd( "«placement»" )nativeAdLoader.setPlacement( "«placement»" );nativeAdLoader.setPlacement( "«placement»" )MaxAdPlacerSettings settings = new MaxAdPlacerSettings( "«ad-unit-ID»" );
settings.setPlacement( "«placement»" );val settings = MaxAdPlacerSettings( "«ad-unit-ID»" )
settings.placement = "«placement»"You can mute audio for some mediated SDK networks when you launch your app. The networks that support this feature via the AppLovin SDK are:
For other networks, consult your network’s account team to learn whether this feature is available and how to access it.
The following code snippets show how you mute audio on those networks that support this feature:
AppLovinSdk sdk = AppLovinSdk.getInstance( context );
sdk.getSettings().setMuted( true ); // to mute
sdk.getSettings().setMuted( false ); // to unmuteval sdk = AppLovinSdk.getInstance( context )
sdk.settings.setMuted( true ) // to mute
sdk.settings.setMuted( false ) // to unmuteSet the mute state before you load ads. Some networks (like Google bidding and Google AdMob) return muted or unmuted videos depending on what the mute state is before ad load.
Note: if you mute ads, this may result in lower ad revenue.
Enable verbose logs by setting a boolean flag in the settings object of the SDK:
AppLovinSdk.getInstance( context ).getSettings().setVerboseLogging( true );AppLovinSdk.getInstance( context ).settings.setVerboseLogging( true )You can also enable verbose logging by editing your application’s Android Manifest file.
Add a <meta-data> element like the following:
<application>
⋮
<meta-data android:name="applovin.sdk.verbose_logging" android:value="true" />
⋮
</application>
To verify that you enabled verbose logs, check for the line that reads Verbose Logging On: true in the initialization section of the AppLovin SDK logs:
AppLovin SDK
Version: 12.4.2
⋮
Verbose Logging On: true
⋮
AppLovin SDK tags its logs with the tag “/AppLovinSdk: [AppLovinSdk]”.
You can retrieve the creative ID and the network name of displayed ads from mediated networks. Refer to the Creative Debugger documentation for more information.
To retrieve the name of the DSP for a MAX ad served from AppLovin Exchange, call the ad’s getDspName() method:
@Override
public void onAdLoaded(final MaxAd ad)
{
System.out.println( "AppLovin Exchange DSP name: " + ad.getDspName() );
}override fun onAdLoaded(maxAd: MaxAd)
{
println( "AppLovin Exchange DSP Name: " + maxAd.getDspName() )
}You can access impression-level user revenue data on the client side. You can use this data to compare different sources and campaigns. You can also access this data by using the MAX user revenue API. MMPs who want to access this data should review the impression-level user revenue API for MMPs documentation.
“Take Ad-Revenue Attribution to the Next Level With MAX” from AppLovin’s Blog
You can share impression-level ad revenue data with your mobile measurement partner of choice, such as Adjust for all supported networks.
You can retrieve the revenue amount in all ad lifecycle callbacks.
Do this by creating a MaxAdRevenueListener, implementing its onAdRevenuePaid() method, and passing that listener to setRevenueListener().
The following example shows how to implement such an “ad revenue paid” callback:
@Override
public void onAdRevenuePaid(final MaxAd ad)
{
double revenue = ad.getRevenue(); // In USD
// Miscellaneous data
String countryCode = AppLovinSdk.getInstance( context ).getConfiguration().getCountryCode(); // "US" for the United States, etc - Note: Do not confuse this with currency code which is "USD"
String networkName = ad.getNetworkName(); // Display name of the network that showed the ad
String adUnitId = ad.getAdUnitId(); // The MAX Ad Unit ID
MaxAdFormat adFormat = ad.getFormat(); // The ad format of the ad (e.g. BANNER, MREC, INTERSTITIAL, REWARDED)
String placement = ad.getPlacement(); // The placement this ad's postbacks are tied to
String networkPlacement = ad.getNetworkPlacement(); // The placement ID from the network that showed the ad
}override fun onAdRevenuePaid(ad: MaxAd)
{
val revenue = ad.revenue // In USD
// Miscellaneous data
val countryCode = AppLovinSdk.getInstance( context ).configuration.countryCode // "US" for the United States, etc - Note: Do not confuse this with currency code which is "USD"
val networkName = ad.networkName // Display name of the network that showed the ad
val adUnitId = ad.adUnitId // The MAX Ad Unit ID
val adFormat = ad.format // The ad format of the ad (e.g. BANNER, MREC, INTERSTITIAL, REWARDED)
val placement = ad.placement // The placement this ad's postbacks are tied to
val networkPlacement = ad.networkPlacement // The placement ID from the network that showed the ad
}The value of ad.getRevenue()/ad.revenue may be -1in the case of an error.
You can also retrieve a precision evaluation for the revenue value, as shown in the following example:
String revenuePrecision = ad.getRevenuePrecision();val revenuePrecision = ad.revenuePrecisionThis precision takes one of the following values:
"publisher_defined""exact""estimated""undefined"""To listen for an ad request, set a MaxAdRequestListener, implement its onAdRequestStarted() method, and pass that listener to setRequestListener().
The following example shows how to implement such an “ad request started” callback:
@Override
public void onAdRequestStarted(final String adUnitId)
{
// Ad request started here
}override fun onAdRequestStarted(adUnitId: String)
{
// Ad request started here
}You can initialize the SDK with specific ad units by specifying your ad units in the AppLovinSdkInitializationConfiguration.
If you do so, the SDK only initializes those networks that you configured for the ad units you specify.
If you do not specify any ad units, the SDK assumes the current session needs all your ad units.
In such a case it initializes all networks that you configured for those ad units.
The following example shows how you implement this feature:
AppLovinSdkInitializationConfiguration.Builder initConfigBuilder = AppLovinSdkInitializationConfiguration.builder( «your-SDK-key» );
initConfigBuilder.setMediationProvider( AppLovinMediationProvider.MAX );
List<String> adUnitIds = new ArrayList<>();
adUnitIds.add( "«ad-unit-ID-1»" );
adUnitIds.add( "«ad-unit-ID-2»" );
initConfigBuilder.setAdUnitIds( adUnitIds ).build();
AppLovinSdk.getInstance( this ).initialize( initConfigBuilder, new AppLovinSdk.SdkInitializationListener()
{
@Override
public void onSdkInitialized(final AppLovinSdkConfiguration sdkConfig)
{
⋮
}
} );val adUnitIds = arrayListOf("«ad-unit-ID-1»", "«ad-unit-ID-2»")
val initConfigBuilder = AppLovinSdkInitializationConfiguration.Builder(«your-SDK-key»)
.setMediationProvider(AppLovinMediationProvider.MAX)
.setAdUnitIds(adUnitIds)
.build()
AppLovinSdk.getInstance(this).initialize(initConfigBuilder) { sdkConfig ->
⋮
}You can find your SDK key in the Account > General > Keys section of the AppLovin dashboard.
When you use selective init, MAX excludes any ad units that you do not explicitly specify from serving ads for the current session.
Selective init has no effect when you enable test mode.
The Waterfall Information API tells you about the current waterfall for an ad (one that has loaded or failed to load). The API returns the ad load state, latency, credentials, and mediated network information for each ad in the waterfall. If an ad in the waterfall fails to load, the API provides error information.
| value | explanation |
|---|---|
| 0 | Ad Load Not Attempted |
| 1 | Ad Loaded |
| 2 | Ad Failed To Load |
@Override
public void onAdLoaded(final MaxAd ad)
{
MaxAdWaterfallInfo waterfall = ad.getWaterfall();
if ( waterfall == null ) return;
System.out.println( "Waterfall Name: " + waterfall.getName() + " and Test Name: " + waterfall.getTestName() );
System.out.println( "Waterfall latency was: " + waterfall.getLatencyMillis() + " milliseconds" );
String waterfallInfoStr;
for ( MaxNetworkResponseInfo networkResponse : waterfall.getNetworkResponses() )
{
waterfallInfoStr = "Network -> " + networkResponse.getMediatedNetwork() +
"\n...adLoadState: " + networkResponse.getAdLoadState() +
"\n...latency: " + networkResponse.getLatencyMillis() + " milliseconds" +
"\n...credentials: " + networkResponse.getCredentials();
if ( networkResponse.getError() != null )
{
waterfallInfoStr += "\n...error: " + networkResponse.getError();
}
System.out.println( waterfallInfoStr );
}
}
@Override
public void onAdLoadFailed(final String adUnitId, final MaxError error)
{
MaxAdWaterfallInfo waterfall = error.getWaterfall();
if ( waterfall == null ) return;
System.out.println( "Waterfall Name: " + waterfall.getName() + " and Test Name: " + waterfall.getTestName() );
System.out.println( "Waterfall latency was: " + waterfall.getLatencyMillis() + " milliseconds" );
for ( MaxNetworkResponseInfo networkResponse : waterfall.getNetworkResponses() )
{
System.out.println( "Network -> " + networkResponse.getMediatedNetwork() +
"...latency: " + networkResponse.getLatencyMillis() +
"...credentials: " + networkResponse.getCredentials() + " milliseconds" +
"...error: " + networkResponse.getError() );
}
}override fun onAdLoaded(ad: MaxAd?) {
val waterfall = ad?.waterfall ?: return
println( "Waterfall Name: " + waterfall.name + " and Test Name: " + waterfall.testName )
println( "Waterfall latency was: " + waterfall.latencyMillis + " milliseconds" )
var waterfallInfoStr: String
for ( networkResponse in waterfall.networkResponses ) {
waterfallInfoStr = "Network -> ${ networkResponse.mediatedNetwork }" +
"\n...adLoadState: ${ networkResponse.adLoadState }" +
"\n...latency: ${ networkResponse.latencyMillis } milliseconds" +
"\n...credentials: ${ networkResponse.credentials }"
if ( networkResponse.error != null ) {
waterfallInfoStr += "\n...error: ${ networkResponse.error }"
}
println( waterfallInfoStr )
}
}
override fun onAdLoadFailed(adUnitId: String?, error: MaxError?) {
val waterfall = error?.waterfall ?: return
println( "Waterfall Name: " + waterfall.name + " and Test Name: " + waterfall.testName )
println( "Waterfall latency was: " + waterfall.latencyMillis + " milliseconds" )
for ( networkResponse in waterfall.networkResponses ) {
println( "Network -> ${ networkResponse.mediatedNetwork }" +
"...latency: ${ networkResponse.latencyMillis } milliseconds" +
"...credentials: ${ networkResponse.credentials }" +
"...error: ${ networkResponse.error }" )
}
}Waterfall Name: Default Waterfall and Test Name: Control
Waterfall latency was: 6668 milliseconds
Network -> MaxMediatedNetworkInfo{name=ironSource, adapterClassName=com.applovin.mediation.adapters.IronSourceMediationAdapter, adapterVersion=7.1.10.1.0, sdkVersion=7.1.10.1}
...adLoadState: FAILED_TO_LOAD
...latency: 1542 milliseconds
...credentials: Bundle[{app_key=88a0872d, placement_id=0}]
...error: MaxAdapterError{errorCode=-5200, errorMessage="Unspecified Error", thirdPartySdkErrorCode=510, thirdPartySdkErrorMessage="Load failed - Failed to load Interstitial ad"}
Network -> MaxMediatedNetworkInfo{name=Mintegral, adapterClassName=com.applovin.mediation.adapters.MintegralMediationAdapter, adapterVersion=15.7.61.0, sdkVersion=MAL_15.7.61}
...adLoadState: AD_LOADED
...latency: 4676 milliseconds
...credentials: Bundle[{app_id=118244, app_key=57205cd060e7e051e5bcccaae6bd2b64, placement_id=515486}]
Network -> MaxMediatedNetworkInfo{name=ironSource, adapterClassName=com.applovin.mediation.adapters.IronSourceMediationAdapter, adapterVersion=7.1.10.1.0, sdkVersion=7.1.10.1}
...adLoadState: AD_LOAD_NOT_ATTEMPTED
...latency: -1 milliseconds
...credentials: Bundle[{app_key=88a0872d, placement_id=1171359}]
If the waterfall is empty, MaxError.getWaterfall() returns null.
If so, you cannot interrogate the waterfall properties.
However, you can retrieve the ad load latency for an empty waterfall by calling the getRequestLatencyMillis() method:
@Override
public void onAdLoaded(final MaxAd ad)
{
System.out.println("Successful ad load latency: " + ad.getRequestLatencyMillis() + " ms");
}
@Override
public void onAdLoadFailed(final String adUnitId, final MaxError error)
{
System.out.println("Failed ad load latency: " + error.getRequestLatencyMillis() + " ms");
}override fun onAdLoaded(ad: MaxAd)
{
println( "Successful ad load latency: " + ad.getRequestLatencyMillis() + " ms" )
}
override fun onAdLoadFailed(adUnitId: String, error: MaxError)
{
println( "Failed ad load latency: " + error.getRequestLatencyMillis() + " ms" )
}You can customize banner and MREC ad refresh intervals via the API, just as you can configure them in the Ad Unit UI. The minimum and maximum refresh intervals allowed are 10 seconds and 120 seconds, respectively. MAX ignores values outside these limits. The following code samples show you how to customize these refresh intervals:
// Where adView is an instance of MaxAdView
adView.setExtraParameter( "ad_refresh_seconds", «ad-refresh-rate» );// Where adView is an instance of MaxAdView
adView.setExtraParameter( "ad_refresh_seconds", «ad-refresh-rate» )