Native Ads

Native ads let you 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:

  1. Create an account on MoPub and integrate the MoPub SDK into your project.
  2. Read our Best Practices article for guidelines about displaying native ads in your app.

Choose an Integration Option

There are three ways to integrate native ads into your app.

The first and second options both involve using the Ad Placer; these options offer the same advantages, but different specifics. The third option is a manual integration.

  • Option 1. Integrate with Ad Placer Using MoPubAdAdapter: This option involves using the MoPubStreamAdPlacer to facilitate loading native ads into an app’s content stream; for example, a scrolling list (refer to our demo). The advantage of using the Ad Placer is that it lets the MoPub SDK request new ads automatically when necessary, insert them into the stream of content, and handle impression tracking and clicks. By default, three native ads are requested and cached initially, and the SDK requests one at a time as the user scrolls through the feed. Each ad’s expiration timer starts once the ad is loaded or cached. After four hours, the SDK marks these ads as ready for cleanup by the OS.

    With Option 1, you insert native ads into a ListView or GridView. This option uses the MoPubStreamAdPlacer class, and a MoPubAdAdapter that wraps your existing adapter subclasses to insert ads into a ListView.

  • Option 2. Integrate with Ad Placer Using MoPubRecyclerAdapter: Like Option 1, this option involves using the MoPubStreamAdPlacer to facilitate loading native ads into an app’s content stream; for example, a scrolling list (refer to our demo). As with Option 1, the advantage of using the Ad Placer is that it lets the MoPub SDK request new ads automatically when necessary, insert them into the stream of content, and handle impression tracking and clicks. By default, three native ads are requested and cached initially, and the SDK requests one at a time as the user scrolls through the feed. Each ad’s expiration timer starts once the ad is loaded or cached. After four hours, the SDK marks these ads as ready for cleanup by the OS.

    With Option 2, you insert native ads into a RecyclerView. This option uses the MoPubStreamAdPlacer class, and a MoPubRecyclerAdapter that wraps your existing adapter subclasses to insert ads into a RecyclerView.

  • Option 3. Integrate Manually: Choose this option when the native ad placement is either a single view (refer to our demo), or is in a content stream where using the AdPlacer approach cannot meet specific flexibility needs.

    With Option 3, you use the MoPubNative class to request and load ads. The MoPub SDK provides an AdapterHelper to retrieve a pre-populated view containing the rendered ad content and required tracking events. AdapterHelper enables you to easily add the ad view into your parent view. However, you, the publisher, must manually handle ad requests, ad expiration, and cases when there are no fills.

Option 1. Integrate Native Ads Using Ad Placer and MoPubAdAdapter

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

Option 1 consists of these high-level 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.
  4. Begin loading ads.
  5. Destroy the MoPubAdAdapter.

Step 1. 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 (refer to this demo). Choose the assets from the ad that will make it fit 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 10 dp padding on all sides (so the icon display area is only 20 dp x 20 dp, but the click area is a little 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" />
         <TextView
             android:id="@+id/native_sponsored_text_view" />
       </RelativeLayout>
      
    • Important: Do not set the background property on your ImageViews to null in order to handle PNG transparency gracefully, as shown here:

         <ImageView
             android:background="@null" />
      
    • Starting with the Facebook Audience Network SDK v4.99.0, if you are mediating Facebook native ads in place of the above ImageViews, you must register Facebook’s own layouts, as shown:

       <!-- 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)
         .sponsoredTextId(R.id.native_sponsored_text_view)
         .build();
    
    • If you display direct-sold native ads, you may have additional subviews for text or images available. Add extra fields using:

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

      or

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

      For example, suppose 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();
      
    • If you add an image to extras, the key must end with ‘image’.

    • Starting with MoPub SDK v5.11+, the Advertiser name is available in the sponsored text field. We recommend using “Sponsored by” or localized versions when this string is returned. Example:

      <string name="com_mopub_nativeads_sponsored_by">Sponsored by %s</string>
      
  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);
    

Step 2. Place Ads in Your Feed

Next, you must define where in your feed you want ads to appear, using the MoPubNativeAdPositioning class to balance ads with your content. We provide server-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

Use server-side positioning 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 row in the feed). After position 7, your ads will appear every 5 positions.

Server-Side Positioning

  1. After updating your settings in the UI, set up the MoPubNativeAdPositioning.MoPubServerPositioning object:

     MoPubNativeAdPositioning.MoPubServerPositioning adPositioning =
           MoPubNativeAdPositioning.serverPositioning();
    

Option B. Client-Side Positioning

The SDK does support setting positioning directly in the method. In this case, the position setting on the ad unit screen of the Publisher UI is 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);
    

Step 3. 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);
    

Step 4. Begin Loading Ads

  1. The MoPubAdAdapter is now ready to begin loading ads according to your specifications. To improve the relevance of the ads shown in your app, you can choose to pass location or additional keyword data (refer to our data passing article). 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) // Note that, starting in v5.9.0 of the MoPub SDK, GPS location is prioritized over location data you supply from the app (i.e. when both are available, the MoPub SDK will utilize GPS 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);
    

    Note: 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();
    

Step 5. Destroy the MoPubAdAdapter

The MoPubAdAdapter must be destroyed when its hosting Activity is destroyed. 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(), destroy it in Activity.onDestroy(). If you created the adapter in Activity.onResume(), destroy it in Activity.onPause().

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

Sample Code

Ad Placer using MoPubAdAdapter

Option 2. Integrate Native Ads Using Ad Placer and MoPubRecyclerAdapter

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

The SDK automatically requests new ads when needed, inserts them into the stream of content, and handles impression tracking and clicks. You can add and remove content from the RecyclerView.

Creating 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, instead register them on the MoPubRecyclerAdapter so that they 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

Manipulating RecyclerView.Adapter content explains ad positioning, including:

Keeping Ads in the Same Relative Position

When adding or removing content items from your RecyclerView.Adapter, the MoPub SDK automatically displays and hides 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 also adjusts the ads so that 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, call these methods from your adapter:

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

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

If you instead call notifyDataSetChanged when changing your content, the ads’ position is not adjusted along with your content. We do not recommend this.

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: Setting the ContentChangeStrategy

If you require more fine-grained control of insertion and 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);
}

Sample Code

Ad Placer using MoPubRecyclerAdapter

Option 3. Integrate Native Ads Manually Using MoPubNative

The manual integration involves two high-level steps:

  1. Request the native ad.
  2. Render the native ad.

We also provide some convenient helper methods.

Step 1. Request the Native Ad

  1. Create a MoPubNative instance, which is 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);
    

    Note: To test your implementation, you can also use the test ad unit ID: [here][13]. 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 may require new ViewBinder bindings for additional assets. Make sure to check our Integrating Third-Party Ad Networks article 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();
    
    • For Direct Serve native ads, you can include additional views for text or images in the ViewBinder. This is optional. You can add extra fields this way:

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

    • For example, given the JSON below that contains the following ad assets, you can expand the ViewBinder to use either addExtras() or addExtra() to append the additional asset. Note that 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 expanded to use addExtra():

      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. To improve the relevance of ads shown in your app, you can pass location and/or additional keyword data with the ad request. This is optional. 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();
    

    You can pass in the above RequestParameters object referenced in step 5 for additional targeting:

     moPubNative.makeRequest(mRequestParameters);
    
  7. Upon success, the MoPubNativeNetworkListener.onNativeLoad() method is called with an instance of NativeAd. Upon failure, the MoPubNativeNetworkListener.onNativeFail() method is 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());
             }
         };
    

    To receive callbacks for impression and click tracking, in the onNativeLoad() callback, you can 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.
             }
         };
    

Step 2. Render 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.
    

    Note: You must use this class even though it is annotated as @Deprecated. Use it when you use AdapterHelper to retrieve a pre-populated view containing the rendered ad content and tracking events. You will need this when applying the manual integration type even for a single-view ad slot. Improper use of AdapterHelper can result in impression or click tracking issues.

  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: You must override certain Adapter methods because including 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.

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

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

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

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

    For 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
         }
     }
    

Best Practice: Avoid Excessive Ad Requests

Making requests for ads that are never displayed to the user consumes unnecessary resources and may negatively impact your revenue. Therefore, try 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, avoid requesting ads that will be displayed near the bottom of the ListView (that is, far below the fold). Instead, wait for the user to begin scrolling through the feed before making additional ad requests.

Last updated March 20, 2020

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.

© 2020 MoPub (a division of Twitter, Inc.)