Native ads

Native advertising is an ad type where the layout can be defined on the app side. This feature allows you to change the visual style of ads and their placement, considering the app design specifics.

Native ads enhance the ad experience. As a result, you can display more ads without losing user interest. This ensures maximum revenue from advertising in the long run.

Ad rendering is performed with native platform tools, which enhances ad performance and quality.

This guide will show how to integrate native ads into iOS apps. In addition to code examples and instructions, it contains format-specific recommendations and links to additional resources.

Prerequisite

  1. Follow the SDK integration steps described in Quick start.
  2. Initialize your ad SDK in advance.
  3. Make sure you're running the latest Yandex Mobile Ads SDK version. If you're using mediation, make sure you're also running the latest version of the unified build.

Implementation

Key steps for integrating native ads:

  • Create and configure the NativeAdLoader.
  • Set a delegate for the loader and implement the required delegate methods.
  • Load the ad.
  • Pass additional settings if you're using Adfox.
  • Display the loaded ad.

Features of native ad integration

  1. All calls to Yandex Mobile Ads SDK methods must be made from the main thread.

  2. We strongly advise against attempting to load a new ad when receiving an error in the func nativeAdLoader(_ loader: NativeAdLoader, didFailLoadingWithError error: Error) method. If you need to load an ad from func nativeAdLoader(_ loader: NativeAdLoader, didFailLoadingWithError error: Error), restrict ad load retries to avoid recurring failed ad requests due to network connection constraints.

  3. We recommend keeping a strong reference to the ad and its loader throughout the lifecycle of the screen interacting with the ad.

  4. We recommend calculating the size of the ad container based on the ad content.

    When the ad is loaded, you must render all of its assets. You can get the list of components available in the ad from the NativeAd ad object.

  5. Ads with video usually have a higher CTR, which results in higher ad revenue. To display video ads, the size of the ad container and the MediaView component should be at least 300x160 dp (density-independent pixels).

  6. We recommend that you use a layout that includes the complete set of possible assets. In our experience, layouts that include the entire set of assets convert better.

Loading ads

To load native ads, create a NativeAdLoader object.

Ad request parameters are configured using the NativeAdRequestConfiguration class object. As request parameters, you need to pass the ad unit ID. You can also configure the image loading method, age, gender, and other data that can improve the quality of ad selection. Read more in the Ad Targeting section.

To receive notifications about ad loading results, implement the NativeAdLoaderDelegate protocol and set it as a delegate for the previously created NativeAdLoader.

To load an ad, call the loadAd(with: NativeAdRequestConfiguration) method.

The following example shows how to load native ads from the View Controller:

final class CustomNativeViewController: UIViewController {
    private var adLoader: NativeAdLoader?

    override func viewDidLoad() {
        adLoader = NativeAdLoader()
        adLoader?.delegate = self
    }

    private func loadNativeAd() {
        let requestConfiguration = NativeAdRequestConfiguration(adUnitID: "R-M-XXXXX-YY")
        adLoader?.loadAd(with: requestConfiguration)
    }
}

extension CustomNativeViewController: NativeAdLoaderDelegate {
    func nativeAdLoader(_ loader: NativeAdLoader, didLoad ad: NativeAd) {
         //  Notifies that a native ad is loaded
    }

    func nativeAdLoader(_ loader: NativeAdLoader, didFailLoadingWithError error: Error) {
        //  Notifies that the ad failed to load
    }
}

Rendering ads

When the ad is loaded, you must render all of its assets. You can get the list of components available in the ad from the NativeAd ad object.

There are two ways to configure the layout of an ad:

  • Layout using a template.
  • Manual setup for a native ad layout.

Layout using a template

The easiest way to work with native ads is to use a standard template for layout: all you need is a few lines of code in the basic version.

The template already has the complete set of required assets and defines their arrangement relative to each other. The template works with any supported type of native ad.

final class NativeTemplateViewController: UIViewController, NativeAdDelegate {
    private let adView = NativeBannerView()

    // ...

    private lazy var adLoader: NativeAdLoader = {
        let adLoader = NativeAdLoader()
        adLoader.delegate = self
        return adLoader
    }()

    override func viewDidLoad() {
        setupUI()
        loadNativeAd()
    }

    private func loadNativeAd() {
        let requestConfiguration = NativeAdRequestConfiguration(adUnitID: "demo-native-content-yandex")
        adLoader.loadAd(with: requestConfiguration)
    }

    private func bindNativeAd(_ ad: NativeAd) {
        ad.delegate = self
        adView.ad = ad
    }

    private func setupUI() {
	// ...
    }
}

extension NativeTemplateViewController: NativeAdLoaderDelegate {
    func nativeAdLoader(_ loader: NativeAdLoader, didLoad ad: NativeAd) {
        bindNativeAd(ad)
    }

    func nativeAdLoader(_ loader: NativeAdLoader, didFailLoadingWithError error: Error) {
        // ...
    }
 }

You can customize the native ad template. You can read more about this in Setting up the layout using a template.

Manual setup of a native ad layout

When the template settings aren't enough to get the desired effect, you can configure native ads manually.

This method allows you to manually create your native ad layout, defining the placement of ad assets relative to each other. Your ad may contain both mandatory and optional display assets. You can find their full list in Native ad assets.

Tip

We recommend that you use a layout that includes the complete set of possible assets. As practice shows, a layout like this has a positive effect on the conversion rate.

To manually configure the display of native ads:

  1. Create a custom view for the YMANativeAdView class.

  2. Configure the placement of custom elements to display components.

  3. Link these custom elements to the corresponding YMANativeAdView properties:

    final class CustomNativeAdView: YMANativeAdView {
        // ...
    
        init() {
            super.init(frame: CGRect())
            setupUI()
            bindAssets()
        }
    
        private func bindViews() {
            titleLabel = customTitleLabel
            domainLabel = customDomainLabel
            warningLabel = customWarningLabel
            sponsoredLabel = customSponsoredLabel
            feedbackButton = customFeedbackButton
            callToActionButton = customCallToActionButton
            mediaView = customMediaView
            priceLabel = customPriceLabel
            reviewCountLabel = customReviewCountLabel
            ratingView = customRatingView
            bodyLabel = customBodyLabel
            iconImageView = customIconImageView
        }
    
        private func setupUI() {
        // ...
        }
    }
    

    Note

    If you don't link a custom element to the YMANativeAdView property for the mandatory component, the ad won't be displayed.

  4. Link the custom view to the NativeAd ad object to display native ads in the nativeAdLoader(_ loader: NativeAdLoader, didLoad ad: NativeAd) method of the NativeAdLoaderDelegate delegate. To do this, call the bind(with adView: YMANativeAdView) method for the NativeAd object:

    final class NativeCustomViewController: UIViewController, NativeAdDelegate {
        private let adView = NativeCustomAdView()
    
        // ...
    
        private lazy var adLoader: NativeAdLoader = {
            let adLoader = NativeAdLoader()
            adLoader.delegate = self
            return adLoader
        }()
    
        override func viewDidLoad() {
            super.viewDidLoad()
            setupUI()
            loadNativeAd()
        }
    
        private func loadNativeAd() {
            let requestConfiguration = NativeAdRequestConfiguration(adUnitID: "demo-native-app-yandex")
            adLoader.loadAd(with: requestConfiguration)
        }
    
        private func bindNativeAd(_ ad: NativeAd) {
            ad.delegate = self
            do {
                try ad.bind(with: adView)
            } catch {
                // ...
            }
        }
    
        private func setupUI() {
        // ...
        }
    }
    
    extension NativeCustomViewController: NativeAdLoaderDelegate {
        func nativeAdLoader(_ loader: NativeAdLoader, didLoad ad: NativeAd) {
            bindNativeAd(ad)
        }
    
        func nativeAdLoader(_ loader: NativeAdLoader, didFailLoadingWithError error: Error) {
            // ...
        }
    }
    

Loading multiple ads

The Yandex Mobile Ads SDK allows loading multiple ads in a single request (up to nine ads).

Note

Use the demo ad unit demo-native-bulk-yandex for AdUnitID. You can view the supported platforms on the page Demo ad units.

  1. Create an instance of the NativeBulkAdLoader class to get native ads.

  2. Create a nativeAdRequestConfiguration using the NativeAdRequestConfiguration class. As the request parameters, you can use the ad unit ID, method for loading images, age, gender, and other data that might improve the quality of ad selection.

  3. Set a delegate for retrieving ads that implements the NativeBulkAdLoaderDelegate protocol.

  4. To track the ad loading process, implement the NativeBulkAdLoaderDelegate: protocol methods: -nativeBulkAdLoader:didLoadAds: and -nativeBulkAdLoader:didFailLoadingWithError:.

  5. Send to the loader the request configuration and count of ads requested (the adsCount parameter).

// Creating a request configuration
let requestConfiguration = MutableNativeAdRequestConfiguration(adUnitID: AdUnitID)

// Creating a loader
adLoader = NativeBulkAdLoader()
adLoader.delegate = self

// Passing the request configuration and the number of requested ads to the loader
adLoader.loadAds(with: requestConfiguration, adsCount: adsCount)

// Implementing delegate methods

func nativeBulkAdLoader(_ nativeBulkAdLoader: NativeBulkAdLoader, didLoad ads: [NativeAd]) {
    // ..
    // Processing each object with the id<NativeAd> separately
}

Note

A bulk ad request allows you to select multiple distinct ads.

The array of ads returned by a bulk request may contain between zero and adsCount NativeAd objects. All ad objects received can be rendered independently of each another using the above methods for native ad layout.

Testing native ad integration

Using demo ad units for ad testing

We recomend using test ads to test your native ad integration and your app itself.

To guarantee that test ads are returned for every ad request, we created a special demo ad placement ID. Use it to check your ad integration.

Demo adUnitId for a text and image ad: demo-native-content-yandex.

Demo adUnitId for an ad for mobile apps: demo-native-app-yandex.

Warning

Before publishing your app in the store, make sure to replace the demo ad unit ID with a real one obtained from the Partner Interface.

Testing ad integration

You can test your ad integration using the native Console tool.

To view detailed logs, call the YMAMobileAds class's enableLogging method.

YMAMobileAds.enableLogging()

To view SDK logs, go to the Console tool and set sybsystem = com.yandex.mobile.ads.sdk. You can also filter logs by category and error level.

If you're having problems integrating ads, you'll get a detailed report on the issues and recommendations for how to fix them.

Native ad integration indicator

Note

By default, the indicator is only shown in simulator mode (device type DeviceTypeSimulator). You can view device types in DeviceType.

If an error was made when integrating native ads, an indicator appears on top of the ad in simulator mode. Click on the indicator to see a message with debugging information to help you understand the reason for the error. Click the indicator again to hide the message.

To enable the indicator for real devices as well, pass the value DeviceTypeHardware | DeviceTypeSimulator in the enableVisibilityErrorIndicatorForDeviceType: method.

MobileAds.enableVisibilityErrorIndicator(for: [.hardware, .simulator])

To disable the indicator, pass the value DeviceTypeNone in the enableVisibilityErrorIndicatorForDeviceType: method.

MobileAds.enableVisibilityErrorIndicator(for: [])

Additional resources