Native Ads (Integrate Using AdPlacer)

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.

Integrate Native Ads Using Ad Placer

This option automatically wraps the TableView and CollectionView data source and delegate, and allows you to control the location of the ad from the MoPub interface.

The high-level steps to integrate using the Ad Placer are:

  1. Set up your native ad layout.
  2. Place and load ads in your feed, which you can do in one of two ways:
  3. Define ad positions, which you can do in one of two ways:
  4. Pass in AdPlacer initialization.
  5. Optionally receive delegate callbacks.

Important: Please do not use publisher-provided overlays (such as close buttons) that are located with the ad placement and that subsequently cover the ad creative. Doing so is against MoPub Policy. If you have questions, please reach out to your account team or support@mopub.com for additional assistance.

Step 1. Set Up Your Native Ad Layout

Set up your native ad layout with the following particulars:

  • Each native ad format is rendered onto a view by a renderer that conforms to the MPNativeAdRenderer protocol. Renderers can be customized through their associated settings objects that conform to the MPNativeAdRendererSettings protocol.

  • You must implement and provide a viewSizeHandler block to your renderer settings object in order to ensure that your views are sized correctly.

  • Renderers and their settings are tied together in the MPNativeAdRendererConfiguration object, which is used when initializing your ad placer objects.

  • Most renderers require you to supply a UIView subclass that adopts the MPNativeAdRenderingProtocol protocol to the renderer’s settings object.

  • You can display advertising content in any new or existing UIView subclass that implements the MPNativeAdRendering protocol. The protocol allows you to specify what elements of your UI should be used for each native ad element.

  • The native ad renderer associated with your ad asks your view for a UI element via protocol methods for each native ad element. Typically, a native ad has a base set of assets (as configured on the MoPub website):

    • title
    • main text
    • call-to-action text
    • sponsored text (new starting with MoPub SDK v5.11+)
    • icon image URL
    • main image URL
    • privacy information icon
  • The MoPub SDK automatically handles tap events on the privacy information icon. You are required to display a privacy information icon in your view.

Sample code:

// YourNativeAdView.h

@interface YourNativeAdView : UIView <MPNativeAdRendering>

@property (strong, nonatomic) UILabel *titleLabel;
@property (strong, nonatomic) UILabel *mainTextLabel;
@property (strong, nonatomic) UILabel *callToActionLabel;
@property (strong, nonatomic) UILabel *sponsoredByLabel;
@property (strong, nonatomic) UIImageView *iconImageView;
@property (strong, nonatomic) UIImageView *mainImageView;
@property (strong, nonatomic) UIImageView *privacyInformationIconImageView;

@end

// YourNativeAdView.m

@implementation YourNativeAdView



- (void)layoutSubviews
{
    [super layoutSubviews];
    // layout your views
}

- (UILabel *)nativeMainTextLabel
{
    return self.mainTextLabel;
}

- (UILabel *)nativeTitleTextLabel
{
    return self.titleLabel;
}

- (UILabel *)nativeCallToActionTextLabel
{
    return self.callToActionLabel;
}

- (UILabel *)nativeSponsoredByCompanyTextLabel
{
    return self.sponsoredByLabel;
}

- (UIImageView *)nativeIconImageView
{
    return self.iconImageView;
}

- (UIImageView *)nativeMainImageView
{
    return self.mainImageView;
}

- (UIImageView *)nativePrivacyInformationIconImageView
{
    return self.privacyInformationIconImageView;
}

@end

Optionally Render Custom Assets for Direct Serve Ads

When creating a Direct Serve ad creative on the MoPub website, you can add custom assets to supplement the pre-defined ones described above. The SDK calls layoutCustomAssetsWithProperties:imageLoader: on your view, which implements MPNativeAdRendering, giving you an opportunity to display custom assets within your view.

The following example demonstrates how to access custom text that you have provided:

- (void)layoutCustomAssetsWithProperties:(NSDictionary *)customProperties imageLoader:(MPNativeAdRenderingImageLoader *)imageLoader
{
    self.customTextLabel.text = customProperties[@"customText"];

    // To load custom images, you can use the imageLoader's convenience method -loadImageForURL:intoImageView:.
    [imageLoader loadImageForURL:[NSURL URLWithString:customProperties[@"customImage"]] intoImageView:self.customImageView];
}

Optionally Localize Sponsored Text

By default, the SDK returns “Sponsored by [Advertiser]” in the sponsored text, a concatination of ‘Sponsored by’ and the advertiser name. If the advertiser data is not available, the label returns an empty string and the label is set to hidden.

The SDK provides an optional localization alternative for publishers who want a more customized experience, or translation across multiple languages:

+ (NSString *)localizedSponsoredByTextWithSponsorName:(NSString *)sponsorName;

Step 2. Place and Load Ads in Your Feed

There are two ways to place and load ads in your feed:

Option A. Place and Load Ads Using UITableView

The MoPub SDK provides a helper class, MPTableViewAdPlacer, that handles requesting ads from MoPub and inserting them into your existing UITableView subclass. When an instance of MPTableViewAdPlacer is initialized with a table view, it wraps the table view’s data source and delegate in order to insert ads and adjust the positions of your regular content cells.

In your UITableView feed UIViewController’s viewDidLoad:

  1. Create and configure an MPStaticNativeAdRendererSettings object with a viewSizeHandler implementation and a rendering view class that adheres to the MPNativeAdRendering protocol:

     MPStaticNativeAdRendererSettings *settings = [[MPStaticNativeAdRendererSettings alloc] init];
    
     settings.renderingViewClass = [YourNativeAdView class]; settings.viewSizeHandler = ^(CGFloat maxWidth) { return CGSizeMake(maxWidth, 312.0f); };
    
  2. Call rendererConfigurationWithRendererSettings: on the renderer you are using with your settings to create an MPNativeAdRendererConfiguration object.

     MPNativeAdRendererConfiguration *config = [MPStaticNativeAdRenderer rendererConfigurationWithRendererSettings:settings];
    
  3. Set up your preferred ad positioning in the MoPub UI in the ad unit settings page. The ad placer will automatically use the positioning it receives from those settings. If you wish to set up ad positioning through code in your app, follow the steps outlined in the Ad Placer instructions.

  4. Instantiate your MPTableViewAdPlacer with your UITableView instance and an array containing you renderer configuration. Make sure to set your view controller as the ad placer’s delegate:

     self.placer = [MPTableViewAdPlacer placerWithTableView:self.tableView viewController:self rendererConfigurations:@[config]];
     self.placer.delegate = self;
    

    self.tableView is the UITableView that contains your feed.

  5. Add targeting parameters to provide more information about your ad to the advertiser, and conserve bandwidth by getting only the right assets:

     MPNativeAdRequestTargeting *targeting = [MPNativeAdRequestTargeting targeting];
     targeting.desiredAssets = [NSSet setWithObjects:kAdIconImageKey, kAdMainImageKey, kAdCTATextKey, kAdTextKey, kAdTitleKey, nil];
    

    Refer to our Data Passing article for more details on passing information such as location.

  6. Instruct your MPTableViewAdPlacer instance to begin loading ads and placing them into your feed, using the ad unit ID you created in the MoPub dashboard.

     [self.placer loadAdsForAdUnitID:@"YOUR_ADUNIT_ID" targeting:targeting];
    

    Note: To test your implementation, you can also use this test ad unit ID. It always returns a static MoPub native creative.

  7. Replace UITableView Method Calls Replace calls to the following UITableView methods with the MoPub SDK category equivalents.

    Instead of:

     [self.tableView selectRowAtIndexPath:myIndexPath];
    

    Use:

     [self.tableView mp_selectRowAtIndexPath:myIndexPath];
    

    These methods work just like the regular UITableView methods, except that they make adjustments to the NSIndexPath parameters to handle the fact that your stream has extra ad rows.

    Important: The following replacements are mandatory. If you skip this step, your content row positions will be out of sync with your table view, causing problems.

    Original Replacement
    setDelegate: mp_setDelegate:
    delegate mp_delegate
    setDataSource: mp_setDataSource:
    dataSource mp_dataSource
    reloadData mp_reloadData
    rectForRowAtIndexPath: mp_rectForRowAtIndexPath:
    indexPathForRowAtPoint: mp_indexPathForRowAtPoint:
    indexPathForCell: mp_indexPathForCell:
    indexPathsForRowsInRect: mp_indexPathsForRowsInRect:
    cellForRowAtIndexPath: mp_cellForRowAtIndexPath:
    visibleCells mp_visibleCells
    indexPathsForVisibleRows: mp_indexPathsForVisibleRows:
    scrollToRowAtIndexPath:atScrollPosition:animated: mp_scrollToRowAtIndexPath:atScrollPositions:animated:
    beginUpdates mp_beginUpdates
    endUpdates mp_endUpdates
    insertSections:withRowAnimation: mp_insertSections:withRowAnimation:
    deleteSections:withRowAnimation: mp_deleteSections:withRowAnimation:
    reloadSections:withRowAnimation: mp_reloadSections:withRowAnimation:
    moveSection:toSection: mp_moveSection:toSection:
    insertRowsAtIndexPaths:withRowAnimation: mp_insertRowsAtIndexPaths:withRowAnimation:
    deleteRowsAtIndexPaths:withRowAnimation: mp_deleteRowsAtIndexPaths:withRowAnimation:
    reloadRowsAtIndexPaths:withRowAnimation: mp_reloadRowsAtIndexPaths:withRowAnimation:
    moveRowAtIndexPath:toIndexPath: mp_moveRowAtIndexPath:toIndexPath:
    indexPathForSelectedRow: mp_indexPathForSelectedRow:
    indexPathsForSelectedRows: mp_indexPathsForSelectedRows:
    selectRowAtIndexPath:animated:scrollPosition: mp_selectRowAtIndexPath:animated:scrollPosition:
    deselectRowAtIndexPath:animated: mp_deselectRowAtIndexPath:animated:
    dequeueReusableCellWithIdentifier:forIndexPath: mp_dequeueReusableCellWithIdentifier:forIndexPath:

Example Code:

- (void)viewDidLoad
{
    [super viewDidLoad];

    [self startLoadingFeed];

    MPStaticNativeAdRendererSettings *settings = [[MPStaticNativeAdRendererSettings alloc] init];
    settings.renderingViewClass = [YourNativeAdView class];
    settings.viewSizeHandler = ^(CGFloat maximumWidth) {
        return CGSizeMake(maximumWidth, 312.0f);
    };

    MPNativeAdRendererConfiguration *config = [MPStaticNativeAdRenderer rendererConfigurationWithRendererSettings:settings];

    self.placer = [MPTableViewAdPlacer placerWithTableView:self.tableView
                                            viewController:self
                                   rendererConfigurations:@[config]];
    self.placer.delegate = self;
    [self.placer loadAdsForAdUnitID:@"YOUR_ADUNIT_ID"];
}

This will ensure that the ads appear based on the settings in your ad unit settings page.

Option B. Place and Load Ads Using UICollectionView

The MoPub SDK provides a helper class, MPCollectionViewAdPlacer, that handles requesting ads from MoPub and inserting them into your existing UICollectionView subclass.

When an instance of MPCollectionViewAdPlacer is initialized with a collection view, it wraps the collection view’s data source and delegate in order to insert ads and adjust the positions of your regular content cells.

In your UICollectionView feed’s UIViewController’s viewDidLoad:

  1. Create and configure an MPStaticNativeAdRendererSettings object with viewSizeHandler implementation and a rendering view class that adheres to the MPNativeAdRendering protocol.

     MPStaticNativeAdRendererSettings *settings = [[MPStaticNativeAdRendererSettings alloc] init];
    
     settings.renderingViewClass = [YourNativeAdView class]; settings.viewSizeHandler = ^(CGFloat maxWidth) { return CGSizeMake(70.0f, 113.0f); };
    
  2. Call rendererConfigurationWithRendererSettings: on the renderer you are using with your settings to create an MPNativeAdRendererConfiguration object.

     MPNativeAdRendererConfiguration *config = [MPStaticNativeAdRenderer rendererConfigurationWithRendererSettings:settings];
    
  3. Set up your preferred ad positioning in the MoPub UI in the ad unit settings page. The ad placer will automatically use the positioning it receives from those settings. If you wish to set up ad positioning through code in your app, follow the steps outlined in the Ad Placer instructions.

  4. Instantiate your MPCollectionViewAdPlacer with your UICollectionView subclass and your MPServerAdPositioning object. Make sure to set your view controller as the ad placer’s delegate.

     self.placer = [MPCollectionViewAdPlacer placerWithCollectionView:self.collectionView viewController:self rendererConfigurations:@[config]];
     self.placer.delegate = self;
    

    self.collectionView is the UICollectionView that contains your feed.

  5. Add targeting parameters to provide more information about your ad to the advertiser, and conserve bandwidth by getting only the right assets.

     MPNativeAdRequestTargeting *targeting = [MPNativeAdRequestTargeting targeting];
     targeting.desiredAssets = [NSSet setWithObjects:kAdIconImageKey, kAdMainImageKey, kAdCTATextKey, kAdTextKey, kAdTitleKey, nil];
    

    Refer to our Data Passing article for more details on passing information such as location.

  6. Instruct your MPCollectionViewAdPlacer instance to begin loading ads and placing them into your feed, using the ad unit ID you got from the MoPub dashboard.

     [self.placer loadAdsForAdUnitID:@"YOUR_ADUNIT_ID" targeting:targeting];
    

    Note: To test your implementation, you can also use this test ad unit ID. It always returns a static MoPub native creative.

  7. Replace UICollectionView Method Calls:

    Replace calls to the following UICollectionView methods with the MoPub SDK category equivalents.

    Instead of:

     [self.collectionView selectItemAtIndexPath:myIndexPath];
    

    Use:

     [self.collectionView mp_selectItemAtIndexPath:myIndexPath];
    

    These methods work just like the regular UICollectionView methods, except that they make adjustments to the NSIndexPath parameters to handle the fact that your stream has extra ad items.

    Important: The following replacements are mandatory. If you skip this step, your content item positions will be out of sync with your collection view, causing problems.

    ORIGINAL REPLACEMENT
    setDelegate: mp_setDelegate:
    delegate mp_delegate
    setDataSource: mp_setDataSource:
    dataSource mp_dataSource
    dequeueReusableCellWithReuseIdentifier:forIndexPath: mp_dequeueReusableCellWithReuseIdentifier:forIndexPath:
    indexPathsForSelectedItems mp_indexPathsForSelectedItems
    selectItemAtIndexPath:animated:scrollPosition: mp_selectItemAtIndexPath:animated:scrollPosition:
    deselectItemAtIndexPath:animated: mp_deselectItemAtIndexPath:animated:
    reloadData mp_reloadData
    layoutAttributesForItemAtIndexPath: mp_layoutAttributesForItemAtIndexPath:
    indexPathForItemAtPoint: mp_indexPathForItemAtPoint:
    indexPathForCell: mp_indexPathForCell:
    cellForItemAtIndexPath: mp_cellForItemAtIndexPath:
    visibleCells mp_visibleCells
    indexPathsForVisibleItems mp_indexPathsForVisibleItems
    scrollToItemAtIndexPath:atScrollPosition:animated: mp_scrollToItemAtIndexPath:atScrollPosition:animated:
    insertSections: mp_insertSections:
    deleteSections: mp_deleteSections:
    reloadSections: mp_reloadSections:
    moveSection:toSection: mp_moveSection:toSection:
    insertItemsAtIndexPaths: mp_insertItemsAtIndexPaths:
    deleteItemsAtIndexPaths: mp_deleteItemsAtIndexPaths:
    reloadItemsAtIndexPaths: mp_reloadItemsAtIndexPaths:
    moveItemAtIndexPath:toIndexPath: mp_moveItemAtIndexPath:toIndexPath:

Sample code:

- (void)viewDidLoad
{
    [super viewDidLoad];

    [self startLoadingFeed];
    MPStaticNativeAdRendererSettings *settings = [[MPStaticNativeAdRendererSettings alloc] init];
    settings.renderingViewClass = [YourNativeAdView class];
    settings.viewSizeHandler = ^(CGFloat maximumWidth) {
        return CGSizeMake(maximumWidth, 77.0f);
    };

    MPNativeAdRendererConfiguration *config = [MPStaticNativeAdRenderer rendererConfigurationWithRendererSettings:settings];

    self.placer = [MPCollectionViewAdPlacer placerWithCollectionView:self.collectionView
                                                      viewController:self
                                             rendererConfigurations:@[config]];
    self.placer.delegate = self;
    [self.placer loadAdsForAdUnitID:self.adUnitID];
}

This will ensure that the ads appear based on your native ad unit settings.

Step 3. Define Ad Positions

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

  2. After updating your settings in the UI, create a MPServerAdPositioning object. This object informs the MPTableViewAdPlacer about where to place ads within the table view:

     MPServerAdPositioning *positioning = [MPServerAdPositioning positioning];
    

Option B. Client-Side Positioning

  1. Create an MPClientAdPositioning object. This object informs the MPTableViewAdPlacer about where to place ads within the table view.

     MPClientAdPositioning *positioning = [MPClientAdPositioning positioning];
    
  2. If you want ads to appear at certain fixed positions within your feed, use addFixedIndexPath: to specify those NSIndexPaths:

     [positioning addFixedIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]];
    

    The above ensures that an ad appears at row 1 section 0 of your feed.

  3. Use enableRepeatingPositionsWithInterval: to instruct the MPTableViewAdPlacer to insert ads at the specified interval as more items are loaded into your feed:

     [positioning enableRepeatingPositionsWithInterval:5];
    

    The above ensures that an ad appears as every 5th row in your feed. Note that repeating ads will only be inserted after the last fixed-position ad.

Step 4. Pass in AdPlacer Initialization

Initialize your ad placer object with either a server-side or client-side positioning object:

  • For MPTableViewAdPlacer:

      self.placer = [MPTableViewAdPlacer placerWithTableView:self.tableView viewController:self adPositioning:positioning rendererConfigurations:@[config]];
    
  • For MPCollectionViewAdPlacer:

      self.placer = [MPCollectionViewAdPlacer placerWithCollectionView:self.collectionView viewController:self adPositioning:positioning rendererConfigurations:@[config]];
    

Note: Ensure that you are using the provided APIs to automatically track impressions and clicks.

Step 5. Optionally Receive Delegate Callbacks

Both collection view and table view ad placers include optional delegate callbacks that you can use to be notified of events such as when an ad will present a modal, an ad modal dismisses, and when the app will background due to user interaction with an ad.

Best Practices

Hide Blank Ad Views

Avoid displaying ad views in your app that have not yet been configured with assets. In addition, make sure your app adapts gracefully when ad requests fail due to lack of inventory or connectivity issues.

For example, if your application displays ads in a table view, ensure that failed ad requests do not cause unnecessary blank cells or gaps in the table.

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.

Last updated October 06, 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.)