Native ads

Native advertising is a type of ad whose layout can be defined at the app level. This feature allows you to change the visual style of ads and their placement, in the context of the app design specifics.

Native ads enhance the overall ad experience, so you can show more ads while keeping users engaged. In the long run, this allows you to maximize your advertising revenue.

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

Appearance

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

Prerequisite

  1. Follow the SDK integration steps described under Quick start.
  2. First, you need to initialize the advertising SDK.
  3. Make sure you're using the latest version of the Yandex Mobile Ads SDK, and if you're using mediation, the latest version of the unified build.

Implementation

Key steps for integrating native ads:

  • Create and configure a NativeAdLoader.
  • Load the ad.
  • Pass additional settings if you're using Adfox.
  • Render the loaded ad.

Specifics 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 immediately after a loading error. With completion handlers, this corresponds to the .failure case. With Swift Concurrency, it's the catch block. If you need to retry, limit the number of attempts. This helps prevent endless failed requests during network issues.

  3. We recommend maintaining a strong reference to the ad and its loader throughout the lifespan of the screen where the ad interaction is taking place.

  4. The size of the ad container should be based on the ad content.

    After the ad has finished loading, you need to render all of its assets. You can get the list of available ad assets from the NativeAd advertising object.

  5. Ads with a video typically have a higher CTR and, consequently, generate more revenue. To display video ads, the size of the ad container and the MediaView component must be at least 300 × 160 dp (density-independent pixels).

  6. We recommend using a layout that includes all the possible components. In practical terms, such layouts result in higher conversion rates.

Loading ads

To load your native ads, create a NativeAdLoader object.

The ad request parameters are configured via the AdRequest class object. To make a request, you'll need to pass your ad unit ID. You can also customize targeting and other parameters to help deliver higher-quality, more relevant ads. Image loading parameters can be passed using NativeAdOptions. To learn more, see Ad targeting.

To load an ad, use either the loadAd(with:options:completion:) method with a completion handler or the Swift Concurrency-powered loadAd(with:options:) 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()
    }

    private func loadNativeAd() async {
        let request = AdRequest(adUnitID: "R-M-XXXXX-YY")
        let options = NativeAdOptions()
        do {
            let ad = try await adLoader?.loadAd(with: request, options: options)
            // Notifies that a native ad is loaded
        } catch {
            // Notifies that the ad failed to load
        }
    }
}
final class CustomNativeViewController: UIViewController {
    private var adLoader: NativeAdLoader?

    override func viewDidLoad() {
        adLoader = NativeAdLoader()
    }

    private func loadNativeAd() {
        let request = AdRequest(adUnitID: "R-M-XXXXX-YY")
        let options = NativeAdOptions()
        adLoader?.loadAd(with: request, options: options) { [weak self] result in
            switch result {
            case .success(let ad):
                // Notifies that a native ad is loaded
                break
            case .failure:
                // Notifies that the ad failed to load
                break
            }
        }
    }
}

Rendering ads

Warning

Starting in version 8.0.0, we've completely removed native templates (NativeBannerView, MutableNativeTemplateAppearance, and related classes) from the SDK. To customize the look and feel of your native ads, you can manually configure their layout using the steps below.

After the ad has finished loading, you need to render all of its assets. You can get the list of available ad assets from the NativeAd advertising object.

Manual configuration of the native ad layout

This method allows you to create a custom layout for your native ads and define their positioning relative to each other. The ad may include both required and optional assets for display. For the full list, see Native ad assets.

Tip

We recommend using a layout that includes all the possible components. In practical terms, such layouts result in a higher conversion rate.

To manually configure the layout of your native ads:

  1. Create a custom view for the NativeAdView class.

  2. Set up the positioning of custom elements responsible for asset rendering.

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

    final class CustomNativeAdView: NativeAdView {
        // ...
    
        init() {
            super.init(frame: CGRect())
            setupUI()
            bindAssets()
        }
    
        private func bindAssets() {
            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 NativeAdView property for the mandatory component, the ad won't be displayed.

  4. Once the ad loads successfully, bind your custom view to the NativeAd object to display it. 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()
            return adLoader
        }()
    
        override func viewDidLoad() {
            super.viewDidLoad()
            setupUI()
            loadNativeAd()
        }
    
        private func loadNativeAd() {
            let request = AdRequest(adUnitID: "demo-native-app-yandex")
            let options = NativeAdOptions()
            adLoader.loadAd(with: request, options: options) { [weak self] result in
                if case .success(let ad) = result {
                    self?.bindNativeAd(ad)
                }
            }
        }
    
        private func bindNativeAd(_ ad: NativeAd) {
            ad.delegate = self
            do {
                try ad.bind(with: adView)
            } catch {
                // ...
            }
        }
    
        private func setupUI() {
        // ...
        }
    }
    
    

Loading multiple ads

The Yandex Mobile Ads SDK provides the option to load multiple ads in a single request (up to nine ads).

Note

Use the demo-native-bulk-yandex demo ad unit for your AdUnitID. For supported platforms, see Demo ad units for testing.

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

  2. Create an AdRequest with your ad unit ID and use NativeAdOptions for extra settings like image parameters.

  3. Call the loadAds(with:adsCount:options:completion:) method to load ads.

let request = AdRequest(adUnitID: AdUnitID)
let options = NativeAdOptions()
let adLoader = NativeBulkAdLoader()

do {
    let ads = try await adLoader.loadAds(with: request, adsCount: adsCount, options: options)
    // Handling each NativeAd object separately
} catch {
    // Load error
}
let request = AdRequest(adUnitID: AdUnitID)
let options = NativeAdOptions()
let adLoader = NativeBulkAdLoader()

adLoader.loadAds(with: request, adsCount: adsCount, options: options) { result in
    switch result {
    case .success(let ads):
        // Handling each NativeAd object separately
        break
    case .failure:
        break
    }
}

Note

Using a bulk ad request, you can select multiple distinct ads.

The array of ads returned by a bulk request may contain between zero and adsCount NativeAd objects. All the received ad objects can be displayed independently, using the previously described methods for native ad layout.

Testing native ad integration

Using demo ad units for ad testing

Use test ads to check your native ad integration and the app itself.

To make sure that test ads are returned for each ad request, we created a special demo ad placement ID designed to help you test your ad integration.

Demo adUnitId for Combinatorial ads: demo-native-content-yandex.

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

Warning

Before publishing your app in the store, make sure to replace the demo placement ID with the real ID you obtained in the interface Boost.

Testing ad integration

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

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

YandexAds.enableLogging()

To view SDK logs, go to the Console tool and set Subsystem = com.mobile.ads.ads.sdk. You can filter logs by category or 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.

Indicator of correct native ad integration

Note

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

If there's an error in native ad integration, the indicator will appear over the ad in the simulator mode. Click the indicator to see the debug message, which should point you to the root cause of the problem. Clicking the indicator again hides the message.

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

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

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

YandexAds.enableVisibilityErrorIndicator(for: [])

Additional resources