Advanced Settings

Ad Placements

You can set a placement name for each ad unit (for example, “Rewarded VideoLevels”, “INTER_levelEnd”, or “RewardedVideoCoinStore”). This can help you aggregate statistics for different placement categories. Below are code snippets that show you how to set the placement name for various ad formats.

Banners / MRECs

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()

Interstitials

  • interstitial.showAd( "placement" );
  • interstitial.showAd( "placement" )

Rewarded Ads

  • rewardedAd.showAd( "placement" );
  • rewardedAd.showAd( "placement" )

Native Ads

  • nativeAdLoader.setPlacement( "placement" );
  • nativeAdLoader.setPlacement( "placement" )

Native Ads (Ad Placer)

  • MaxAdPlacerSettings settings = new MaxAdPlacerSettings( "ad-unit-ID" );
    settings.setPlacement( "placement" );
  • val settings = MaxAdPlacerSettings( "ad-unit-ID" )
    settings.placement = "placement"

Mute Audio

You can mute audio for certain mediated SDK networks when you launch your app. The networks that support this functionality via the AppLovin SDK are Google bidding and Google AdMob, AppLovin, DT Exchange, Google Ad Manager, LINE, Mintegral, Tencent, and Verve. For other networks, consult your network’s account team to learn whether this functionality is available and how to access it.

DT Exchange supports muting audio only on interstitial ads.

The following code snippets show how you mute audio on the supported networks:

  • AppLovinSdk sdk = AppLovinSdk.getInstance( context );
    sdk.getSettings().setMuted( true );  // to mute
    sdk.getSettings().setMuted( false ); // to unmute
  • val sdk = AppLovinSdk.getInstance( context )
    sdk.settings.setMuted( true )  // to mute
    sdk.settings.setMuted( false ) // to unmute

Set 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.

Enable Verbose Logging

Enable verbose logs by setting a boolean flag in the settings object of the SDK:

Programmatically

  • AppLovinSdk.getInstance( context ).getSettings().setVerboseLogging( true );
  • AppLovinSdk.getInstance( context ).settings.setVerboseLogging( true )

Android Manifest

You can also enable verbose logging by editing your application’s Android Manifest file and adding a <meta-data> element like the following:

<application>
⋮
  <meta-data
    android:name="applovin.sdk.verbose_logging"
    android:value="true" />
⋮
</application>

Verification

To verify that you enabled verbose logs successfully you can check for the line that reads Verbose Logging On: true in the initialization section of the AppLovin SDK logs:

AppLovin SDK
Version: 11.4.2
⋮
Verbose Logging On: true
⋮

AppLovin SDK tags its logs with the tag /AppLovinSdk: [AppLovinSdk].

Segment Name

You can compartmentalize your users into “segments.” This can help you analyze users with particular characteristics, or can be helpful as a part of A/B testing. Each segment has a name of your choice, in the form of a string of 32 or fewer alphanumeric characters. You can set or retrieve the segment name of the current user from the AppLovin SDK by means of the userSegment property:

  • AppLovinSdk.getInstance( context ).getUserSegment().setName( "segment-name" );
  • AppLovinSdk.getInstance( context ).userSegment.name = "segment-name"

Creative ID and Network Name

You can retrieve the creative ID and the network name of displayed ads of various mediated networks. Refer to the Creative Debugger documentation for more information.

DSP Name

You can retrieve the name of the DSP for a MAX ad served from AppLovin Exchange by calling 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() )
    }

Impression-Level User Revenue API

Starting in SDK version 10.3.0, 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 reference the instructions provided at the Impression-Level User Revenue API for MMPs page.

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 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
    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.revenuePrecision

This precision is one of the following values:

"publisher_defined"
revenue is the price assigned by the publisher
"exact"
revenue is the resulting price of a real-time auction
"estimated"
the revenue amount is based on Auto CPM or FB Bidding estimates
"undefined"
no revenue amount is defined and there is not enough data to estimate
""
revenue and precision are not valid (for example, in test mode)

Establishing Ad Request Callbacks

You can listen for when an ad request is made by setting a MaxAdRequestListener, implementing its onAdRequestStarted() method, and passing 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
    }

Selective Init

Starting in SDK version 10.0.0, you can initialize the SDK with specific ad units. If you do so, the SDK only initializes those networks that you have configured for the ad units you specify. If you do not specify any ad units, the SDK assumes the current session needs all of your ad units and so it initializes all networks that you have configured for them. The following example shows how you implement this feature:

  • AppLovinSdkSettings settings = new AppLovinSdkSettings( context );
    List<String> adUnitIds = new ArrayList<>();
    adUnitIds.add( "ad_unit_id_1" );
    adUnitIds.add( "ad_unit_id_2" );
    settings.setInitializationAdUnitIds( adUnitIds );
    
    AppLovinSdk sdk = AppLovinSdk.getInstance( settings, context );
    sdk.setMediationProvider( "max" );
    sdk.initializeSdk( new AppLovinSdk.SdkInitializationListener() {
      @Override
      public void onSdkInitialized(final AppLovinSdkConfiguration config) {
        ⋮
      }
    } );
  • val settings = AppLovinSdkSettings( context )
    settings.initializationAdUnitIds = arrayListOf( "ad_unit_id_1", "ad_unit_id_2" )
    
    val sdk = AppLovinSdk.getInstance( settings, context );
    sdk.mediationProvider = "max"
    sdk.initializeSdk({ config ->
      ⋮
    })

When you use selective init, any ad units that you do not explicitly specify are excluded from serving ads for the current session.

Waterfall Information API

This feature allows you to see the information about the current waterfall for an ad that has loaded or failed to load. The network responses provide 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 network response provides error information.

This API is supported as of Android SDK version 10.3.5.

AdLoadState Values

0 Ad Load Not Attempted
1 Ad Loaded
2 Ad Failed To Load

Example

  • @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 }" )
      }
    }

Output

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 was empty, MaxError.getWaterfall() will return null and so you will not be able to interrogate the waterfall properties. However, you can still retrieve the ad load latency for an empty waterfall by means of 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" )
    }

Customize Banner / MREC Ad Refresh

You can customize banner and MREC ad refresh intervals directly in your integration, 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. Values outside of these limits are ignored. 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 )