Native Ads Integration

Native ads let you easily monetize your app in a way that’s consistent with its existing design. The MoPub SDK 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.

Prerequisites

Before integrating native ads into your app, ensure you have completed the following items:

  1. Read the Best Practices page for guidelines on how native ads can be displayed in your app.
  2. Follow the Android Getting Started Guide to integrate the MoPub SDK into your project.

Sample Code

Choose an Integration Method

Ad Placer

This approach uses the MoPubStreamAdPlacer to facilitate loading native ads into an app’s content stream (i.e. a scrolling list) (demo). The MoPub SDK provides a MoPubAdAdapter or a MoPubRecyclerAdapter that wrap your existing adapter subclasses to insert ads into a ListView and RecyclerView, respectively. This approach has the advantage of letting the MoPub SDK handle automatically requesting new ads when needed, inserting them into the stream of content, and handling impression tracking and clicks. By default, three native ads will be requested and cached initially, and the SDK will request one at a time as a user scrolls through the feed. Each ad’s expiration timer starts once the ad is loaded/cached. After 4 hours, the SDK will mark these ads as ready for cleanup by the OS.

Manual

This approach is suitable for when the native ad placement is a single view (demo), or in a content stream but when specific flexibility cannot be fulfilled by using the AdPlacer approach. With this method, you will use the MoPubNative class to request and load ads. The MoPub SDK provides an AdapterHelper that you can use to retrieve a pre-populated view containing the rendered ad content and required tracking events. That allows you to easily add the ad view into your parent view. However, publishers have to manually handle ad requests, ad expiration, and cases when there are no fills.

Ad Placer (via MoPubAdAdapter)

The MoPub SDK provides the class MoPubAdAdapter that wraps your existing Adapter subclass to insert ads into a ListView, GridView, or other view that uses an implementation of Adapter (including CursorAdapter).

Adding native ads to your Android app takes three easy steps:

  1. Set up your native ad layout
  2. Place ads in your feed
  3. Create a MoPubAdAdapter to wrap your existing Adapter subclass and begin loading ads

Set up your Native Ad Layout

  1. Start by defining an XML layout for how an ad should look inside your app’s feed. This example layout contains two TextViews for a title and additional text, plus three ImageViews for an icon image, a main image, and a Privacy Information icon image (demo). Choose the assets from the ad that will make it fit in most seamlessly in your app’s feed.

    Your ad must contain the Privacy Information icon. The recommended size for this is 40 dp with a 10dp padding on all sides (so the icon display area is only 20dp by 20dp, but the click area is a bit larger). This icon links to an important privacy notice, and is required for you to use MoPub’s native ads. The MoPub SDK automatically handles tap events on the privacy information icon. For example: res/layout/native_ad_layout.xml

     <RelativeLayout
       xmlns:android="http://schemas.android.com/apk/res/android"
       android:id="@+id/example_view"
       android:layout_width="match_parent"
       android:layout_height="wrap_content">
    
       <ImageView
           android:id="@+id/native_ad_main_image" />
       <ImageView
           android:id="@+id/native_ad_icon_image" />
       <TextView
           android:id="@+id/native_ad_title" />
       <TextView
           android:id="@+id/native_ad_text" />
       <ImageView
           android:id="@+id/native_ad_privacy_information_icon_image"
           android:layout_width="40dp"
           android:layout_height="40dp"
           android:padding="10dp" />
     </RelativeLayout>
    

    IMPORTANT You should set the background property on your ImageViews to null in order to handle PNG transparency gracefully:

       <ImageView
           android:background="@null" />
    

    Note: Starting with the 4.99.0 release of the Facebook Audience Network SDK, if you are mediating Facebook native ads, in place of the above ImageViews, you must register Facebook’s own layouts, like so:

     <!-- Facebook's MediaView for the main image view -->
     <com.facebook.ads.MediaView
         android:id="@+id/native_ad_main_image"></com.facebook.ads.MediaView>
    
     <!-- Facebook's AdIconView for the icon image -->
     <com.facebook.ads.AdIconView
         android:id="@+id/native_ad_icon_image"></com.facebook.ads.AdIconView>
    
     <!-- A RelativeLayout for the AdChoices icon image from Facebook -->
     <RelativeLayout
         android:id="@+id/native_ad_choices_relative_layout"
         android:layout_width="40dp"
         android:layout_height="40dp" />
    
  2. Create a ViewBinder object specifying the binding between your layout XML and the ad’s content. If you use mediation, specific ad networks might require new ViewBinder bindings for additional assets. Make sure to check the Integrating Third Party Ad Networks page for more implementation information.

     ViewBinder viewBinder = new ViewBinder.Builder(R.layout.native_ad_layout)
         .mainImageId(R.id.native_ad_main_image)
         .iconImageId(R.id.native_ad_icon_image)
         .titleId(R.id.native_ad_title)
         .textId(R.id.native_ad_text)
         .privacyInformationIconImageId(R.id.native_ad_privacy_information_icon_image)
         .build();
    

    Note: If you’re displaying direct-sold native ads, you may have additional subviews for text or images available. Extra fields may be added using:

    new ViewBinder.Builder().addExtras(Map<String, Integer> resIds)

    or

    new ViewBinder.Builder().addExtra(String key, int resId)

    Example: Let’s say that in the MoPub Web UI you’ve added the custom fields “sponsoredtext” and “sponsoredimage”:

     "sponsoredtext" : "Sponsored",
     "sponsoredimage" : "http://www.mopub.com/sponsored.jpg"
    

    You would add these sponsored fields to your XML layout, then bind them to the view like this:

     ViewBinder viewBinder = new ViewBinder.Builder(R.layout.native_ad_layout)
       .mainImageId(R.id.native_ad_main_image)
       .iconImageId(R.id.native_ad_icon_image)
       .titleId(R.id.native_ad_title)
       .textId(R.id.native_ad_text)
       .privacyInformationIconImageId(R.id.native_ad_privacy_information_icon_image)
       // Your custom fields are bound with the addExtra() call.
       .addExtra("sponsoredtext", R.id.sponsored_text)
       .addExtra("sponsoredimage", R.id.sponsored_image)
       .build();
    

    Note: If you are adding an image to extras, the key must end with “image”

  3. The MoPubAdAdapter uses a class called MoPubStaticNativeAdRenderer to load ads within your feed. Create an instance with the ViewBinder:

     MoPubStaticNativeAdRenderer adRenderer = new MoPubStaticNativeAdRenderer(viewBinder);
    

Place Ads in your Feed

Next, you’ll need to define where in your feed you’d like ads to appear using the MoPubNativeAdPositioning class to balance ads with your content. We provides sever-side and client-side positioning approaches. In which you can specify:

  • Starting positions in the feed where you always want to display ads and
  • Set the interval at which how often an ad should appear

This allows you to achieve the optimal balance of ads for your app without changing your app code or releasing a new version. To set up server-side positioning:

  1. Update your native ad unit settings page. In the example below, your ads will appear in positions 1, 4, and 7 (where 0 is the position of the first ad). After position 7, your ads will appear every 5 positions. Server-Side Positioning

  2. Once you’ve updated your settings in the UI, set up the MoPubNativeAdPositioning.MoPubServerPositioning object:

     MoPubNativeAdPositioning.MoPubServerPositioning adPositioning =
           MoPubNativeAdPositioning.serverPositioning();
    

Client-side Positioning

The SDK does support setting positioning directly in the method. In this case, the position setting on ad unit page will be ignored. To set up client-side positioning:

  1. Create an MoPubClientPositioning object

     MoPubClientPositioning adPositioning = MoPubNativeAdPositioning.clientPositioning();
    
  2. If you want ads to appear at certain fixed positions within your feed, use addFixedPosition

     adPositioning.addFixedPosition(1);
     adPositioning.addFixedPosition(3);
     adPositioning.addFixedPosition(7);
    
  3. Use enableRepeatingPositions to instruct adapter insert ads at the specified interval as more items are loaded into your feed

     positioning.enableRepeatingPositions(5);
    

Create a MoPubAdAdapter

The MoPubAdAdapter class places the ads according to the rules set in the MoPub UI and also handles ad caching.

  1. Create an instance of MoPubAdAdapter using the current Context, your existing Adapter subclass, and the MoPubNativeAdPositioning object you created in the previous step.

     mAdAdapter = new MoPubAdAdapter(this, adapter, adPositioning);
    
  2. Register the ad renderer (created from your ViewBinder in step 1) so that the adapter renders your ads according to the layout you created:

     mAdAdapter.registerAdRenderer(adRenderer);
    
  3. Set your old view’s adapter to be the new MoPubAdAdapter instance:

     myListView.setAdapter(mAdAdapter);
    

Begin Loading Ads

  1. The MoPubAdAdapter is now ready to begin loading ads according to your specifications. To improve the relevance of the ads that get shown in your app, you can choose to pass up location or additional keyword data (see the data passing guide). You can also specify exactly which assets you want, to help conserve bandwidth, like so:

     final EnumSet<NativeAdAsset> desiredAssets = EnumSet.of(
                           NativeAdAsset.TITLE,
                           NativeAdAsset.TEXT,
                           // Don't pull the ICON_IMAGE
                           // NativeAdAsset.ICON_IMAGE,
                           NativeAdAsset.MAIN_IMAGE,
                           NativeAdAsset.CALL_TO_ACTION_TEXT);
    
  2. Create a new RequestParameters object using the Builder:

     mRequestParameters = new RequestParameters.Builder()
                         .location(location)
                         .keywords(keywords)
                         .desiredAssets(desiredAssets)
                         .build();
    
  3. You’re now ready to load ads, using the request parameters and the ad unit ID you created on the MoPub dashboard:

     mAdAdapter.loadAds(AD_UNIT_ID, mRequestParameters);
    

    To test your implementation, you can also use the test ad unit ID: here. It will always return a static MoPub native creative.

    To force loading all-new ads into the stream you can call:

     MoPubAdAdapter.refreshAds();
    

Destroy the MoPubAdAdapter

The MoPubAdAdapter must be destroyed when its hosting Activity is destroyed. You should destroy the adapter in the life-cycle method that is the opposite of the method used to create the adapter. If you created the adapter in Activity.onCreate(), you should destroy it in Activity.onDestroy(). If you created the adapter in Activity.onResume(), you should destroy it in Activity.onPause().

@Override
protected void onDestroy() {
    mAdAdapter.destroy();
    super.onDestroy();
}

Ad Placer (via MoPubRecyclerAdapter)

The MoPub SDK includes a RecyclerView.Adapter class called MoPubRecyclerAdapter. Using this class, you can insert ads automatically into a RecyclerView much as you do with a ListView or GridView using MoPubAdAdapter.

The SDK will handle automatically requesting new ads when needed, inserting them into the stream of content, and handling impression tracking and clicks. You can add and remove content from the RecyclerView.

Create a MoPubRecyclerAdapter

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState)
    // Set up your own recycler adapter
    // Set up your RecyclerView

    // Pass the recycler Adapter your original adapter.
    MoPubRecyclerAdapter myMoPubAdapter = new MoPubRecyclerAdapter(context, YOUR_OWN_ADAPTER);
    // Create an ad renderer and view binder that describe your native ad layout.
    ViewBinder myViewBinder = new ViewBinder.Builder(R.layout.my_ad_layout)
            .titleId(R.id.my_ad_title)
            .textId(R.id.my_ad_text)
            .mainImageId(R.id.my_ad_image)
            .iconImageId(R.id.my_ad_icon)
            .callToActionId(R.id.my_call_to_action)
            .privacyInformationIconImageId(R.id.my_ad_privacy_information_icon)
            .build());

    MoPubStaticNativeAdRenderer myRenderer = new MoPubStaticNativeAdRenderer(myViewBinder);

    myMoPubAdapter.registerAdRenderer(myRenderer);

    // Set up the RecyclerView and start loading ads
    recyclerView.setAdapter(myMoPubAdapter);
    myMoPubAdapter.loadAds("YOUR_AD_UNIT_ID");
}

@Override
public void onDestroy() {
    myMoPubAdapter.destroy();
    super.onDestroy();
}

If you register any data observers on your original adapter, you should instead register them on the MoPubRecyclerAdapter so they will receive messages with the adjusted position of content items. If you do not do this, the positions you receive for insertion and removal messages may be inaccurate. Be sure to check isAd(position) and use MoPubRecyclerAdapter.getOriginalPosition() if you need the position of the item in your local adapter.

Manipulating RecyclerView.Adapter Content

Keeping Ads in the Same Relative Position

When adding or removing content items from your RecyclerView.Adapter, the MoPub SDK will automatically handle displaying and hiding ads as the length of the content stream changes. When adding or removing from the end, ads may appear or be hidden. When removing or inserting ads at the beginning or middle of the stream, the SDK will also adjust the ads so they remain in the same position relative to the content in the stream.

All content manipulation happens through an AdapterDataObserver that the MoPub SDK registers on your original adapter. When adding or deleting items from your stream, you should call

notifyItemInserted(position);
notifyItemRemoved(position);
notifyItemsInserted(position, count);
notifyItemsRemoved(position, count);

from your adapter. You must do this so that the RecyclerView is notified to schedule a layout.

If you instead call notifyDataSetChanged when changing your content, the position of ads will not be adjusted along with your content. This is not recommended.

Keeping Ads in the Same Absolute Position

If you want MoPub to keep its ads in the same absolute position when inserting or deleting items, simply call notifyDataSetChanged() from your adapter instead of notifyItemsInserted or notifyItemsRemoved.

Advanced: ContentChangeStrategy

If you require more fine-grained control of insertion & deletion behavior with a MoPubRecyclerAdapter, you can set the ContentChangeStrategy on the adapter. The default strategy, INSERT_AT_END, behaves as described in Manipulating RecyclerView.Adapter Content.

To always keep ads in the same position, you can set the strategy to KEEP_ADS_FIXED. To always move ad positions when content is added or deleted, set the strategy to MOVE_ADS_WITH_CONTENT. You can change the strategy at any time if you require more complex ad position manipulation.

void insertOneRowAtTheEndOnTap() {
  myAdapter.setContentChangeStrategy(KEEP_ADS_FIXED);

  View actionView = // Create the view.

  // Implement addItemAtEnd to call notifyItemInserted()
  myOriginalAdapter.addItemAtEnd(actionView);

  // When other content is added at the end, ads can be inserted.
  myAdapter.setContentChangeStrategy(INSERT_AT_END);
}

Manual Integration

Request the Native Ad

  1. Create a MoPubNative instance, which will be used to register ad listeners, and ad renderers, and to make ad requests. To instantiate your MoPubNative instance, specify a Context object, an ad unit ID of type String, and a MoPubNativeNetworkListener object that will be used to listen to ad load successes/failures.

     moPubNativeNetworkListener = new MoPubNative.MoPubNativeNetworkListener() {
         // We will be populating this below
     }
    
     moPubNative = new MoPubNative(this, "11a17b188668469fb0412708c3d16813 ", moPubNativeNetworkListener);
    

    To test your implementation, you can also use the test ad unit ID: here. It will always return a static MoPub native creative.

  2. Create an XML layout, specifying how ad assets should be organized. As an example, this layout contains a standard hierarchy of our ad assets. It will be used when we create our ViewBinder in the next step.

  3. Create a ViewBinder object to bind our layout XML and the ad’s assets. We will use the XML layout referenced in step 2. If you use mediation, specific ad networks might require new ViewBinder bindings for additional assets. Make sure to check the Integrating Third Party Ad Networks page for more implementation information.

     ViewBinder viewBinder = new ViewBinder.Builder(R.layout.native_ad_list_item)
        .mainImageId(R.id.native_main_image)
        .iconImageId(R.id.native_icon_image)
        .titleId(R.id.native_title)
        .textId(R.id.native_text)
        .privacyInformationIconImageId(R.id.native_privacy_information_icon_image)
        .build();
    

    (Optional) For direct-sold native ads, additional views for text or images may be included in the ViewBinder. Extra fields may be added like so:

    ViewBinder.Builder().addExtras(Map<String, Integer> resIds) or ViewBinder.Builder().addExtra(String key, int resId)

    For example, given the below JSON that contains the following ad assets, the ViewBinder can be expanded to use either addExtras() or addExtra() to append the additional asset. Note: If you are adding an image to extras, the key must end with “image”.

     {
         "mainimage" : "http://www.mopub.com/mainimage.jpg",
         "iconimage" : "http://www.mopub.com/iconimage.jpg",
         "title" : "Sample Native Ad",
         "text" : "Sample Text",
         "sponsoredtext" : "Sponsored",
         "sponsoredimage" : "http://www.mopub.com/sponsored.jpg"
     }
    
     ViewBinder viewBinder = new ViewBinder.Builder(R.layout.native_ad_layout)
         .mainImageId(R.id.native_ad_main_image)
         .iconImageId(R.id.native_ad_icon_image)
         .titleId(R.id.native_ad_title)
         .textId(R.id.native_ad_text)
         .addExtra("sponsoredtext", R.id.sponsored_text)
         .addExtra("sponsoredimage", R.id.sponsored_image)
         .build();
    
  4. Create a MoPubStaticNativeAdRenderer with the ViewBinder just created as the argument, and register it with the MoPubNative instance. The MoPubStaticNativeAdRenderer will be used to construct and render the ad view.

     MoPubStaticNativeAdRenderer moPubStaticNativeAdRenderer = new MoPubStaticNativeAdRenderer(viewBinder);
     moPubNative.registerAdRenderer(moPubStaticNativeAdRenderer);
    
  5. (Optional) To improve the relevance of ads that get shown in your app, you can choose to pass location and/or additional keyword data with the ad request. You can also specify exactly which assets you want.

     EnumSet<RequestParameters.NativeAdAsset> desiredAssets = EnumSet.of(
                RequestParameters.NativeAdAsset.TITLE,
                RequestParameters.NativeAdAsset.TEXT,
                RequestParameters.NativeAdAsset.CALL_TO_ACTION_TEXT,
                RequestParameters.NativeAdAsset.MAIN_IMAGE,
                RequestParameters.NativeAdAsset.ICON_IMAGE,
                RequestParameters.NativeAdAsset.STAR_RATING
        );
    

    Then, create a new RequestParameters object using the Builder():

     RequestParameters mRequestParameters = new RequestParameters.Builder()
         .location(exampleLocation)
         .keywords(exampleKeywords)
         .desiredAssets(desiredAssets)
         .build();
    
  6. Call MoPubNative.makeRequest() to request an ad from the server and download associated images asynchronously.

     moPubNative.makeRequest();
    

    (Optional) You may pass in the above RequestParameters object referenced in step 5 for additional targeting.

     moPubNative.makeRequest(mRequestParameters);
    
  7. Upon success, the MoPubNativeNetworkListener.onNativeLoad() method will be called with an instance of NativeAd. Upon failure, the MoPubNativeNetworkListener.onNativeFail() method will be called with a corresponding error code object.

     moPubNativeNetworkListener = new MoPubNative.MoPubNativeNetworkListener() {
             @Override
             public void onNativeLoad(final NativeAd nativeAd) {
                 Log.d("MoPub", "Native ad has loaded.");
             }
             @Override
             public void onNativeFail(NativeErrorCode errorCode) {
                 Log.d("MoPub", "Native ad failed to load with error: " + errorCode.toString());
             }
         };
    

    (Optional) To receive callbacks for impression and click tracking, in the onNativeLoad() callback, register the MoPubNativeEventListener (nativeAd.setMoPubNativeEventListener(moPubNativeEventListener);), and override onImpression() and onClick(), like so:

          moPubNativeEventListener = new NativeAd.MoPubNativeEventListener() {
             @Override
             public void onImpression(View view) {
                 Log.d("MoPub", "Native ad recorded an impression.");
                 // Impress is recorded - do what is needed AFTER the ad is visibly shown here.
             }
    
             @Override
             public void onClick(View view) {
                 Log.d("MoPub", "Native ad recorded a click.");
                 // Click tracking.
             }
         };
    

Rendering the Native Ad

  1. Create an instance of AdapterHelper. You can pass in any integers as arguments for the interval:

     adapterHelper = new AdapterHelper(this, 0, 3); // When standalone, any range will be fine.
    

    In spite of the @Deprecated annotation on this class, it is still required to use AdapterHelper to retrieve a pre-populated view containing the rendered ad content and tracking events while applying Manual integration type even for a single-view ad slot. You might encounter impression or click tracking issue without properly using AdapterHelper.

  2. In your onNativeLoad callback, call AdapterHelper.getAdView() with the following parameters to get a fully populated View containing the rendered ad content. The View returned by AdapterHelper.getAdView() has a click listener attached to it, and will automatically handle opening the ad’s destination URL. It will also track impressions and clicks automatically.

     /**
      * @convertView   View    An old view to reuse, if possible, as per Adapter.getView(). If null, a new View will be inflated from XML.
      * @parent        ViewGroup   The optional parent view, which provides the correct subclass of LayoutParams for the root view’s XML.
      * @nativeAd      NativeAd    The native ad returned by the MoPub SDK. This should have been previously obtained from MoPubNativeListener.onNativeLoad(). If this is null or destroyed, the view returned will have its visibility set to View.GONE.
      * @viewBinder    ViewBinder  It's just a placeholder that is never used in this method. Should just pass in any non-null ViewBinder as below.
      */
     @NonNull
     public View getAdView(@Nullable final View convertView,
             @Nullable final ViewGroup parent,
             @Nullable final NativeAd nativeAd,
             @Nullable final ViewBinder viewBinder) {
     }
    
     // Retrieve the pre-built ad view that AdapterHelper prepared for us.
     View v = adapterHelper.getAdView(null, nativeAdView, nativeAd, new ViewBinder.Builder(0).build());
     // Set the native event listeners (onImpression, and onClick).
     nativeAd.setMoPubNativeEventListener(moPubNativeEventListener);
     // Add the ad view to our view hierarchy
     parentView.addView(v);
    

Advanced: Inserting the Native Ad into BaseAdapter Subclasses

AdapterHelper contains a few convenience methods for including native ads in a feed.

  1. Create an instance of AdapterHelper, passing in a Context, along with int start (the position of the first ad in the feed) and int interval (the frequency with which ads are shown in the feed).

    Note: It is required to override certain Adapter methods as the inclusion of Native Ads will modify the position, number, and type of elements in the corresponding feed.

  2. Update the adapter’s getCount() to account for the addition of ads in the feed.

    Example (subclassing ArrayAdapter):

     mAdapterHelper = new AdapterHelper(context, start, interval);
    
     @Override
     public int getCount() {
         int originalCount = super.getCount();
         return mAdapterHelper.shiftedCount(originalCount);
    
  3. Increment the adapter’s getViewTypeCount() method, indicating that an additional view type has been added to the adapter.

    Example (subclassing ArrayAdapter):

     int originalViewTypeCount = 2; // number of unique view types in the feed
    
     @Override
     public int getViewTypeCount() {
         // Add 1 for native ad view type
         return originalViewTypeCount + 1;
    
  4. Update the adapter’s getItem() method to account for the fact that ads are being placed in the feed.

    Example (subclassing ArrayAdapter):

     mAdapterHelper = new AdapterHelper(context, start, interval);
    
     @Override
     public T getItem(int position) {
         // Shifted position returns the original position of the content
         // in ArrayAdapter's backing array
         int shiftedPosition = mAdapterHelper.shiftedPosition(position);
         return super.getItem(shiftedPosition);
     }
    
  5. Update the adapter’s getItemViewType() method to specify the positions in the feed associated with native ads.

    Example (subclassing ArrayAdapter):

     mAdapterHelper = new AdapterHelper(context, start, interval);
    
     private static final int EXISTING_ROW_TYPE_0 = 0;
     private static final int EXISTING_ROW_TYPE_1 = 1;
     private static final int MOPUB_NATIVE_ROW_TYPE = 2;
    
     @Override
     public int getItemViewType(int position) {
         if (mAdapterHelper.isAdPosition(position) {
            return MOPUB_NATIVE_ROW_TYPE;
         } else {
            int shiftedPosition = mAdapterHelper.shiftedPosition(position);
            // Previous getItemViewType() logic, using shiftedPosition as the new index
         }
     }
    
  6. Update getView() to return a native ad for the appropriate feed positions.

    Example (subclassing ArrayAdapter):

     mAdapterHelper = new AdapterHelper(context, start, interval);
    
     @Override
     View getView(int position, View convertView, ViewGroup parent) {
         if (mAdapterHelper.isAdPosition(position)) {
            return new AdapterHelper.getAdView(
              convertView,
              parent,
              nativeAd,
              viewBinder,
              moPubNativeListener
            );
         } else {
            // Previous getView() logic
         }
     }
    

Important Notes

Avoid Excessive Ad Requests

Making requests for ads which are never displayed to the user will consume unnecessary resources and may negatively impact your revenue. Therefore, your application should make an effort to request ads only when they are likely to be displayed. In particular, avoid caching large quantities of ads for long periods of time.

For example, when a user initially navigates to a ListView with many rows, you should avoid requesting ads that will be displayed near the bottom of the ListView (i.e. far below the fold). Instead, wait for the user to begin scrolling through the feed before making additional ad requests.

Last updated October 10, 2018

TWITTER, MOPUB, and the Bird logo are trademarks of Twitter, Inc. or its affiliates. All third party logos and trademarks included are the property of their respective owners.

© 2018 MoPub Inc.