AI Search

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:

  • @objc public var adTitle: String? - Returns the title for the ad.
  • @objc public var adDescription: String? - Returns the description for the ad.
  • @objc public var adIcon: IMNativeImage? - Returns icon image for the ad.
  • @objc public var adCtaText: String? - Returns click to action text for the ad.
  • @objc public var adRating: String? - Returns rating for the ad (optional).
  • @objc public var advertiserName: String? - Returns advertiser name for the ad. (optional).
  • @objc public var adChoice: UIImageView? - Returns ad choice view for the ad. (optional).

The IMNative Class supports the following functions:

  • @objc public func load() - Function to load an ad into memory.
  • @objc public func isReady() -> Bool - True implies that the ad is ready to be displayed.
  • @objc public func getCustomAdContent() -> [String: Any]? - This will have additional information (description, image URL, etc.), which can be used to create custom UI around the primary view of ad.
  • @objc public func isVideoAd() -> Bool - True implies that the ad is a video ad.
  • @objc public func registerViewForTracking(_ view: IMNativeViewData) - Registers your native ad UI for viewability, impression, and click tracking.
  • @objc public func getMediaView() -> UIView? - Returns the SDK-managed media view (image or video) for this ad, if available.

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 <uikit uikit.h="">
    
    @interface InFeedTableViewCell : UITableViewCell
    
    @property (nonatomic, weak) IBOutlet UIImageView *iconImage;
    @property (nonatomic, weak) IBOutlet UILabel *titleLabel;
    @property (nonatomic, weak) IBOutlet UILabel *subtitleLabel;
    @property (nonatomic, weak) IBOutlet UILabel *descriptionLabel;
    @property (nonatomic, weak) IBOutlet UILabel *ctaLabel;
    @property (nonatomic, weak) IBOutlet UIView *adView;
    @property (nonatomic, weak) IBOutlet UIImageView *adChoice;
    
    @end
    </uikit>
    

    Swift

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

    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.image = currentNativeAd.adIcon.imageview;
            cell.titleLabel.text = currentNativeAd.adTitle;
            cell.subtitleLabel.text = @"Sponsored";
            cell.descriptionLabel.text = currentNativeAd.adDescription;
            cell.ctaLabel.text = currentNativeAd.adCtaText;
    
            // Add ad choice view
            [cell.adChoice addSubview:currentNativeAd.adChoice];
            cell.adChoice.userInteractionEnabled = YES;
    
            // Add media view
            UIView *mediaView = [currentNativeAd getMediaView];
            [cell.adView addSubview:mediaView];
            
            // Register native ad views for tracking
            IMNativeViewDataBuilder *builder = [[IMNativeViewDataBuilder alloc] initWithParentView:self.cell];
            [builder setTitleView:cell.titleLabel];
            [builder setDescriptionView:cell.descriptionLabel];
            [builder setCTAView:cell.ctaLabel];
            [builder setIconView:(UIImageView *)cell.iconImage];
    
            IMNativeViewData *nativePubData = [builder build];
            [currentNativeAd registerViewForTracking:nativePubData];
        } 
        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?.imageview
                cell.titleLabel!.text! = currentNativeAd.adTitle
                cell.subtitleLabel?.text! = "Sponsored"
                cell.descriptionLabel.text! = currentNativeAd.adDescription
                cell.ctaLabel?.text! = currentNativeAd.adCtaText
    
                // Add ad choice view
                cell.adChoice.addSubview(currentNativeAd.adChoice)
                cell.adChoice.isUserInteractionEnabled = true
    
                // Add media view
                let mediaView = currentNativeAd.getMediaView()
                adView.addSubview(mediaView)
    
                // Register native ad views for tracking
                let nativePubData = IMNativeViewData.Builder(parentView: cell)
                    .setTitleView(cell.adTitle)
                    .setDescriptionView(cell.descriptionLabel)
                    .setIconView(cell.adIcon)
                    .setCTAView(cell.CtaButton)
                    .build()
                currentNativeAd?.registerViewForTracking(nativePubData)
            }
            
            else {
                // Your app's Table Cell implementations
                
            }
            return cell
    }
    
  7. When implementing ad placements in reusable table view cells, it’s essential to clear out any previously loaded ad before displaying a new one. To achieve this, override the prepareForReuse() method in your custom UITableViewCell subclass. This ensures that any old ad views or data are removed, preventing overlapping content, memory leaks, or incorrect ad rendering during cell reuse.

    Objective-C

    - (void)prepareForReuse {
        [super prepareForReuse];
    
        // Remove previously added ad/media subviews
        for (UIView *v in self.adView.subviews) {
            [v removeFromSuperview];
        }
        // Optionally clear icon/title/etc. if you want:
        // self.iconImage.image = nil; self.titleLabel.text = nil; ...
    }
    

    Swift

    override func prepareForReuse() {
      super.prepareForReuse()
      _ = adView.subviews.map { $0.removeFromSuperview()}
    
      // Optionally clear icon/title/etc. if you want:
      // self.iconImage.image = nil; self.titleLabel.text = nil; ...
    }
    
    
  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

    // Suggested approach
    // Use`- (void)prepareForReuse` in UItableViewCell to clear out any ad before loading
    // 
    -(void)refreshInMobiStrandAd { 
       [self.tableData removeObject:self.InMobiNativeAd]; 
       [self.tableView reloadData];
       self.InMobiNativeAd = [[IMNative alloc] initWithPlacementId:]; 
       self.InMobiNativeAd.delegate = self; 
       [self.InMobiNativeAd load]; 
    }
    
    

    Swift

    //Suggested approach
    //Use `override func prepareForReuse()` in UItableViewCell to clear out any ad before loading
    // any new Ad.
    func refreshInMobiStrandAd() {
            tableData = tableData?.filter({ (obj) -> Bool in
                if obj is IMNative {
                    return false
                }
                return true
            })
            tableView.reloadData()
            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.

  9. Handling Orientation Change - Use autolayout to handle all orientaiton changes on your cell and views. Ad will respond to auto layout changes.
  10. You should set the InMobiNativeAd object and its delegate to nil in the dealloc method of your ViewController class.

    Objective-C

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

    Swift

    deinit {
            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 set the InMobiNativeAd object and its delegate to nil.

    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 = 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 = 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. You should set the InMobiNativeAd object and its delegate to nil.

    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 = nil;
    }
    

    Swift

     var prerollAdView: UIView? // Use this to store the primaryView returned by the IMNative instance.
     func dismissAd() {
            prerollAdView?.isHidden = true
            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)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 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: 22 Nov, 2025