Native Ads

  • Updated
  • Native ads let you monetize your app in a way that’s consistent with its existing design. The AppLovin MAX SDK version 11.0.0 gives you access to an ad’s individual assets so you can design the ad layout to be consistent with the look and feel of your app. The SDK automatically handles image caching and metrics tracking so you can focus on how, when, and where to display ads.

    Templates API

    The easiest way to integrate native ads into your app is to use the templates API. The AppLovin MAX SDK allows you to load an android.view.View with the assets of the native ads pre-populated for you. To use the templates API, select either a “Small” (360×120 dp) or “Medium” (300×250 dp) size template in the Create New Ad Unit screen. The media view for “Small” templates will fill one third of the template’s width, and span the template’s height. The media view for “Medium” templates will span the media content’s width and height while preserving the content’s aspect ratio. Please make sure to set a height for the native ad’s container view in order for the media content to render properly. Select the size that best suits your needs. The SDK automatically handles the view layouts for you.

    Small: Test Ad: Flood-It! Flood-It App for free! Free Popular… Install. Medium: Test Ad: Flood-It! Flood-It App for free! Free Popular Casual Game. Install.

    Loading a Native Ad

    To load a native ad, instantiate a MaxNativeAdLoader corresponding to your ad unit and call its loadAd() method. Implement MaxNativeAdLoadListener so that you are notified when your native ad is ready, and implement MaxAdListener to be notified of other ad-related events.

    Remember to clean up unused instances of unused native ads by calling the destroy() method.

    Native ads are expected to be shown within the ad expiration window of four hours. Impressions associated with ads shown outside of this window will be invalidated.

    • public class ExampleActivity extends Activity
      {
        private MaxNativeAdLoader nativeAdLoader;
        private MaxAd             nativeAd;
      
        void createNativeAd()
        {
          FrameLayout nativeAdContainer = findViewById( R.id.native_ad_layout );
      
          nativeAdLoader = new MaxNativeAdLoader( "ad_unit_ID", this );
          nativeAdLoader.setNativeAdListener( new MaxNativeAdListener()
          {
            @Override
            public void onNativeAdLoaded(final MaxNativeAdView nativeAdView, final MaxAd ad)
            {
              // Clean up any pre-existing native ad to prevent memory leaks.
              if ( nativeAd != null )
              {
                nativeAdLoader.destroy( nativeAd );
              }
      
              // Save ad for cleanup.
              nativeAd = ad;
      
              // Add ad view to view.
              nativeAdContainer.removeAllViews();
              nativeAdContainer.addView( nativeAdView );
            }
      
            @Override
            public void onNativeAdLoadFailed(final String adUnitId, final MaxError error)
            {
              // AppLovin recommends that you retry with exponentially higher delays up to a maximum delay
            }
      
            @Override
            public void onNativeAdClicked(final MaxAd ad)
            {
              // Optional click callback
            }
          } );
      
          nativeAdLoader.loadAd();
        }
      }
    • class ExampleActivity : Activity()
      {
        private lateinit var nativeAdLoader: MaxNativeAdLoader
        private var nativeAd: MaxAd? = null
      
        fun createNativeAd()
        {
          val nativeAdContainer = findViewById(R.id.native_ad_layout)
          nativeAdLoader = MaxNativeAdLoader( "ad_unit_ID", this )
          nativeAdLoader.setNativeAdListener(object : MaxNativeAdListener() {
      
            override fun onNativeAdLoaded(nativeAdView: MaxNativeAdView?, ad: MaxAd)
            {
              // Clean up any pre-existing native ad to prevent memory leaks.
              if ( nativeAd != null )
              {
                nativeAdLoader.destroy( nativeAd )
              }
      
              // Save ad for cleanup.
              nativeAd = ad
      
              // Add ad view to view.
              nativeAdContainer.removeAllViews()
              nativeAdContainer.addView( nativeAdView )
            }
      
            override fun onNativeAdLoadFailed(adUnitId: String, error: MaxError)
            {
              // AppLovin recommends that you retry with exponentially higher delays up to a maximum delay
            }
      
            override fun onNativeAdClicked(ad: MaxAd)
            {
              // Optional click callback
            }
          })
          nativeAdLoader.loadAd()
        }
      }

    Asset Sizes

    For AppLovin Exchange demand, the maximum numbers of characters allowed for Title, Description, and CTA are as follows:

    Asset Maximum Character Count
    Title 25 characters
    Description 100 characters. You can add an ellipsis () after 99 characters, as the 100th character.
    CTA 15 characters

    For SDK-mediated networks, the maximum limits are set by the network itself.

    How to Get the Media Content Aspect Ratio

    The following code snippet shows you how to get the media content aspect ratio of your native ad:

    • @Override
      public void onNativeAdLoaded(final MaxNativeAdView adView, final MaxAd ad)
      {
        MaxNativeAd nativeAd = ad.getNativeAd();
        if ( nativeAd != null )
        {
          float aspectRatio = nativeAd.getMediaContentAspectRatio();
        }
      }
    • override fun onNativeAdLoaded(nativeAdView: MaxNativeAdView?, ad: MaxAd) {
        val nativeAd = ad.nativeAd
        if (nativeAd != null) {
          val aspectRatio = nativeAd.mediaContentAspectRatio
        }
      }

    Some networks do not provide media content aspect ratios, in which case the value will be zero.

    Supported Adapter Versions

    Ad Network Adapter Version
    BidMachine 1.9.4.1
    Google Ad Manager 20.5.0.2
    Google bidding and Google AdMob 20.5.0.2
    InMobi 10.0.5.3
    LINE 2021.5.11.9
    Meta Audience Network 6.8.0.3
    Mintegral 15.8.1.1
    myTarget 5.14.4.2
    Pangle 4.1.1.5.2
    Smaato 21.6.7.1
    Yandex 5.3.0.1
  • Native ads let you monetize your app in a way that’s consistent with its existing design. The AppLovin MAX SDK version 11.0.0 gives you access to an ad’s individual assets so you can design the ad layout to be consistent with the look and feel of your app. The SDK automatically handles image caching and metrics tracking so you can focus on how, when, and where to display ads.

    Manual API

    Use this API if you have custom views and you want to manually load native ad assets into those views. This integration method involves three high-level steps:

    1. Bind UI Components.
    2. Load the Native Ad.
    3. Destroy the Native Ad.

    To use the manual API, select the Manual template in the Create New Ad Unit screen:

    Template: ☐ Small, ☐ Medium, ☒ Manual

    Bind UI Components

    You can bind custom UI components to the MAX SDK and render native ad assets into those components. This example demonstrates this with custom views created using the Layout Editor and unique view IDs, but you could also use this method if you create your views programmatically.

    Per AppLovin’s policy, your ad must contain the Privacy Information icon. This icon links to an important privacy notice. You can bind to it via MaxNativeAdViewBinder.Builder#setOptionsContentViewGroupId(…).

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="https://schemas.android.com/apk/res/android"
      android:layout_width="match_parent"
      android:layout_height="wrap_content">
    
      <ImageView
        android:id="@+id/icon_image_view"
      … />
      <LinearLayout
        android:id="@+id/ad_options_view"
      … />
      <TextView
        android:id="@+id/title_text_view"
      … />
      <FrameLayout
        android:id="@+id/star_rating_view"
      … />
      <TextView
        android:id="@+id/advertiser_textView"
      … />
      <TextView
        android:id="@+id/body_text_view"
      … />
      <FrameLayout
        android:id="@+id/media_view_container"
      … />
      <Button
        android:id="@+id/cta_button"
      … />
    </androidx.constraintlayout.widget.ConstraintLayout>

    Next, bind the subviews using unique view IDs with an instance of MaxNativeAdViewBinder. AppLovin does not guarantee a network will return certain assets.

    • public class ExampleActivity
              extends Activity
              implements MaxAdRevenueListener
      {
        ⋮
        private MaxNativeAdView createNativeAdView()
        {
          MaxNativeAdViewBinder binder = new MaxNativeAdViewBinder.Builder( R.layout.native_custom_ad_view )
            .setTitleTextViewId( R.id.title_text_view )
            .setBodyTextViewId( R.id.body_text_view )
            .setStarRatingContentViewGroupId( R.id.star_rating_view )
            .setAdvertiserTextViewId( R.id.advertiser_textView )
            .setIconImageViewId( R.id.icon_image_view )
            .setMediaContentViewGroupId( R.id.media_view_container )
            .setOptionsContentViewGroupId( R.id.options_view )
            .setCallToActionButtonId( R.id.cta_button )
            .build();
      
          return new MaxNativeAdView( binder, this );
        }
        ⋮
      }
    • class ExampleActivity : Activity(), MaxAdRevenueListener
      {
        ⋮
        private fun createNativeAdView(): MaxNativeAdView
        {
          val binder: MaxNativeAdViewBinder =
            MaxNativeAdViewBinder.Builder(R.layout.native_custom_ad_view)
              .setTitleTextViewId(R.id.title_text_view)
              .setBodyTextViewId(R.id.body_text_view)
              .setStarRatingContentViewGroupId(R.id.star_rating_view )
              .setAdvertiserTextViewId(R.id.advertiser_textView)
              .setIconImageViewId(R.id.icon_image_view)
              .setMediaContentViewGroupId(R.id.media_view_container)
              .setOptionsContentViewGroupId(R.id.options_view)
              .setCallToActionButtonId(R.id.cta_button)
              .build()
          return MaxNativeAdView(binder, this)
        }
        ⋮
      }

    Please ensure you follow each network’s guidance and bind their required ad assets as they may invalidate your impressions otherwise.

    Load the Native Ad

    Load a Pre-Rendered Ad

    To load a pre-rendered native ad, instantiate a MaxNativeAdLoader corresponding to your Ad Unit ID and call its loadAd(MaxNativeAdView) method. Implement and set the MaxNativeAdLoadListener so that you are notified when your native ad’s load state changes.

    Load and Render Ad Separately

    To load a native ad, instantiate a MaxNativeAdLoader corresponding to your Ad Unit ID and call its loadAd() method. Implement and set the MaxNativeAdLoadListener so that you are notified when your native ad’s load state changes. Then use the MaxAd returned in onNativeAdLoaded to render the ad view by calling MaxNativeAdLoader.render(MaxNativeAdView, MaxAd).

    Native ads are expected to be shown within the ad expiration window of four hours. Impressions associated with ads shown outside of this window will be invalidated.

    Destroy the Native Ad

    Once you are no longer using a native ad, you must clean up its resources by calling the destroy() method. If you do not do so, the performance of your app will degrade over time. Below is an example of how you load and destroy a native ad, after you have bound the UI components from the previous step.

    • public class ExampleActivity
              extends Activity
              implements MaxAdRevenueListener
      {
        private ViewGroup         nativeAdContainerView;
        private MaxNativeAdLoader nativeAdLoader;
        private MaxAd             loadedNativeAd;
      
        ⋮
      
        private void createNativeAdLoader()
        {
          nativeAdLoader = new MaxNativeAdLoader( "ad_unit_ID", this );
          nativeAdLoader.setRevenueListener( this );
          nativeAdLoader.setNativeAdListener( new NativeAdListener() );
        }
      
        private void loadNativeAd()
        {
          nativeAdLoader.loadAd( createNativeAdView() );
        }
      
        @Override
        public void onAdRevenuePaid(final MaxAd ad) { }
      
        private class NativeAdListener
                extends MaxNativeAdListener
        {
          @Override
          public void onNativeAdLoaded(final MaxNativeAdView nativeAdView, final MaxAd nativeAd)
          {
            // Clean up any pre-existing native ad to prevent memory leaks.
            if ( loadedNativeAd != null )
            {
              nativeAdLoader.destroy( loadedNativeAd );
            }
      
            // Save ad for cleanup.
            loadedNativeAd = nativeAd;
      
            nativeAdContainerView.removeAllViews();
            nativeAdContainerView.addView( nativeAdView );
          }
      
          @Override
          public void onNativeAdLoadFailed(final String adUnitId, final MaxError error)
          {
            // Native ad load failed.
            // AppLovin recommends retrying with exponentially higher delays up to a maximum delay.
          }
      
          @Override
          public void onNativeAdClicked(final MaxAd nativeAd) { }
        }
      }
    • class ExampleActivity : Activity(), MaxAdRevenueListener
      {
        private val nativeAdContainerView: ViewGroup? = null
        private var nativeAdLoader: MaxNativeAdLoader? = null
        private var loadedNativeAd: MaxAd? = null
      
        ⋮
      
        private fun createNativeAdLoader()
        {
          nativeAdLoader = MaxNativeAdLoader("ad_unit_ID", this)
          nativeAdLoader.setRevenueListener(this)
          nativeAdLoader.setNativeAdListener(NativeAdListener())
        }
      
        private fun loadNativeAd()
        {
          nativeAdLoader.loadAd(createNativeAdView())
        }
      
        override fun onAdRevenuePaid(ad: MaxAd) {}
      
        private inner class NativeAdListener : MaxNativeAdListener()
        {
          override fun onNativeAdLoaded(nativeAdView: MaxNativeAdView?, nativeAd: MaxAd)
          {
            // Clean up any pre-existing native ad to prevent memory leaks.
            if (loadedNativeAd != null)
            {
              nativeAdLoader.destroy(loadedNativeAd)
            }
      
            // Save ad for cleanup.
            loadedNativeAd = nativeAd
            nativeAdContainerView.removeAllViews()
            nativeAdContainerView.addView(nativeAdView)
          }
      
          override fun onNativeAdLoadFailed(adUnitId: String, error: MaxError)
          {
            // Native ad load failed.
            // AppLovin recommends retrying with exponentially higher delays up to a maximum delay.
          }
      
          override fun onNativeAdClicked(nativeAd: MaxAd) {}
        }
      }

    Asset Sizes

    AppLovin recommends that you incorporate as many of the native elements as appropriate in the context of what the rest of your app looks like, such as the Title and Media View or Icon. Giving the user more information helps them decide whether they want to click on the ad.

    For AppLovin Exchange demand, the maximum numbers of characters allowed for Title, Description, and CTA are as follows:

    Asset Maximum Character Count
    Title 25 characters
    Description 100 characters. You can add an ellipsis () after 99 characters, as the 100th character.
    CTA 15 characters

    For SDK-mediated networks, the maximum limits are set by the network itself.

    How to Get the Media Content Aspect Ratio

    The following code snippet shows you how to get the media content aspect ratio of your native ad:

    • @Override
      public void onNativeAdLoaded(final MaxNativeAdView adView, final MaxAd ad)
      {
        MaxNativeAd nativeAd = ad.getNativeAd();
        if ( nativeAd != null )
        {
          float aspectRatio = nativeAd.getMediaContentAspectRatio();
        }
      }
    • override fun onNativeAdLoaded(nativeAdView: MaxNativeAdView?, ad: MaxAd) {
        val nativeAd = ad.nativeAd
        if (nativeAd != null) {
          val aspectRatio = nativeAd.mediaContentAspectRatio
        }
      }

    Some networks do not provide media content aspect ratios, in which case the value will be zero.

    Supported Adapter Versions

    Ad Network Adapter Version
    BidMachine 1.9.4.1
    Google Ad Manager 20.5.0.2
    Google bidding and Google AdMob 20.5.0.2
    InMobi 10.0.5.3
    LINE 2021.5.11.9
    Meta Audience Network 6.8.0.3
    Mintegral 15.8.1.1
    myTarget 5.14.4.2
    Pangle 4.1.1.5.2
    Smaato 21.6.7.1
    Yandex 5.3.0.1

    Star Rating

    As of the AppLovin MAX SDK v11.7.0, you can access and render the star rating for the advertised app. The value, if available, is a floating point number in the range of [0.0, 5.0].

    The MAX SDK automatically renders the stars in the container view that you designate as the star rating container. If the network does not provide the star rating, or the star rating is < 3, the SDK leaves the star rating container view empty. You are responsible for adjusting your layout accordingly.

    To retrieve the star rating for the current ad:

    • @Override
      public void onNativeAdLoaded(final MaxNativeAdView adView, final MaxAd ad)
      {
        MaxNativeAd nativeAd = ad.getNativeAd();
        if ( nativeAd != null )
        {
          Double starRating = nativeAd.getStarRating();
          if ( starRating == null || starRating < 3 )
          {
            // Star rating not available, or < 3 - hide star rating container view
            return;
          }
          // Star rating available and >= 3 - show star rating container view
        }
      }
    • override fun onNativeAdLoaded(nativeAdView: MaxNativeAdView?, ad: MaxAd) {
        val nativeAd = ad.nativeAd
        if (nativeAd != null) {
          val starRating = nativeAd.starRating
          if (starRating == null || starRating < 3) {
            // Star rating not available, or < 3 - hide star rating container view
            return
          }
          // Star rating available and >= 3 - show star rating container view
        }
      }

    Supported Adapter Versions (Star Rating)

    Ad Network Adapter Version
    Google Ad Manager 20.5.0.2
    Google bidding and Google AdMob 20.5.0.2
    InMobi 10.1.2.3
    Mintegral 16.3.41.1
    Yahoo 2.2.0.7
  • Ad Placer is available starting in AppLovin MAX Android SDK version 11.4.0. Native ads let you monetize your app in a way that’s consistent with its existing design. Native ads give you access to an ad’s individual assets so you can design the ad layout to be consistent with the look and feel of your app. The SDK automatically handles image caching and metrics tracking so you can focus on how, when, and where to display ads.

    Ad Placer API

    This API automatically inserts native ads into your existing content stream using RecyclerView. To integrate this API, take the following high-level steps:

    1. Set up native ad layout.
    2. Create ad placer settings.
    3. Set up ad placer.
    4. Configure ad rendering settings.
    5. Optionally, set listener.

    Per AppLovin’s policy, your ad must contain the Privacy Information icon. This icon links to an important privacy notice. You can bind to it via MaxNativeAdViewBinder.Builder#setOptionsContentViewGroupId(…).

    1. Set Up Native Ad Layout

    Ad placer supports either template or manual native ad layouts. See the “Native (Tempates)” and “Native (Manual)” tabs above for instructions on how to configure your ad units, as well as any required setup. See Configure Ad Rendering Settings below for more information on setting up the ad placer to support your layout.

    Please ensure you follow each network’s guidance and bind their required ad assets as they may invalidate your impressions otherwise.

    2. Create Ad Placer Settings

    Create a MaxAdPlacerSettings object with your ad unit identifier. This object configures your ad placer and provides positioning information for ads in your feed.

    • MaxAdPlacerSettings settings = new MaxAdPlacerSettings( "ad_unit_ID" );
    • val settings = MaxAdPlacerSettings( "ad_unit_ID" )

    Configure Ad Positions

    Ad placer positions ads in your feed based on at least one of the following:

    1. a list of fixed index paths that indicate where to place ads
    2. a repeating interval at which to regularly insert ads
      • Your ad placer inserts repeating ads after the last fixed position. If you do not set any fixed positions, your ad placer adds repeating ads after the first position in the stream. This value must be greater than or equal to 2; any value less than that disables it.

    Configure ad positions by modifying MaxAdPlacerSettings:

    1. To add a new fixed ad position, for example at row 1:
      • settings.addFixedPosition( 3 );
      • settings.addFixedPosition( 3 )
    2. To remove existing fixed positions:
      • settings.resetFixedPositions();
      • settings.resetFixedPositions()
    3. To change the repeating interval; for example, to insert ads at every fifth position in the feed:
      • settings.setRepeatingInterval( 5 );
      • settings.repeatingInterval = 5

    Additional Settings

    You can configure your ad placer by adjusting additional settings in MaxAdPlacerSettings:

    maxAdCount
    Set this to the maximum number of ads in a stream (default=256). If a stream contains multiple sections, this determines the maximum number of ads per ad section.
    maxPreloadedAdCount
    Set this to the maximum number of ads to preload for placement in a stream (default=4).

    3. Set Up Ad Placer

    Choose one of these two options when you set up your ad placer:

    1. If your feed is based on a RecyclerView, use MaxRecyclerAdapter. The helper class wraps the original adapter to automatically render and insert ads into the feed. You can access the underlying ad placer by calling getAdPlacer().
    2. If your feed uses some other custom UI component you may prefer to subclass or to directly use MaxAdPlacer in your implementation.

    Using MaxRecyclerAdapter

    To set up your ad placer with MaxRecyclerAdapter follow these instructions:

    1. Initialize MaxRecyclerAdapter with your settings, original adapter, and activity:
      • adAdapter = new MaxRecyclerAdapter( settings, adapter, this );
      • adAdapter = MaxRecyclerAdapter( settings, adapter, this )
    2. Set your recycler view’s adapter to the instantiated MaxRecyclerAdapter:
      • recyclerView.setAdapter( adAdapter );
      • recyclerView.adapter = adAdapter
    3. Update your code to implement the following:
      • Whenever you add or delete items from your stream, call the appropriate methods from your adapter to notify the ad placer of updates to your stream:
        • notifyItemInserted()
        • notifyItemRemoved()
        • notifyItemsInserted()
        • notifyItemsRemoved()
      • If you register any data observers on your original adapter, register them on the MaxRecyclerAdapter instead so that they receive the adjusted position of content items after ad insertion.
      • If any other parts of your code depend on a content item’s position before ad insertion, convert the position to its original position by calling adAdapter.getOriginalPosition().
    4. Call loadAds() to start loading ads:
      • adAdapter.loadAds();
      • adAdapter.loadAds()

    The following code shows how you load ads into a recycler view by using MaxRecyclerAdapter:

    • @Override
      public void onCreate(Bundle savedInstanceState)
      {
        super.onCreate( savedInstanceState );
        // Create your own recycler view and original adapter
        ⋮
      
        // Configure ad adapter
        MaxAdPlacerSettings settings = new MaxAdPlacerSettings( "ad_unit_ID" );
        settings.setRepeatingInterval( 5 );
        adAdapter = new MaxRecyclerAdapter( settings, originalAdapter, this );
      
        // Optionally, register listener
        adAdapter.setListener( this );
      
        // Configure recycler view and load ads
        recyclerView.setAdapter( adAdapter );
        adAdapter.loadAds();
      }
      
      @Override
      public void onDestroy()
      {
        adAdapter.destroy();
        super.onDestroy();
      }
         
    • override fun onCreate(savedInstanceState: Bundle?)
      {
        super.onCreate( savedInstanceState )
        // Create your own recycler view and original adapter
        ⋮
      
        // Configure ad adapter
        val settings = MaxAdPlacerSettings( "ad_unit_ID" )
        settings.repeatingInterval = 5
        adAdapter = MaxRecyclerAdapter( settings, originalAdapter, this )
      
        // Optionally, register listener
        adAdapter.listener = this
      
        // Configure recycler view and load ads
        recycler.adapter = adAdapter
        adAdapter.loadAds()
      }
      
      override fun onDestroy()
      {
        adAdapter.destroy()
        super.onDestroy()
      }

    4. Configure Ad Rendering Settings

    Templates

    If you use a default template, the ad view will automatically size to 360×120 for “Small” and 360×300 for “Medium” templates.

    You can customize the rendered ad size by calling setAdSize on the ad placer before you load ads. For example, to set the ad size with a width of 300 and height of 200:

    • adAdapter.getAdPlacer().setAdSize( 300, 200 );
    • adAdapter.adPlacer.setAdSize( 300, 200 )

    You may also pass a value of −1 (MATCH_PARENT) for the width or height to have the ad view fill the corresponding dimension of its parent view.

    Manual

    If you use a manual layout, you must call setNativeAdViewBinder on the ad placer before you load ads. Always set the ad size when you use manual templates, for optimal rendering.

    When you use MaxRecyclerAdapter, if the width of the desired ad size exceeds the width of its parent item view, the ad placer will resize to fit the width of the item while preserving the height (for “Small” templates) or the aspect ratio (for “Medium” templates). For manual templates, the dimensions will not be resized to fit.

    5. Optionally Set Listener

    The ad placer supports an optional listener so you can be notified of events:

    • onAdLoaded()
    • onAdRemoved()
    • onAdClicked()
    • onAdRevenuePaid()