Adding the Native Ad API in iOS

The Native Ad API allows you to build a customized experience for the ads you show in your app. When using the Native Ad API, instead of receiving an ad ready to be displayed, you will receive a group of ad properties such as a title, an image, a call to action, and you will have to use them to construct a custom UIView where the ad is shown.

Please consult our guidelines for native ads when designing native ads in your app.

Let's implement the following native ad placement. You will create the following views to our native ad.

View #1: advertiser icon

View #2: ad title

View #3: sponsored label

View #4: advertiser choice

View #5: ad media view

View #6: social context

View #7: ad body

View #8: ad call to action button


Step 1: Create Native Ad Views in Storyboard

Step 2: Load and Show Native Ad

Step 3: How to Get Aspect Ratio of the Content and Apply Natural Width and Height

Step 4: Verify Impression and Click Logging

Step 5: How to Debug When Ad Not Shown

Step 1: Create Native Ad Views in Storyboard

Ensure you have completed the Audience Network Getting Started and iOS Getting Started guides before you proceed.

  1. After you have created a new project from iOS Getting Started guides, open Main.storyboard. Add a UIView element to the main View element and name it to AdUIView.

  2. In addition, add adIconImageView (UIImageView), adTitleLable (UILabel), adCoverMediaView (FBMediaView), adSocialContext (UILabel), adCallToActionaButton (UIButton), adChoiceView (FBAdChoicesView), adBodyLabel (UILabel), sponsoredLabel (UILabel) under AdUIView as illustrated in the image below.

  3. You may notice that there is a red arrow nearby View Controller Scene. This usually means that there are missing constraints in your layout.


    You would need to select all the view objects in your scene and click the "resolve layout issue" icon to add missing constraints.



  4. Now that you have created all the UI elements for showing a native ad, you will need to reference these UI elements in the ViewController interface. First open the ViewController.m, then drag adUIView inside the ViewController interface object. You can name it as adUIView. After, you will need to do the same thing for adIconImageView , adTitleLable, adCoverMediaView, adSocialContext, adCallToActionaButton, adChoiceView, adBodyLabel, sponsoredLabel.

  5. Build and run the project. You should see from your device or simulator empty content as follows:

Now that you have created all the UI elements to show native ads, the next step is to load the native ad and bind the contents to the UI elements.

Step 2: Load and Show Native Ad

  1. Now, in your View Controller header file, import the SDK header, declare that ViewController implements the FBNativeAdDelegate protocol and add a nativeAd instance variable:
    #import <UIKit/UIKit.h>
    @import FBAudienceNetwork;
    
    @interface ViewController () <FBNativeAdDelegate>
      @property (strong, nonatomic) FBNativeAd *nativeAd;
    @end
  2. In viewDidLoad method, add the following lines of code to load native ad content.
    - (void)viewDidLoad 
    {
        [super viewDidLoad];
        FBNativeAd *nativeAd = [[FBNativeAd alloc] initWithPlacementID:@"1805712459697860_1805714169697689"];
        nativeAd.delegate = self;
        nativeAd.mediaCachePolicy = FBNativeAdsCachePolicyAll;
        [nativeAd loadAd];
    }
    Replace YOUR_PLACEMENT_ID with your own placement id string. If you don't have a placement id or don't know how to get one, you can refer to the Getting Started Guide

    Set mediaCachePolicy to be FBNativeAdsCachePolicyAll. This will configure native ad to wait to call nativeAdDidLoad until all ad assets are loaded.

    Audience Network supports five cache options in native ads as defined in the FBNativeAd.h:
    Cache Constants Description

    NONE

    No pre-caching, default

    ICON

    Pre-cache ad icon

    IMAGE

    Pre-cache ad images

    VIDEO

    Pre-cache ad video

    ALL

    Pre-cache all (icon, images, and video)


  3. The next step is to show ad when content is ready. You would need to implement nativeAdDidLoad method in ViewController.m file.
    - (void)nativeAdDidLoad:(FBNativeAd *)nativeAd
    {
        if (self.nativeAd) {
            [self.nativeAd unregisterView];
        }
        
        self.nativeAd = nativeAd;
        // Wire up UIView with the native ad; the whole UIView will be clickable.
        [nativeAd registerViewForInteraction:self.adUIView
                          withViewController:self];
        
        // Create native UI using the ad metadata.
        [self.adCoverMediaView setNativeAd:nativeAd];
        
        __weak typeof(self) weakSelf = self;
        [self.nativeAd.icon loadImageAsyncWithBlock:^(UIImage *image) {
            __strong typeof(self) strongSelf = weakSelf;
            strongSelf.adIconImageView.image = image;
        }];
        
        // Render native ads onto UIView
        self.adTitleLabel.text = self.nativeAd.title;
        self.adBodyLabel.text = self.nativeAd.body;
        self.adSocialContextLabel.text = self.nativeAd.socialContext;
        self.sponsoredLabel.text = @"Sponsored";
        [self.adCallToActionButton setTitle:self.nativeAd.callToAction
                                   forState:UIControlStateNormal];
        self.adChoicesView.nativeAd = nativeAd;
        self.adChoicesView.corner = UIRectCornerTopRight;
    }
    First, you will need to check if there is an existing nativeAd object. If there is, you will need to call unregisterView method. Then you will call [nativeAd registerViewForInteraction:withViewController:] method.

    What registerViewForInteraction mainly does is register what views will be tappable and what the delegate is to notify when a registered view is tapped. In this case, all views inside adUIView will be tappable and when the view is tapped, ViewController will be notified through FBNativeAdDelegate.

    adCoverMediaView contains the media content, either picture or video, of the ad. You will need to call setNativeAd method to set the content of nativeAd to the view.

    You will call loadImageAsyncWithBlock to asynchronously load the image content of the ad icon.

  4. Controlling Clickable Area

    For a better user experience and better results, you should always consider controlling the clickable area of your ad to avoid unintentional clicks.

    For finer control of what is clickable, you can use the [nativeAd registerViewForInteraction:withViewController:withClickableViews:] method to register a list of views that can be clicked. For example if we only want to make the ad image and the call to action button clickable in the previous example, we can write like this:
    - (void)nativeAdDidLoad:(FBNativeAd *)nativeAd
    {
        ...
        // Wire up UIView with the native ad; the whole UIView will be clickable.
        [nativeAd registerViewForInteraction:self.adUIView
                          withViewController:self
                          withClickableViews:@[self.adCallToActionButton, self.adCoverMediaView]];
        
        ...
    }
  5. Choose your build target to be device and run the above code, you should see something like this:



When running in the simulator, you need to set test mode to view test ads. Please refer to How to Use Test Mode for more information.

Step 3: How to Get the Aspect Ratio of the Content and Apply Natural Width and Height

In the example above, the media content of the ad is shown in adCoverMediaView and its object type is FBMediaView. From previous step, we have shown how to use FBMediaView to load media content from a given FBNativeAd object. This view takes the place of manually loading a cover image. When creating the FBMediaView, its width and height can be either determined by the auto layout constraints set in the storyboard, or they can be hard-coded. However, the width and height of the view may not be fit with the actual cover image of the ad downloaded later. To fix this, the example following shows how to get the aspect ratio of the content and apply natural width and height:

  1. In your View Controller header file, declare that ViewController implements the FBMediaViewDelegate protocol as follows:
    @interface ViewController : UIViewController <FBNativeAdDelegate, FBMediaViewDelegate>
  2. When the native ad is loaded, set the delegate of FBMediaView object to be the controller self as follows:
    - (void)nativeAdDidLoad:(FBNativeAd *)nativeAd 
    {
      [self.adCoverMediaView setNativeAd:nativeAd];
      self.adCoverMediaView.delegate = self;
    }
  3. Implement mediaViewDidLoad method in ViewController as follows:
    - (void)mediaViewDidLoad:(FBMediaView *)mediaView
    {
      CGFloat currentAspect = mediaView.frame.size.width / mediaView.frame.size.height;
      NSLog(@"current aspect of media view: %f", currentAspect);
      
      CGFloat actualAspect = mediaView.aspectRatio;
      NSLog(@"actual aspect of media view: %f", actualAspect);
    }
    mediaView.aspectRatio returns a positive CGFloat, or 0.0 if no ad is currently loaded. Its value is valid after media view is loaded. There are convenience methods that will set the width and height of the FBMediaView object respecting its apsect ratio of the media content loaded. You can call applyNaturalWidth or applyNaturalHeight to update the FBMediaView object's width or height to respect the media content's aspect ratio.

Step 4: Verify Impression and Click Logging

Optionally, you can add the following functions to handle the cases where the native ad is closed or when the user clicks on it:

- (void)nativeAdDidClick:(FBNativeAd *)nativeAd
{
    NSLog(@"Native ad was clicked.");
}

- (void)nativeAdDidFinishHandlingClick:(FBNativeAd *)nativeAd
{
    NSLog(@"Native ad did finish click handling.");
}

- (void)nativeAdWillLogImpression:(FBNativeAd *)nativeAd
{
    NSLog(@"Native ad impression is being captured.");
}

Step 5: How to Debug When Ad Not Shown

Add and implement the following function in your View Controller implementation file to handle ad loading failures and completions:

- (void)nativeAd:(FBNativeAd *)nativeAd didFailWithError:(NSError *)error
{
    NSLog(@"Native ad failed to load with error: %@", error);
}

How to Test Audience Network Ad Using Test Mode

Audience Network SDK provides a way to request and show test ads. FBAdSettings provides a test mode for testing Audience Network ad. Here is how you can enable test mode:


When using Testflight to distribute and test your app, you will not be able to see real ads in those test builds. Instead, you will need to set test mode as shown below in order to get ads from Audience Network. Each time a Testflight-distributed app asks for the the Identifier for Advertisers (IDFA), it will get a different IDFA. Normally, IDFA remains constant for a device until a user resets it manually. But when a Testflight build asks for the IDFA from the operating system, it doesn’t get the "real" IDFA. Instead, it gets a "dummy" IDFA that changes each time the app asks for it.

To resolve this issue, you can turn on the test mode to allow the test ad to be shown.

Before loading an ad, add following line of code:

[FBAdSettings setLogLevel:FBAdLogLevelLog];
[FBAdSettings addTestDevice:@”HASHED_ID”];

You would see the following log message:

[FBAudienceNetworkLog/FBAdSettings:94] 
When testing your app with Facebook ad units,  
you must specify the device hashed ID to ensure the delivery of test ads, 
add the following code before loading an ad: `[FBAdSettings addTestDevice:@"HASHED_ID"]`
Test mode device hash: bd675f960298a92003630d76fa612b1706b745ab

Replace HASHED_ID with the test mode device hash printed in the log above.

When you are finished testing, you should turn off the test mode with following call:

//Replace HASHED_ID with the test mode device hash string printed in the log above. 
[FBAdSettings clearTestDevice:@"HASHED_ID"]; 

Next Steps

  • Submit your app for review.

  • As soon as we receive a request for an ad from your app or website, we'll review it to make sure it complies with Audience Network policies and the Facebook community standards. Learn more about our review process.

  • Explore our code samples which demonstrate how to use native ads. The NativeAdSample is available as part of the SDK and can be found under the FBAudienceNetwork/samples folder. Open the project with Xcode and run it either on a device or the simulator.

When using latest Xcode with Facebook Audience Network samples, Xcode will give signing error that the app id used in the sample app cannot be registered to your development team. You would need to change your bundle identifier to a unique string and try again.

More Resources

Getting Started Guide

Technical guide to get started with the Audience Network

Native Ads Manager

Deliver the most relevant ads at the right time

API Reference

Facebook SDK for iOS Reference

Horizontal Scroll

Implement a horizontal scroll unit to maximize ad space