Native Ads

InMobi Native Ads support both static and video ads. You can opt for In-Feed, Splash, or Pre-Roll formats. The steps for creating a native ad placement are given below.

Set up Native Ad

InMobi Native Ads support both static and video ads. You can opt for In-Feed, Splash , or Pre-Roll formats. The steps for creating a native ad placement are given below.

  1. From the left navigation, select Inventory Inventory Settings.
  2. Search for the app or website you would like to create a placement for and click + Add a placement.
  3. Click Select Ad Unit and select Native.
  4. Click Add a placement to start setting up your Native settings.

Once the native placement is created, you will be able to see the placement ID.

Native Ad APIs

The IMNative Class contains the following objects:

  • NSString* adTitle - Returns the title for the ad.
  • NSString* adDescription - Returns the description for the ad.
  • UIImage* adIcon - Returns icon image for the ad.
  • NSString* adCtaText - Returns click to action text for the ad.
  • NSString* adRating - Returns rating for the ad (optional).
  • NSURL* adLandingPageUrl - Returns landing URL for the ad.
  • BOOL isAppDownload - Returns whether the ad is for downloading an app.
  • NSString* customAdContent - This will have additional information (description, image URL, etc.), which can be used to create custom UI around the primary view of ad.

The IMNative Class supports the following functions:

  • -(UIView*)primaryViewOfWidth:(CGFloat)width - Returns a UIView of specified width. This is the main ad content in your native ad. It will return a view of the same aspect ratio that you selected on the InMobi dashboard while creating the native placement. All impression render events are also fired automatically when this primary view is displayed on the screen. 
  • If you have selected Feed Layout while creating your placement, specify width = 25 while fetching your primaryView. It will just show the AdChoices Icon and fire the ad render events. 
  • -(void)load - Function to load an ad into memory. 
  • -(BOOL)isReady - True implies that the ad is ready to be displayed. 
  • -(void)reportAdClickAndOpenLandingPage - This function fires the click events and opens the landing page. You need not open landing page on your own while using this function. 
  • -(void)recyclePrimaryView - Call this function whenever the ad goes out of the visible area on the screen. Also, call this before loading a native ad again on the same object. 

In-Feed Ad Integration

  1. Import the InMobi SDK header files.

    Objective-C

    #import <InMobiSDK/InMobiSDK.h>
    

    Swift

    import InMobiSDK
    
  2. Declare an ad position in your feed where you want to show ad. Example is to show ad at 4th position.

    Objective-C

    #define IM_AD_INSERTION_POSITION 4
    

    Swift

    let adInsertionPosition = 4
    
  3. Declare a native Ad instance in your ViewController.m.

    Objective-C

    @interface TableViewController () <IMNativeDelegate> 
    @property(nonatomic,strong) IMNative *InMobiNativeAd; 
    @end
    

    Swift

    class ViewController: UIViewController, IMNativeDelegate {
    var inMobiNativeAd: IMNative?
    
  4. Your final ViewDidLoad Code should look like:

    Objective-C

    - (void)viewDidLoad { 
        [super viewDidLoad]; 
        self.InMobiNativeAd = [[IMNative alloc] initWithPlacementId:<Insert InMobi  placement ID here>]; 
        self.InMobiNativeAd.delegate = self; 
        [self.InMobiNativeAd load]; 
        //Your app content 
    }
    

    Swift

    override func viewDidLoad() {
        super.viewDidLoad()
        inMobiNativeAd = IMNative(placementId: <Insert InMobi plc id> )
        inMobiNativeAd?.delegate = self
        inMobiNativeAd?.load()
        // Your app content 
    }
    
    	
  5. Implement IMNativeDelegate methods for the success callback. The success callback indicates that the ad is ready to be shown on the screen. Here you should add the InMobiNativeAd Object to your TableView's data source.

    Objective-C

    -(void)nativeDidFinishLoading:(IMNative*)native{
        [self.tableData insertObject:native atIndex:IM_AD_INSERTION_POSITION];
        [self.tableView reloadData];
        NSLog(@"Native Ad did finish loading");
    }
    
    

    Swift

    func nativeDidFinishLoading(_ native: IMNative!) {
         self.tableData.insert(native, at: IM_AD_INSERTION_POSITION)
         self.tableView.reloadData()
         NSLog("InMobi Native Did finished loading");
    }
    
    
    
  6. Rendering native ads and impression tracking

    You have successfully received a native ad when you get the callback nativeAdDidFinishLoading. The following example shows how to fetch the adView in your tableView delegate cellForRowAtIndexPath.

    Note

    Impression events will be fired only when the Native Ad's primary view is in visible area of the screen.

    Implement the below custom cell class using storyboard.


    Objective-C

    #import
    @interface InFeedTableCell : UITableViewCell
    @property (nonatomic, strong) IBOutlet UIImage *iconImage;
    @property (nonatomic, strong) IBOutlet UILabel *titleLabel;
    @property (nonatomic, strong) IBOutlet UILabel *subTitleLabel;
    @property (nonatomic, strong) IBOutlet UILabel *descriptionLabel;
    @property (nonatomic, strong) IBOutlet UILabel *ctaLabel;
    @property (nonatomic, strong) IBOutlet UIView *adView;
    @end
    
    

    Swift

    class InFeedTableViewCell: UITableViewCell {
        @IBOutlet var iconImage : UIImage?
        @IBOutlet var titleLabel : UILabel?
        @IBOutlet var subtitleLabel : UILabel?
        @IBOutlet var descriptionLabel : UILabel?
        @IBOutlet var ctaLabel : UILabel?
        @IBOutlet var adView : UIView?
    }
    
    
     

    Objective-C

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
        InFeedTableCell *cell = ( *)[tableView dequeueReusableCellWithIdentifier:@"InFeedTableCell"]; 
        id nativeAd = [self.tableData objectAtIndex:indexPath.row]; 
        if ([nativeAd isKindOfClass:[IMNative Class]]]) { 
            IMNative * currentNativeAd = nativeAd; 
            cell.iconImage = currentNativeAd.adIcon; 
            cell.titleLabel.text = currentNativeAd.adTitle; 
            cell.subTitleLabel.text = @"Sponsored"; 
            cell.descriptionLabel.text = currentNativeAd.adDescription; 
            cell.ctaLabel.text = currentNativeAd.adCtaText; 
            //Calculate your feed's primaryImageViewWidth and use it to fetch and 
            Ad Primary view of same width. 
            UIView* = [currentNativeAd 
                       primaryViewOfWidth:primaryImageViewWidth]; 
            //Set the frame of Ad Primary View same as that of your feed's Primary View 
            cell.adView = adView; 
            UITapGestureRecognizer *singleTapAndOpenLandingPage = 
            [[UITapGestureRecognizer alloc] initWithTarget:currentNativeAd 
    
        action:@selector(reportAdClickAndOpenLandingPage)]; 
            cell.ctaLabel.userInteractionEnabled = YES; 
            [cell.ctaLabel addGestureRecognizer:singleTapAndOpenLandingPage]; 
        } 
        else{ 
            //Your App’s TableCell implementation 
        } 
        return cell; 
    } 
    

    Swift

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
            let cell = (tableView.dequeueReusableCell(withIdentifier: "InFeedTableCell")! as! InFeedTableViewCell)
    
            if let currentNativeAd = self.tableData?[indexPath.row] as? IMNative {
    
                    cell.iconImageView.image! = currentNativeAd.adIcon
    
                    cell.titleLabel!.text! = currentNativeAd.adTitle
    
                    cell.subtitleLabel?.text! = "Sponsored"
    
                    cell.descriptionLabel.text! = currentNativeAd.adDescription
    
                cell.ctaLabel?.text! = currentNativeAd.adCtaText
    
                    //Calculate your feed’s primaryImageViewWidth and use it to fetch and Ad Primary view of same width.
    
                    if let adPrimaryViewOfCorrectWidth =
                        currentNativeAd.primaryView(ofWidth: primaryImageViewWidth) {
                        cell.addSubview(adPrimaryViewOfCorrectWidth)
                }
                   
    
                let singleTapAndOpenLandingPage = UITapGestureRecognizer(target:currentNativeAd, action: #selector(self.reportAdClickAndOpenLandingPage))
    
                cell.ctaLabel?.isUserInteractionEnabled = true
    
                cell.ctaLabel?.addGestureRecognizer(singleTapAndOpenLandingPage)
    
                }
    
            else {
    
                // Your app's Table Cell implementations
    
            }
    
            return cell
    
        }
    
    	
  7. You need to recycle the Native Ad's Primary view, every time your ad goes out of the screen area. This is to optimize memory usage as well as ensuring that the AdView does not conflict with your app’s native views. Call recyclePrimaryView method on the InMobiNativeAd object every time the ad goes out of the visible area. In a TableView, this can be called in the didEndDisplayingCell Method:

    Objective-C

    - (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { 
        id nativeAd = [self.tableData objectAtIndex:indexPath.row] 
        if([nativeAdself isKindOfClass:[IMNative Class]]){ 
            IMNative *currentNativeAd = nativeAd; 
            [currentNativeAd recyclePrimaryView]; 
        } 
    }
    

    Swift

     func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) {
            if (tableData?[indexPath.row] as? UIView) != nil {
                inMobiNativeAd?.recyclePrimaryView()
            }
        }
    
    	

     

    Note

    After calling the recyclePrimaryView, if you want to add the view again on the screen, you must fetch it from [self.InMobiNativeAd primaryViewOfWidth:<custom width="">]</custom> as the previous view would have been recycled. If you have added it in the cellForRowAtIndexPath delegate (as mentioned in step 8), you don’t have to do anything here.
     

  8. Refreshing the ad - You will need to refresh the ad at various points to optimize ad exposure to your users. To refresh the ad, you will need to call the following functions in the same order.
     

    Objective-C

    -(void)refreshInMobiStrandAd { 
       [self.tableData removeObject:self.InMobiNativeAd]; 
       [self.tableView reloadData]; 
       [self.InMobiNativeAd recyclePrimaryView]; 
       self.InMobiNativeAd = [[IMNative alloc] initWithPlacementId:<Insert InMobi placement ID here>]; 
       self.InMobiNativeAd.delegate = self; 
       [self.InMobiNativeAd load]; 
    }
    

    Swift

    func refreshInMobiStrandAd() {
            tableData = tableData?.filter({ (obj) -> Bool in
                if obj is IMNative {
                    return false
                }
                return true
            })
            tableView.reloadData()
            inMobiNativeAd?.recyclePrimaryView()
            inMobiNativeAd = IMNative(placementId: )
            inMobiNativeAd?.delegate = self
            inMobiNativeAd?.load()
        }
    
    	

    It is important to remove the IMNative object from your tableData and destroy the current ad object. Then you need to create a new object and call load on it. Also, you should recycle the Primary View before destroying your existing object. 
  9. Handling Orientation Change - You will need to calculate the new width for Ad Primary View on orientation change and call the [self.InMobiNativeAd primaryViewOfWidth:<custom width="">]</custom> method again to replace the current Ad Primary View with the new view.
  10. You should set the InMobiNativeAd object and its delegate to nil in the dealloc method of your ViewController class. Do ensure you recycle the view before deallocating to remove all references to the adView.

    Objective-C

    -(void)dealloc {
        [self.InMobiNativeAd recyclePrimaryView];
        self.InMobiNativeAd.delegate = nil;
        self.InMobiNativeAd = nil;
    }
    
    

    Swift

    deinit {
            inMobiNativeAd?.recyclePrimaryView()
            inMobiNativeAd?.delegate = nil
            inMobiNativeAd = nil
        }
    	

Splash Ad Integration

  1. Splash experience can be implemented using the same IMNative Class.
  2. You should use self.InMobiNativeAd.isReady function to determine if the ad is ready to be shown. Sometimes, your main thread may be occupied and hence you may not receive nativeDidFinishLoading in time. Hence, it is better to proactively check if the ad is ready just after your cut-off time has elapsed.
  3. IMPORTANT: You should NOT dismiss the ad if the second screen of the ad is in display. You can check this in the nativeWillPresentScreen and not dismiss the ad if this delegate is fired. Sample implementation is as follows:

    Objective-C

    @property(nonatomic,strong) bool *isSecondScreenDisplayed;// Use this to check if second screen has to be shown or not
    -(void)nativeWillPresentScreen:(IMNative*)native{
        NSLog(@"Native Ad will present screen");
        isSecondScreenDisplayed = YES;
    }
    
    

    Swift

     var isSecondScreenDisplayed: Bool = false// Use this to check if second screen has to be shown or not
        func nativeWillPresentScreen(_ native: IMNative) {
            print("Native Ad will present screen")
            isSecondScreenDisplayed = true
        }
    	
  4. You should recycle the Primary View before dismissing the ad. This can be implemented as follows:

    Objective-C

    @property (nonatomic, strong) UIView* SplashAdView; // Use this view to check for visibility of splash screen
    -(void)dismissAd{
        if(isSecondScreenDisplayed){
            NSLog(@"DO NOT DISMISS THE AD WHILE THE SCREEN IS BEING DISPLAYED");
        }
        else{
            self.SplashAdView.hidden = true;
            [self.InMobiNativeAd recyclePrimaryView];
            self.InMobiNativeAd = nil;
        }
    }
    
    

    Swift

    var splashAdView: UIView? // Use this to check visibility of second screen
        func dismissAd() {
            if isSecondScreenDisplayed {
                print("DO NOT DISMISS THE AD WHILE THE SCREEN IS BEING DISPLAYED")
            }
            else {
                splashAdView?.isHidden = true
                inMobiNativeAd?.recyclePrimaryView()
                inMobiNativeAd = nil
            }
        }
    	

Pre-Roll Ad Integration

  1. Pre-Roll Video experience can be implemented using the same IMNative Class. You will need to dismiss the ad view in the following delegate:

    Objective-C

    -(void)nativeDidFinishPlayingMedia:(IMNative *)native{
        [self dismissAd];
    }
    
    

    Swift

    func nativeDidFinishPlayingMedia(_ native: IMNative) {
            self.dismissAd()
        }
    	
  2. The Pre-Roll ad can be dismissed as follows:

    Objective-C

    @property (nonatomic, strong) UIView* PrerollAdView; //Use this to store the primaryView returned by the IMNative instance.
    -(void)dismissAd{
        self.PrerollAdView.hidden = true;
        [self.InMobiNativeAd recyclePrimaryView];
        self.InMobiNativeAd = nil;
    }
    

    Swift

     var prerollAdView: UIView? // Use this to store the primaryView returned by the IMNative instance.
     func dismissAd() {
            prerollAdView?.isHidden = true
            inMobiNativeAd?.recyclePrimaryView()
            inMobiNativeAd = nil
        }
    
    	

Advanced Settings

You can perform the following steps to get additional callbacks. Implement the following delegate methods in your ViewController.m file:

Objective-C

-(void)nativeDidFinishLoading:(IMNative*)native{
    NSLog(@"Native Ad load Successful"); // Ad is ready to be displayed
}
-(void)native:(IMNative*)native didFailToLoadWithError:(IMRequestStatus*)error{
    NSLog(@"Native Ad load Failed"); // No Fill or error
}
-(void)nativeWillPresentScreen:(IMNative*)native{
    NSLog(@"Native Ad will present screen"); //Full Screen experience is about to be presented
}
-(void)nativeDidPresentScreen:(IMNative*)native{
    NSLog(@"Native Ad did present screen"); //Full Screen experience has been presented
}
-(void)nativeWillDismissScreen:(IMNative*)native{
    NSLog(@"Native Ad will dismiss screen"); //Full Screen experience is going to be dismissed
}
-(void)nativeDidDismissScreen:(IMNative*)native{
    NSLog(@"Native Ad did dismiss screen"); //Full Screen experience has been dismissed
}
-(void)userWillLeaveApplicationFromNative:(IMNative*)native{
    NSLog(@"User leave"); //User is about to leave the app on clicking the ad
}
-(void)native:(IMNative *)native didInteractWithParams:(NSDictionary *)params{
    NSLog(@"User clicked"); // Called when the user clicks on the ad.
}
-(void)nativeAdImpressed:(IMNative *)native{
    NSLog(@"User viewed the ad"); // Called when impression event is fired.
}
-(void)nativeDidFinishPlayingMedia:(IMNative*)native{
    NSLog(@"The Video has finished playing"); // Called when the video has finished playing. Used for preroll use-case
}
-(void)userDidSkipPlayingMediaFromNative:(IMNative*) native {
    NSLog(@"User has skipped playing media"); // Called when the user has opted to skip the media being shown.
}
-(void)native:(IMNative*)native adAudioStateChanged:(BOOL)audioStateMuted {
    if (audioStateMuted) {
        NSLog(@"Inline video-ad audio state changed to mute");
    } 
    else {
        NSLog(@"Inline video-ad audio state changed to unmute");
    }
    //This is called when inline video audio state changes.
}

Swift

func nativeDidFinishLoading(_ native: IMNative) {
        print("Native Ad load Successful") // Ad is ready to be displayed
    }    
    func native(_ native: IMNative, didFailToLoadWithError error: IMRequestStatus) {
        print("Native Ad load Failed") // No Fill or error
    }    
    func nativeWillPresentScreen(_ native: IMNative) {
        print("Native Ad will present screen") //Full Screen experience is about to be presented
    }
    func nativeDidPresentScreen(_ native: IMNative) {
        print("Native Ad did present screen") //Full Screen experience has been presented
    }
    func nativeWillDismissScreen(_ native: IMNative) {
        print("Native Ad will dismiss screen") //Full Screen experience is going to be dismissed
    }    
    func nativeDidDismissScreen(_ native: IMNative) {
        print("Native Ad did dismiss screen") //Full Screen experience has been dismissed
    }    
    func userWillLeaveApplicationFromNative(_ native: IMNative) {
        print("User leave") //User is about to leave the app on clicking the ad
    }    
    func native(_ native: IMNative, didInteractWithParams params: [String : Any]?) {
        print("User clicked") // Called when the user clicks on the ad.
    }    
    func nativeAdImpressed(_ native: IMNative) {
        print("User viewed the ad") // Called when impression event is fired.
    }    
    func nativeDidFinishPlayingMedia(_ native: IMNative) {
        print("The Video has finished playing") // Called when the video has finished playing. Used for preroll use-case
    }    
    func userDidSkipPlayingMediaFromNative(_ native: IMNative) {
        print("User has skipped playing the media") // Called when the user has opted to skip the media being shown.
    }
    func native(_ native: IMNative, adAudioStateChanged audioStateMuted: Bool) {
        if (audioStateMuted) {
            print("Inline state changed to mute")
        }
        else {
            print("Inline state changed to unmute")
        }
    }


Implementing Backfill

InMobi's SDK can run both HTML and native units against your native placement. You can run the following ad sizes depending on the real-estate reserved for your native placement.

  • 320x50 HTML Banner
  • 300x250 HTML Banner
  • 320x480 HTML Full screen Banner
  • 320x568 HTML Full screen Banner

To switch this on, you need to reach out to your respective partner manager with the preferred backfill size. Also, you will need to handle this in your code as follows:

Objective-C

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    InFeedTableCell *cell = (InFeedTableCell *)[tableView
                                                dequeueReusableCellWithIdentifier:@"InFeedTableCell"];
    NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"InFeedTableCell"
                                                 owner:self options:nil];
    cell = [nib objectAtIndex:0];
    id slide = [self.tableData objectAtIndex:indexPath.row];
    if ([self isAdAtIndexPath:indexPath]) {
        IMNative *currentNativeAd = slide;
        NSString *customJSONstring = currentNativeAd.customAdContent;
        NSData *data = [customJSONstring dataUsingEncoding:NSUTF8StringEncoding];
        NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
        BOOL isBackFillBanner = [[jsonDict objectForKey:@"isHTMLResponse"] boolValue];
        if (isBackFillBanner) {
            IMNative * currentNativeAd = slide;
            //Depending on the selected backfill size, provide accurate width below
            UIView* AdPrimaryViewOfCorrectWidth = [currentNativeAd primaryViewOfWidth:250];
            AdPrimaryViewOfCorrectWidth.frame = CGRectMake((_screenWidth-300)/2, 0, 300, 250);
            [cell addSubview:AdPrimaryViewOfCorrectWidth];
        }
        else
        {
            //continue with the current native implementation
            IMNative * currentNativeAd = slide;
            cell.iconImageView.image = currentNativeAd.adIcon;
            cell.titleLabel.text = currentNativeAd.adTitle;
            cell.subTitleLabel.text = @"Sponsored";
            cell.descriptionLabel.text = currentNativeAd.adDescription;
            cell.ctaLabel.text = currentNativeAd.adCtaText;
            //Calculate your feed's primaryImageViewWidth and use it to fetch and Ad Primary view of same width.
            UIView* AdPrimaryViewOfCorrectWidth = [currentNativeAd primaryViewOfWidth:primaryImageViewWidth];
            //Set the frame of Ad Primary View same as that of your feed's Primary View
            AdPrimaryViewOfCorrectWidth.frame = primaryImageViewFrame;
            [cell addSubview:AdPrimaryViewOfCorrectWidth];
            UITapGestureRecognizer *singleTapAndOpenLandingPage =
            [[UITapGestureRecognizer alloc] initWithTarget:currentNativeAd
                                                    action:@selector(reportAdClickAndOpenLandingPage)];
            cell.ctaLabel.userInteractionEnabled = YES;
            [cell.ctaLabel addGestureRecognizer:singleTapAndOpenLandingPage];
        }
    }
    else {
        //Your App’s TableCell implementation
    }
    return cell;
}

Swift

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = (tableView.dequeueReusableCell(withIdentifier: "InFeedTableCell")! as! InFeedTableViewCell)
        if let currentNativeAd = self.tableData?[indexPath.row] as? IMNative {
            let customJSONstring = currentNativeAd.customAdContent
            if let data = customJSONstring?.data(using: .utf8) {
                do {
                    if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
                        if let isBackFillBanner = json["isHTMLResponse"] as? Bool, isBackFillBanner {
                            //Depending on the selected backfill size, provide accurate width below
                            let adPrimaryViewOfCorrectWidth: UIView = currentNativeAd.primaryView(ofWidth: 250)
                            adPrimaryViewOfCorrectWidth.frame = CGRect(x: (_screenWidth-300)/2, y: 0, width: 300, height: 250)
                            cell.addSubview(adPrimaryViewOfCorrectWidth)
                           
                        } else {
                            //continue with the current native implementation
                            cell.iconImageView.image = currentNativeAd.adIcon
                            cell.titleLabel.text = currentNativeAd.adTitle
                            cell.subtitleLabel.text = "Sponsored"
                            cell.descriptionLabel.text = currentNativeAd.description
                            cell.ctaLabel?.text = currentNativeAd.adCtaText
                           
                            //Calculate your feed's primaryImageViewWidth and use it to fetch and Ad Primary view of same width.
                            let adPrimaryViewOfCorrectWidth: UIView = currentNativeAd.primaryView(ofWidth: primaryImageViewWidth)
                           
                            //Set the frame of Ad Primary View same as that of your feed's Primary View
                            let singleTapAndOpenLandingPage = UITapGestureRecognizer(target:currentNativeAd, action: #selector(self.reportAdClickAndOpenLandingPage))
                            cell.ctaLabel?.isUserInteractionEnabled = true
                            cell.ctaLabel?.addGestureRecognizer(singleTapAndOpenLandingPage)
                        }
                    }
                } catch let error as NSError {
                    print("Failed to load: \(error.localizedDescription)")
                }
            }
        }
        return cell    }

 

Note

  • To detect if the response is backfill, the customAdContent will contain the string isHTMLResponse.
  • Do NOT scale the width of the HTML banner response. For e.g. if you selected backfill of 300x250, make sure the provided width is hardcoded 250.
  • Do NOT add the CTA button in case of backfill response. The clicks will not be monetized in case you add this button alongside the ad.

On This Page

Last Updated on: 04 Nov, 2024