Skip to content

Opera Ads iOS SDK - Integration Guide

Overview

The Opera Ads iOS SDK enables developers to monetize their iOS applications with high-quality ads. The SDK supports multiple ad formats including Native, Banner (MRAID), Interstitial, Rewarded Video, Rewarded Interstitial, and App Open ads, with minimal setup and robust event callbacks.

Key Features

  • Multiple Ad Formats: Native, Banner, Interstitial, Rewarded Video, Rewarded Interstitial, and App Open
  • Bidding Support: Waterfall, Client-to-Server (C2S) Bidding, and Server-to-Server (S2S) Bidding
  • Dual Language API: Full Swift and Objective-C support
  • Mediation Ready: Adapters for AdMob, AppLovin MAX, and TopOn
  • Privacy Compliant: GDPR, CCPA, and COPPA support
  • Rich Media: MRAID 2.0 support for interactive ads
  • Debug Logging: Comprehensive logging system for development

Prerequisites

Before integrating the Opera Ads SDK, ensure you meet the following requirements:

Development Environment

  • Xcode: 14.0 or higher
  • iOS Deployment Target: iOS 13.0 or higher
  • Language: Swift 5.0+ or Objective-C
  • CocoaPods: 1.10.0 or higher (if using CocoaPods)

Account Setup

  • Active Opera Ads publisher account
  • Application ID (format: pub{}/ep{}/app{})
  • iOS App ID (iTunes App ID)
  • Placement IDs for each ad unit

Required Permissions

Add the following to your Info.plist:

xml
<!-- Required for ad serving -->
<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

Location Data (Optional)

The SDK never requests location permission. If your app already has location permission granted by the user, the SDK will passively read the cached location with approximately 10 km precision (latitude/longitude rounded to 1 decimal place) to improve ad targeting — no additional Info.plist configuration is needed for this.

If your app does not use location at all, no action is required.


Installation & Setup

Add the following to your Podfile:

ruby
platform :ios, '13.0'

target 'YourApp' do
  use_frameworks!

  # Opera Ads SDK
  pod 'OpAdxSdk', '~> 2.9.1'
end

Then run:

bash
pod install

Method 2: Manual Integration

  1. Download the latest OpAdxSdk.xcframework from the releases page
  2. Drag OpAdxSdk.xcframework into your Xcode project
  3. In General > Frameworks, Libraries, and Embedded Content, select Embed & Sign for the framework

Dependency Configuration

The SDK has zero external third-party pod dependencies. Everything you need is bundled within the SDK itself:

  • OMSDK_Opera.xcframework — Open Measurement SDK, vendored directly inside the SDK package. No separate pod installation is required.
  • All networking is implemented using Apple's native URLSession.
  • Privacy consent is handled via Apple's native AppTrackingTransparency framework (a system framework, no pod required).

When integrating via CocoaPods, simply add:

ruby
pod 'OpAdxSdk', '~> 2.9.1'

No additional pod entries are needed.


Initialization

Initialize the SDK in your AppDelegate before loading any ads. The SDK supports both synchronous and asynchronous initialization.

Swift Example

swift
import UIKit
import OpAdxSdk

// Replace with your own values from Opera Ads Publisher Portal
let kApplicationId = "pub13423013211200/ep13423013211584/app14170937163904"
let kIOSAppId = "1444253128"  // Your App Store ID (numeric part of the App Store URL)

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(_ application: UIApplication,
                     didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        // Optional: Enable debug logging (development only)
        // OpAdxLogger.logLevel = .debug

        // Create SDK configuration
        let config = OpAdxSdkInitConfig.create(
            applicationId: kApplicationId,
            iOSAppId: kIOSAppId
        )

        // Initialize SDK with callbacks
        OpAdxSDK.initialize(
            withConfig: config,
            onSuccess: {
                print("Opera Ads SDK initialized successfully")
            },
            onError: { error in
                print("SDK initialization failed: \(error.localizedDescription)")
            }
        )

        return true
    }
}

Objective-C Example

objective-c
#import "AppDelegate.h"
#import <OpAdxSdk/OpAdxSdk.h>

// Replace with your own values from Opera Ads Publisher Portal
static NSString *const kApplicationId = @"pub13423013211200/ep13423013211584/app14170937163904";
static NSString *const kIOSAppId = @"1444253128";  // Your App Store ID (numeric part of the App Store URL)

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    // Optional: Enable debug logging (development only)
    // OpAdxLogger.logLevel = OpAdxLogLevelDebug;

    // Create SDK configuration
    OpAdxSdkInitConfig *config = [OpAdxSdkInitConfig
        createWithApplicationId:kApplicationId
        iOSAppId:kIOSAppId
        publisherName:nil];

    // Initialize SDK with callbacks
    [OpAdxSDK initializeWithConfig:config
                         onSuccess:^{
        NSLog(@"Opera Ads SDK initialized successfully");
    }
                           onError:^(NSError *error) {
        NSLog(@"SDK initialization failed: %@", error.localizedDescription);
    }];

    return YES;
}

@end

Initialization Parameters

ParameterTypeRequiredDescription
applicationIdStringYesYour application ID (format: pub{}/ep{}/app{})
iOSAppIdStringYesApp Store ID — the numeric part of your App Store URL (e.g., xxxxxxxxxxx from https://apps.apple.com/app/xxxxxxxxxxx). If your app is not yet published, use any placeholder value (e.g., "") and update it before release.
publisherNameStringNoPublisher name for reporting
coppaBooleanNoCOPPA compliance flag
usPrivacyStringNoCCPA/US Privacy string

Ad Formats

1. Native Ads

Native ads provide customizable ad content that matches your app's look and feel.

Swift Implementation

swift
import OpAdxSdk

let kNativePlacementId = "s14198263063424"  // Replace with your placement ID

class NativeAdViewController: UIViewController {
    private var nativeAd: OpAdxNativeAd?
    private var adContainerView: UIView!

    func loadNativeAd() {
        nativeAd = OpAdxNativeAd(
            placementId: kNativePlacementId,
            auctionType: .regular
        )

        let listener = OpAdxNativeAdListenerImp(
            onAdLoaded: { [weak self] ad in
                guard let self = self, let nativeAd = ad as? OpAdxNativeAd else { return }
                self.renderNativeAd(nativeAd)
            },
            onAdFailedToLoad: { error in
                print("Native ad failed to load: \(error.message)")
            },
            onAdImpression: {
                print("Native ad impression recorded")
            },
            onAdClicked: {
                print("Native ad clicked")
            }
        )

        nativeAd?.loadAd(listener: listener)
    }

    func renderNativeAd(_ nativeAd: OpAdxNativeAd) {
        // Build your custom ad layout
        let containerView = UIView(frame: CGRect(x: 0, y: 0, width: 300, height: 400))

        let titleLabel = UILabel()
        titleLabel.text = nativeAd.title()

        let bodyLabel = UILabel()
        bodyLabel.text = nativeAd.descriptionStr()

        let ctaButton = UIButton(type: .system)
        ctaButton.setTitle(nativeAd.callToAction(), for: .normal)

        let iconImageView = UIImageView()
        // Load icon from nativeAd.iconUrl()

        let mediaView = nativeAd.createMediaView()

        // Add subviews to containerView (layout omitted for brevity)
        containerView.addSubview(titleLabel)
        containerView.addSubview(bodyLabel)
        containerView.addSubview(ctaButton)
        containerView.addSubview(iconImageView)
        containerView.addSubview(mediaView)
        view.addSubview(containerView)

        // Register views for interaction tracking and ad choice icon
        let rootView = OpAdxNativeAdRootView(root: containerView)
        let interactionViews = OpAdxInteractionViews(
            mediaView: mediaView,
            titleView: titleLabel,
            bodyView: bodyLabel,
            callToActionView: ctaButton,
            iconView: iconImageView,
            extraClickableViews: nil
        )
        nativeAd.registerInteractionViews(
            container: rootView,
            interactionViews: interactionViews,
            adChoicePosition: .topRight
        )
    }

    func destroyNativeAd() {
        nativeAd?.destroy()
        nativeAd = nil
    }
}

Objective-C Implementation

objective-c
#import <OpAdxSdk/OpAdxSdk.h>

static NSString *const kNativePlacementId = @"s14198263063424";  // Replace with your placement ID

@interface NativeAdViewController () <OpAdxNativeAdDelegate>
@property (nonatomic, strong) OpAdxNativeAdBridge *nativeAd;
@end

@implementation NativeAdViewController

- (void)loadNativeAd {
    self.nativeAd = [[OpAdxNativeAdBridge alloc]
        initWithPlacementId:kNativePlacementId
        auctionType:AdAuctionTypeRegular];

    self.nativeAd.delegate = self;
    [self.nativeAd loadAd];
}

#pragma mark - OpAdxNativeAdDelegate

- (void)nativeAdDidLoad:(OpAdxNativeAdBridge *)nativeAd {
    [self renderNativeAd:nativeAd];
}

- (void)nativeAd:(OpAdxNativeAdBridge *)nativeAd didFailWithError:(OpAdxAdError *)error {
    NSLog(@"Native ad failed: %@", error.message);
}

- (void)nativeAdDidDownloadMedia:(OpAdxNativeAdBridge *)nativeAd {
    NSLog(@"Native ad media downloaded");
}

- (void)nativeAdWillLogImpression:(OpAdxNativeAdBridge *)nativeAd {
    NSLog(@"Native ad impression");
}

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

- (void)nativeAdDidFinishHandlingClick:(OpAdxNativeAdBridge *)nativeAd {
    NSLog(@"Native ad finished handling click");
}

@end

OpAdxNativeAdDelegate Methods (Objective-C)

All delegate methods are optional:

MethodDescription
nativeAdDidLoad:Ad loaded successfully
nativeAd:didFailWithError:Ad failed to load
nativeAdDidDownloadMedia:Media assets downloaded
nativeAdWillLogImpression:Impression is about to be recorded
nativeAdDidClick:Ad was clicked
nativeAdDidFinishHandlingClick:Click handling completed

Native Ad Assets

Swift MethodObjC PropertyReturn TypeDescription
title()titleString?Ad headline
descriptionStr()adDescriptionString?Ad description text
callToAction()callToActionString?CTA button text (e.g., "Install")
iconUrl()iconUrlURL?Square icon image URL
imageUrl()imageUrlURL?Main creative image URL
starRating()starRatingNSNumber?App rating (0–5)
sponsor()sponsorString?Advertiser / sponsor name
privacy()privacyURL?Privacy policy URL
createMediaView()createMediaViewOpAdxMediaViewVideo/image media view (call on main thread)

2. Banner Ads

Banner ads are rectangular ads that appear at the top or bottom of your app's interface.

Supported Sizes

Size ConstantDimensionsDescription
BANNER320x50Standard banner
LARGE_BANNER320x100Large banner
MEDIUM_RECTANGLE300x250Medium rectangle
FULL_BANNER468x60Full banner
LEADERBOARD728x90Leaderboard (iPad)
SMART_BANNERScreen width x autoSmart banner (adapts to device)

Swift Implementation

swift
import OpAdxSdk

let kBannerPlacementId = "s14170965187264"  // Replace with your placement ID

class BannerViewController: UIViewController {
    private var bannerAdView: OpAdxBannerAdView?

    func loadBannerAd() {
        // Create banner ad view
        bannerAdView = OpAdxBannerAdView()
        bannerAdView?.setPlacementId(kBannerPlacementId)
        bannerAdView?.setAdSize(.MEDIUM_RECTANGLE)

        // Create listener
        let listener = OpAdxBannerAdListenerImp(
            onAdLoaded: { [weak self] bannerAdInfo in
                guard let self = self, let info = bannerAdInfo as? OpAdxBannerAdInfo else { return }
                print("Banner loaded: \(info.adSize)")
                self.showBanner()
            },
            onAdFailedToLoad: { error in
                print("Banner failed to load: \(error.message)")
            },
            onAdImpression: {
                print("Banner impression")
            },
            onAdClicked: {
                print("Banner clicked")
            }
        )

        // Load ad
        bannerAdView?.loadAd(listener: listener)
    }

    func showBanner() {
        guard let bannerAdView = bannerAdView else { return }

        // Add to view hierarchy
        view.addSubview(bannerAdView)
        bannerAdView.translatesAutoresizingMaskIntoConstraints = false

        NSLayoutConstraint.activate([
            bannerAdView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            bannerAdView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
            bannerAdView.widthAnchor.constraint(equalToConstant: 300),
            bannerAdView.heightAnchor.constraint(equalToConstant: 250)
        ])
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        bannerAdView?.pause()
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        bannerAdView?.resume()
    }

    func destroyBanner() {
        bannerAdView?.destroy()
        bannerAdView = nil
    }
}

Objective-C Implementation

objc
#import <OpAdxSdk/OpAdxSdk.h>

static NSString *const kBannerPlacementId = @"s14170965187264";  // Replace with your placement ID

@interface BannerViewController () <OpAdxBannerAdDelegate>
@property (nonatomic, strong) OpAdxBannerAdBridge *bannerAdView;
@end

@implementation BannerViewController

- (void)loadBannerAd {
    [self destroyBanner];

    // Create banner ad with placement ID and size
    self.bannerAdView = [[OpAdxBannerAdBridge alloc] initWithPlacementId:kBannerPlacementId
                                                                 adSize:OpAdxAdSize.MEDIUM_RECTANGLE];
    self.bannerAdView.delegate = self;

    // Load ad
    [self.bannerAdView loadAd];
}

- (void)showBanner {
    if (!self.bannerAdView) return;

    [self.view addSubview:self.bannerAdView];
    self.bannerAdView.translatesAutoresizingMaskIntoConstraints = NO;

    [NSLayoutConstraint activateConstraints:@[
        [self.bannerAdView.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor],
        [self.bannerAdView.bottomAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.bottomAnchor],
        [self.bannerAdView.widthAnchor constraintEqualToConstant:300],
        [self.bannerAdView.heightAnchor constraintEqualToConstant:250]
    ]];
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    [self.bannerAdView pause];
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self.bannerAdView resume];
}

- (void)destroyBanner {
    [self.bannerAdView destroy];
    self.bannerAdView = nil;
}

#pragma mark - OpAdxBannerAdDelegate

- (void)bannerAdDidLoad:(OpAdxBannerAdBridge *)bannerAd {
    NSLog(@"Banner loaded: %@", bannerAd.adSize);
    [self showBanner];
}

- (void)bannerAd:(OpAdxBannerAdBridge *)bannerAd didFailWithError:(OpAdxAdError *)error {
    NSLog(@"Banner failed to load: %@", error.message);
}

- (void)bannerAdDidDisplay:(OpAdxBannerAdBridge *)bannerAd {
    NSLog(@"Banner impression");
}

- (void)bannerAdDidClick:(OpAdxBannerAdBridge *)bannerAd {
    NSLog(@"Banner clicked");
}

@end

OpAdxBannerAdDelegate Methods (Objective-C)

MethodDescription
bannerAdDidLoad:Called when the banner ad is loaded successfully
bannerAd:didFailWithError:Called when the banner ad fails to load
bannerAdDidDisplay:Called when the banner ad records an impression
bannerAdDidClick:Called when the banner ad is clicked
bannerAdDidClose:Called when the banner ad is closed
bannerAdWillLeaveApplication:Called when the user leaves the app after clicking
bannerAdDidReturnToApplication:Called when the user returns to the app

All delegate methods are optional.

Auto-Refresh Configuration

swift
// Set auto-refresh interval (30-120 seconds)
bannerAdView?.setAutoRefreshInterval(60)

// Or disable auto-refresh
bannerAdView?.setAutoRefreshInterval(0)

3. Interstitial Ads

Interstitial ads are full-screen ads that cover the interface of their host app.

Swift Implementation

swift
import OpAdxSdk

let kInterstitialPlacementId = "s14198264979520"  // Replace with your placement ID

class InterstitialViewController: UIViewController {
    private var interstitialAd: OpAdxInterstitialAd?

    func loadInterstitialAd() {
        destroyAd()

        // Create interstitial ad
        interstitialAd = OpAdxInterstitialAd(
            placementId: kInterstitialPlacementId,
            auctionType: .regular
        )

        // Create load listener
        let loadListener = OpAdxInterstitialAdLoadListenerImp(
            onAdLoaded: { [weak self] ad in
                print("Interstitial loaded")
            },
            onAdFailedToLoad: { error in
                print("Interstitial failed to load: \(error.message)")
            }
        )

        // Load ad
        interstitialAd?.load(placementId: kInterstitialPlacementId, listener: loadListener)
    }

    func showInterstitialAd() {
        guard let interstitialAd = interstitialAd else { return }

        // Check if ad is still valid
        if interstitialAd.isAdInvalidated() {
            print("Ad has expired")
            loadInterstitialAd()
            return
        }

        // Create interaction listener
        let interactionListener = OpAdxInterstitialAdInteractionListenerImp(
            onAdClicked: {
                print("Interstitial clicked")
            },
            onAdDisplayed: {
                print("Interstitial displayed")
            },
            onAdDismissed: { [weak self] in
                print("Interstitial dismissed")
                self?.interstitialAd = nil
            },
            onAdFailedToShow: { error in
                print("Interstitial failed to show: \(error.message)")
            }
        )

        // Show ad
        interstitialAd.show(on: self, listener: interactionListener)
    }

    func destroyAd() {
        interstitialAd?.destroy()
        interstitialAd = nil
    }
}

Objective-C Implementation

objc
#import <OpAdxSdk/OpAdxSdk.h>

static NSString *const kInterstitialPlacementId = @"s14198264979520";  // Replace with your placement ID

@interface InterstitialViewController () <OpAdxInterstitialAdDelegate>
@property (nonatomic, strong) OpAdxInterstitialAdBridge *interstitialAd;
@end

@implementation InterstitialViewController

- (void)loadInterstitialAd {
    [self destroyAd];

    // Create interstitial ad
    self.interstitialAd = [[OpAdxInterstitialAdBridge alloc] initWithPlacementId:kInterstitialPlacementId
                                                                    auctionType:AdAuctionTypeRegular];
    self.interstitialAd.delegate = self;

    // Load ad
    [self.interstitialAd loadAd];
}

- (void)showInterstitialAd {
    if (!self.interstitialAd) return;

    // Check if ad is still valid
    if (![self.interstitialAd isAdValid]) {
        NSLog(@"Ad has expired");
        [self loadInterstitialAd];
        return;
    }

    // Show ad
    [self.interstitialAd showAdFrom:self];
}

- (void)destroyAd {
    self.interstitialAd = nil;
}

#pragma mark - OpAdxInterstitialAdDelegate

- (void)interstitialAdDidLoad:(OpAdxInterstitialAdBridge *)interstitialAd {
    NSLog(@"Interstitial loaded");
}

- (void)interstitialAd:(OpAdxInterstitialAdBridge *)interstitialAd didFailWithError:(OpAdxAdError *)error {
    NSLog(@"Interstitial failed to load: %@", error.message);
}

- (void)interstitialAdDidDisplay:(OpAdxInterstitialAdBridge *)interstitialAd {
    NSLog(@"Interstitial displayed");
}

- (void)interstitialAdDidClick:(OpAdxInterstitialAdBridge *)interstitialAd {
    NSLog(@"Interstitial clicked");
}

- (void)interstitialAdDidClose:(OpAdxInterstitialAdBridge *)interstitialAd {
    NSLog(@"Interstitial dismissed");
    self.interstitialAd = nil;
}

- (void)interstitialAd:(OpAdxInterstitialAdBridge *)interstitialAd didFailToDisplayWithError:(OpAdxAdError *)error {
    NSLog(@"Interstitial failed to show: %@", error.message);
}

@end

OpAdxInterstitialAdDelegate Methods (Objective-C)

MethodDescription
interstitialAdDidLoad:Called when the interstitial ad is loaded successfully
interstitialAd:didFailWithError:Called when the interstitial ad fails to load
interstitialAdDidDisplay:Called when the interstitial ad is displayed
interstitialAdDidClick:Called when the interstitial ad is clicked
interstitialAdDidClose:Called when the interstitial ad is closed
interstitialAd:didFailToDisplayWithError:Called when the interstitial ad fails to show

All delegate methods are optional.


4. Rewarded Video Ads

Rewarded video ads reward users for watching short videos.

Swift Implementation

swift
import OpAdxSdk

let kRewardedPlacementId = "s14198592226752"  // Replace with your placement ID

class RewardedViewController: UIViewController {
    private var rewardedAd: OpAdxRewardedAd?

    func loadRewardedAd() {
        destroyAd()

        // Create rewarded ad
        rewardedAd = OpAdxRewardedAd(
            placementId: kRewardedPlacementId,
            auctionType: .regular
        )

        // Create load listener
        let loadListener = OpAdxRewardedAdLoadListenerImp(
            onAdLoaded: { [weak self] ad in
                print("Rewarded ad loaded")
            },
            onAdFailedToLoad: { error in
                print("Rewarded ad failed to load: \(error.message)")
            }
        )

        // Load ad
        rewardedAd?.load(placementId: kRewardedPlacementId, listener: loadListener)
    }

    func showRewardedAd() {
        guard let rewardedAd = rewardedAd else { return }

        if rewardedAd.isAdInvalidated() {
            print("Ad has expired")
            loadRewardedAd()
            return
        }

        // Set scene ID (optional, for analytics)
        rewardedAd.setSceneId("level_complete")

        // Set SSV options (optional, for server-side verification)
        let ssvOptions = RewardSsvOptions.Builder()
            .userId("user_12345")
            .customData("level=5&score=1000")
            .build()
        rewardedAd.setRewardSsvOptions(ssvOptions)

        // Create interaction listener
        let interactionListener = OpAdxRewardedAdInteractionListenerImp(
            onAdClicked: {
                print("Rewarded ad clicked")
            },
            onAdDisplayed: {
                print("Rewarded ad displayed")
            },
            onAdDismissed: { [weak self] in
                print("Rewarded ad dismissed")
                self?.rewardedAd = nil
            },
            onAdFailedToShow: { error in
                print("Rewarded ad failed to show: \(error.message)")
            },
            onUserRewarded: { reward in
                // reward.type: String, reward.amount: Int
                print("User rewarded: \(reward.type) x \(reward.amount)")
            }
        )

        // Show ad
        rewardedAd.show(on: self, listener: interactionListener)
    }

    func destroyAd() {
        rewardedAd?.destroy()
        rewardedAd = nil
    }
}

Objective-C Implementation

objc
#import <OpAdxSdk/OpAdxSdk.h>

static NSString *const kRewardedPlacementId = @"s14198592226752";  // Replace with your placement ID

@interface RewardedViewController () <OpAdxRewardedAdDelegate>
@property (nonatomic, strong) OpAdxRewardedAdBridge *rewardedAd;
@end

@implementation RewardedViewController

- (void)loadRewardedAd {
    [self destroyAd];

    // Create rewarded ad
    self.rewardedAd = [[OpAdxRewardedAdBridge alloc] initWithPlacementId:kRewardedPlacementId
                                                            auctionType:AdAuctionTypeRegular];
    self.rewardedAd.delegate = self;

    // Load ad
    [self.rewardedAd loadAd];
}

- (void)showRewardedAd {
    if (!self.rewardedAd) return;

    if (![self.rewardedAd isAdValid]) {
        NSLog(@"Ad has expired");
        [self loadRewardedAd];
        return;
    }

    // Show ad
    [self.rewardedAd showAdFrom:self];
}

- (void)destroyAd {
    self.rewardedAd = nil;
}

#pragma mark - OpAdxRewardedAdDelegate

- (void)rewardedAdDidLoad:(OpAdxRewardedAdBridge *)rewardedAd {
    NSLog(@"Rewarded ad loaded");
}

- (void)rewardedAd:(OpAdxRewardedAdBridge *)rewardedAd didFailWithError:(OpAdxAdError *)error {
    NSLog(@"Rewarded ad failed to load: %@", error.message);
}

- (void)rewardedAdDidDisplay:(OpAdxRewardedAdBridge *)rewardedAd {
    NSLog(@"Rewarded ad displayed");
}

- (void)rewardedAdDidClick:(OpAdxRewardedAdBridge *)rewardedAd {
    NSLog(@"Rewarded ad clicked");
}

- (void)rewardedAdDidClose:(OpAdxRewardedAdBridge *)rewardedAd {
    NSLog(@"Rewarded ad dismissed");
    self.rewardedAd = nil;
}

- (void)rewardedAd:(OpAdxRewardedAdBridge *)rewardedAd didFailToDisplayWithError:(OpAdxAdError *)error {
    NSLog(@"Rewarded ad failed to show: %@", error.message);
}

- (void)rewardedAd:(OpAdxRewardedAdBridge *)rewardedAd didRewardUserWithItem:(OpAdxRewardItem *)rewardItem {
    // rewardItem.type: NSString, rewardItem.amount: NSInteger
    NSLog(@"User rewarded: %@ x %ld", rewardItem.type, (long)rewardItem.amount);
}

@end

OpAdxRewardedAdDelegate Methods (Objective-C)

MethodDescription
rewardedAdDidLoad:Called when the rewarded ad is loaded successfully
rewardedAd:didFailWithError:Called when the rewarded ad fails to load
rewardedAdDidDisplay:Called when the rewarded ad is displayed
rewardedAdDidClick:Called when the rewarded ad is clicked
rewardedAdDidClose:Called when the rewarded ad is closed
rewardedAd:didFailToDisplayWithError:Called when the rewarded ad fails to show
rewardedAd:didRewardUserWithItem:Called when the user earns a reward

All delegate methods are optional.


5. App Open Ads

App Open ads are shown when users open or switch back to your app.

Swift Implementation

swift
import OpAdxSdk

let kAppOpenPlacementId = "s14496438551808"  // Replace with your placement ID

class AppOpenViewController: UIViewController {
    private var appOpenAd: OpAdxAppOpenAd?

    func loadAppOpenAd() {
        destroyAd()

        // Create app open ad
        appOpenAd = OpAdxAppOpenAd(
            placementId: kAppOpenPlacementId,
            auctionType: .regular
        )

        // Create load listener
        let loadListener = OpAdxAppOpenAdLoadListenerImp(
            onAdLoaded: { [weak self] ad in
                print("App open ad loaded")
            },
            onAdFailedToLoad: { error in
                print("App open ad failed to load: \(error.message)")
            }
        )

        // Load ad
        appOpenAd?.load(placementId: kAppOpenPlacementId, listener: loadListener)
    }

    func showAppOpenAd() {
        guard let appOpenAd = appOpenAd else { return }

        if appOpenAd.isAdInvalidated() {
            print("Ad has expired")
            loadAppOpenAd()
            return
        }

        // Create interaction listener
        let interactionListener = OpAdxAppOpenAdInteractionListenerImp(
            onAdClicked: {
                print("App open ad clicked")
            },
            onAdDisplayed: {
                print("App open ad displayed")
            },
            onAdDismissed: { [weak self] in
                print("App open ad dismissed")
                self?.appOpenAd = nil
            },
            onAdFailedToShow: { error in
                print("App open ad failed to show: \(error.message)")
            }
        )

        // Show ad
        appOpenAd.show(on: self, listener: interactionListener)
    }

    func destroyAd() {
        appOpenAd?.destroy()
        appOpenAd = nil
    }
}

Objective-C Implementation

objc
#import <OpAdxSdk/OpAdxSdk.h>

static NSString *const kAppOpenPlacementId = @"s14496438551808";  // Replace with your placement ID

@interface AppOpenViewController () <OpAdxAppOpenAdDelegate>
@property (nonatomic, strong) OpAdxAppOpenAdBridge *appOpenAd;
@end

@implementation AppOpenViewController

- (void)loadAppOpenAd {
    [self destroyAd];

    // Create app open ad
    self.appOpenAd = [[OpAdxAppOpenAdBridge alloc] initWithPlacementId:kAppOpenPlacementId
                                                          auctionType:AdAuctionTypeRegular];
    self.appOpenAd.delegate = self;

    // Load ad
    [self.appOpenAd loadAd];
}

- (void)showAppOpenAd {
    if (!self.appOpenAd) return;

    if (![self.appOpenAd isAdValid]) {
        NSLog(@"Ad has expired");
        [self loadAppOpenAd];
        return;
    }

    // Show ad
    [self.appOpenAd showAdFrom:self];
}

- (void)destroyAd {
    self.appOpenAd = nil;
}

#pragma mark - OpAdxAppOpenAdDelegate

- (void)appOpenAdDidLoad:(OpAdxAppOpenAdBridge *)appOpenAd {
    NSLog(@"App open ad loaded");
}

- (void)appOpenAd:(OpAdxAppOpenAdBridge *)appOpenAd didFailWithError:(OpAdxAdError *)error {
    NSLog(@"App open ad failed to load: %@", error.message);
}

- (void)appOpenAdDidDisplay:(OpAdxAppOpenAdBridge *)appOpenAd {
    NSLog(@"App open ad displayed");
}

- (void)appOpenAdDidClick:(OpAdxAppOpenAdBridge *)appOpenAd {
    NSLog(@"App open ad clicked");
}

- (void)appOpenAdDidClose:(OpAdxAppOpenAdBridge *)appOpenAd {
    NSLog(@"App open ad dismissed");
    self.appOpenAd = nil;
}

- (void)appOpenAd:(OpAdxAppOpenAdBridge *)appOpenAd didFailToDisplayWithError:(OpAdxAdError *)error {
    NSLog(@"App open ad failed to show: %@", error.message);
}

@end

OpAdxAppOpenAdDelegate Methods (Objective-C)

MethodDescription
appOpenAdDidLoad:Called when the app open ad is loaded successfully
appOpenAd:didFailWithError:Called when the app open ad fails to load
appOpenAdDidDisplay:Called when the app open ad is displayed
appOpenAdDidClick:Called when the app open ad is clicked
appOpenAdDidClose:Called when the app open ad is closed
appOpenAd:didFailToDisplayWithError:Called when the app open ad fails to show

All delegate methods are optional.


Advanced Features

Bidding Support

The Opera Ads SDK supports three bidding modes:

1. Waterfall (Regular)

Standard mediation waterfall based on CPM priorities.

swift
let ad = OpAdxInterstitialAd(placementId: "YOUR_PLACEMENT_ID", auctionType: .regular)

2. Client-to-Server (C2S) Bidding

Also known as "In-App Bidding" or "Header Bidding".

swift
// Step 1: Get bid token
let request = BidTokenRequest.Builder(adMediation: .admob)
    .placementId("YOUR_PLACEMENT_ID")
    .adFormat(.interstitial)
    .build()

// Implement BidTokenCallback protocol
class MyBidTokenCallback: BidTokenCallback {
    func onSuccess(bidToken: String) {
        print("Bid token: \(bidToken)")
        // Send token to your mediation platform
    }

    func onError(error: OpAdxAdError) {
        print("Failed to get bid token: \(error.message)")
    }
}

OpAdxSDK.getBidToken(request, callback: MyBidTokenCallback())

// Step 2: Load ad with client bidding
let ad = OpAdxInterstitialAd(placementId: "YOUR_PLACEMENT_ID", auctionType: .clientBidding)
Objective-C
objective-c
// Step 1: Get bid token
OpAdxBidTokenRequest *request = [[[OpAdxBidTokenRequestBuilder alloc] initWithAdMediation:@"admob"]
    placementId:@"YOUR_PLACEMENT_ID"]
    adFormat:@"interstitial"]
    build];

// Implement OpAdxBidTokenCallback protocol
[OpAdxSDK getBidTokenWithRequest:request callback:self];

// In your callback methods:
- (void)onSuccessWithBidToken:(NSString *)bidToken {
    NSLog(@"Bid token: %@", bidToken);
}

- (void)onErrorWithError:(OpAdxAdError *)error {
    NSLog(@"Failed: %@", error.message);
}

3. Server-to-Server (S2S) Bidding

Bidding handled entirely on the server side.

swift
// Step 1: Get bid token (same as C2S)
// Step 2: Your server participates in the auction
// Step 3: Load ad with bid response

let ad = OpAdxInterstitialAd(placementId: "YOUR_PLACEMENT_ID", auctionType: .serverBidding)
ad.loadRtb(placementId: "YOUR_PLACEMENT_ID", bidResponse: "BID_RESPONSE_FROM_SERVER", listener: listener)

Audio Control

Control audio output for video ads:

swift
// Mute all video ads
OpAdxSdkCore.setOpAdxSdkMuted(true)

// Unmute all video ads
OpAdxSdkCore.setOpAdxSdkMuted(false)

// Reset to default (nil = follow device volume)
OpAdxSdkCore.setOpAdxSdkMuted(nil)
objective-c
// Objective-C
[OpAdxSdkCore setOpAdxSdkMuted:@YES];  // Mute
[OpAdxSdkCore setOpAdxSdkMuted:@NO];   // Unmute
[OpAdxSdkCore setOpAdxSdkMuted:nil];   // Reset to default

Important: Call setOpAdxSdkMuted() before loading ads. It affects all video ad formats.

Server-Side Verification (SSV)

For rewarded ads, configure SSV to prevent reward fraud:

swift
// Configure in your app
let ssvOptions = RewardSsvOptions.Builder()
    .userId("user_12345")              // Max 100 bytes after URL encoding
    .customData("level=5&score=1000")  // Max 1KB after URL encoding
    .build()

rewardedAd.setRewardSsvOptions(ssvOptions)

// Configure callback URL in Opera Publisher Portal
// Your server will receive a callback when the user earns a reward

SSV Callback Parameters:

  • user_id: User identifier you provided
  • custom_data: Custom data you provided
  • reward_type: Reward type (e.g., "coins")
  • reward_amount: Reward amount (e.g., 100)
  • transaction_id: Unique transaction ID
  • signature: HMAC-SHA256 signature for verification

Privacy & Compliance

COPPA Compliance

If your app is directed at children under 13 (or subject to COPPA):

swift
let config = OpAdxSdkInitConfig.Builder(applicationId: "YOUR_APP_ID")
    .coppa(true)  // Enable COPPA compliance
    .build()

COPPA Values:

  • true: Subject to COPPA (children under 13)
  • false: Not subject to COPPA
  • nil (default): Unspecified

CCPA / US Privacy

Pass the IAB US Privacy String via the SDK init config:

swift
let config = OpAdxSdkInitConfig.Builder(applicationId: "YOUR_APP_ID")
    .iOSAppId("YOUR_IOS_APP_ID")
    .usPrivacy("1YNN")
    .build()

GDPR Compliance

The Opera Ads SDK (Vendor ID: 1135) is registered in the IAB TCF Global Vendor List. The SDK automatically reads TCF consent strings (IABTCF_TCString, IABTCF_gdprApplies) from UserDefaults. No additional code is needed if you use a TCF-compliant CMP.


Debug Logging

The Opera Ads SDK includes a comprehensive logging system for development and debugging, helping developers quickly identify and resolve integration issues.

Enable Debug Logs

Swift

swift
// Set log level (do this before SDK initialization)
OpAdxLogger.logLevel = .debug

// Available log levels:
// .none     - No logs (recommended for production)
// .error    - Errors only
// .warning  - Warnings and errors
// .info     - Info, warnings, and errors (default)
// .debug    - Debug, info, warnings, and errors (recommended for development)
// .verbose  - All logs including network request details (for detailed debugging)

Objective-C

objective-c
// Set log level (do this before SDK initialization)
OpAdxLogger.logLevel = OpAdxLogLevelDebug;

// Available log levels:
// OpAdxLogLevelNone     - No logs
// OpAdxLogLevelError    - Errors only
// OpAdxLogLevelWarning  - Warnings and errors
// OpAdxLogLevelInfo     - Info, warnings, and errors
// OpAdxLogLevelDebug    - Debug, info, warnings, and errors
// OpAdxLogLevelVerbose  - All logs including network request details

Complete Log Output Example

With .debug level enabled, you'll see logs throughout the ad lifecycle:

[11:23:45.123] ℹ️ [OpAdx-Init] 📱 Initializing Opera Ads SDK...
[11:23:45.124] ℹ️ [OpAdx-Init]    Application ID: pub13423013211200/ep13423013211584/app14170937163904
[11:23:45.125] ℹ️ [OpAdx-Init]    iOS App ID: 1444253128
[11:23:45.200] ℹ️ [OpAdx-Init] ✅ SDK initialized successfully
[11:23:45.201] ℹ️ [OpAdx-Init]    SDK Version: 2.9.1.20260408

[11:23:50.100] ℹ️ [OpAdx-Banner] 🎯 [Banner] Loading ad - Placement: s14170965187264, Size: 300x250
[11:23:50.101] ℹ️ [OpAdx-AdLoad] 🔄 Loading ad - Placement: s14170965187264, Auction: regular
[11:23:50.102] 🐛 [OpAdx-Network]    Request ID: req_1234567890
[11:23:50.103] 🐛 [OpAdx-Network]    Format: banner
[11:23:50.104] 🐛 [OpAdx-Network]    Auction Type: regular
[11:23:51.200] 🐛 [OpAdx-Network] ✅ Network request succeeded - HTTP 200, Ads: 1
[11:23:51.201] ℹ️ [OpAdx-AdLoad] ✅ Ad loaded successfully - Placement: s14170965187264
[11:23:51.202] 🐛 [OpAdx-AdLoad]    Ad Type: banner
[11:23:51.203] 🐛 [OpAdx-AdLoad]    Creative ID: cr_9876543210
[11:23:51.204] 🐛 [OpAdx-AdLoad]    eCPM: $0.0150
[11:23:51.205] ℹ️ [OpAdx-Banner] ✅ [Banner] Ad loaded successfully

[11:23:55.100] 🐛 [OpAdx-Banner] [Banner] renderAd: Render current banner ad
[11:23:55.500] ℹ️ [OpAdx-Banner] 👁️ Ad impression - Placement: s14170965187264

[11:24:00.100] ℹ️ [OpAdx-Banner] 👆 Ad clicked - Placement: s14170965187264

Log Tag System

The SDK uses structured log tags to organize logs by component:

Log TagDescriptionWhen It Appears
OpAdx-InitSDK initializationDuring SDK startup
OpAdx-AdLoadAd loading core flowWhen loading any ad format
OpAdx-NetworkNetwork request detailsDuring ad requests and responses
OpAdx-BannerBanner adsBanner lifecycle events
OpAdx-InterstitialInterstitial adsInterstitial lifecycle events
OpAdx-RewardedRewarded adsRewarded ad lifecycle events
OpAdx-NativeNative adsNative ad lifecycle events
OpAdx-AppOpenApp open adsApp open ad lifecycle events
OpAdx-SKAdNetworkSKAdNetworkApp Store attribution events

Error Log Example

When ad loading fails, you'll see detailed error information:

[11:25:00.100] ℹ️ [OpAdx-Banner] 🎯 [Banner] Loading ad - Placement: s14170965187264
[11:25:01.200] ❌ [OpAdx-AdLoad] Ad request failed - Code: 5, Message: NO_FILL
[11:25:01.201] 🐛 [OpAdx-AdLoad]    HTTP Status Code: 204
[11:25:01.202] ❌ [OpAdx-Banner] Ad failed to load - Code: 5, Message: NO_FILL

Custom Logging

You can also use OpAdxLogger for your own application logs:

swift
// Log custom messages
OpAdxLogger.info("User logged in successfully", tag: "MyApp")
OpAdxLogger.debug("Cache size: 25MB", tag: "MyApp")
OpAdxLogger.warning("Approaching storage limit", tag: "MyApp")
OpAdxLogger.logError("Failed to save file", tag: "MyApp")

Production Environment Best Practices

Important Notes:

  • ⚠️ Enable DEBUG or VERBOSE logs only in development and testing
  • Use .info or .error level in production
  • Set log level to .none or .error before releasing
swift
#if DEBUG
    OpAdxLogger.logLevel = .debug  // Development
#else
    OpAdxLogger.logLevel = .error  // Production
#endif

Log Filtering

In Xcode Console, use filtering to quickly locate issues:

  • Filter SDK initialization: Search OpAdx-Init
  • Filter ad loading: Search OpAdx-AdLoad
  • Filter Banner ads: Search OpAdx-Banner
  • Filter errors: Search or ERROR
  • Filter success events: Search

Demo Configuration

Use the following test credentials during development:

Application Configuration

swift
let config = OpAdxSdkInitConfig.create(
    applicationId: "pub13423013211200/ep13423013211584/app14170937163904",
    iOSAppId: "1444253128"
)

Test Placement IDs

Ad FormatPlacement IDVideo Support
Natives14198263063424No
Banners14170965187264No
Banner (Video)s14198605602880Yes
Interstitials14198264979520No
Interstitial (Video)s14198603681728Yes
Rewarded Videos14198592226752Yes
Rewarded Interstitials14496445187904Yes
App Opens14496438551808No

Important Notes:

  • Replace placement IDs with your production IDs before releasing
  • Never use test credentials in production builds

Error Codes

The SDK returns errors through the OpAdxAdError class.

Load Error Codes

CodeNameDescriptionResolution
-1UNKNOWN_ERRORUnknown errorCheck logs for details
1ILLEGAL_API_CALLIllegal call to SDK APIEnsure SDK is initialized before loading ads
2INVALID_PARAMETERInvalid parameterCheck placement ID and other parameters
3ASSETS_ERRORAd assets errorRetry loading; contact support if persistent
4NETWORK_ERRORNetwork connection failedCheck internet connectivity
5NO_FILLNo ad available to showNormal occurrence, try again later
6SDK_INITIALIZATION_ERRORSDK initialization errorVerify Application ID and network access

Show Error Codes

CodeNameDescriptionResolution
101SHOW_AD_REUSEDAd instance has already been shownCreate and load a new ad instance
102SHOW_AD_NOT_FOREGROUNDApp is not in the foregroundOnly show ads when app is active
103SHOW_AD_INVALIDATEDAd has expired or been invalidatedLoad a fresh ad
104SHOW_AD_START_ACTIVITY_ERRORFailed to present ad view controllerEnsure the presenting view controller is valid

Bidding Error Codes

CodeNameDescriptionResolution
201BID_RESP_DEBUGGING_NOT_ALLOWEDBid response debugging not allowedUse production bid responses

Error Handling Example

swift
let listener = OpAdxBannerAdListenerImp(
    onAdLoaded: { bannerAdInfo in
        print("Ad loaded successfully")
    },
    onAdFailedToLoad: { error in
        print("Error Code: \(error.code)")
        print("Error Message: \(error.message)")

        switch error.code {
        case OpAdxAdError.ILLEGAL_API_CALL:
            // SDK not initialized or illegal API usage
            print("Please initialize SDK before loading ads")
        case OpAdxAdError.NO_FILL:
            // No fill - normal occurrence
            print("No ad available, will try again later")
        case OpAdxAdError.NETWORK_ERROR:
            // Network issues
            print("Network issue, retrying in 30 seconds...")
            DispatchQueue.main.asyncAfter(deadline: .now() + 30) {
                self.loadBannerAd()
            }
        default:
            print("Error: \(error.message)")
        }
    }
)

Best Practices

Ad Loading

  1. Preload Ads: Load interstitial and rewarded ads in advance
  2. Check Validity: Always check isAdInvalidated() before showing
  3. Handle No Fill: Implement retry logic with exponential backoff
  4. Limit Frequency: Don't load ads too frequently (respect rate limits)
swift
func loadAdWithRetry(attempt: Int = 0) {
    guard attempt < 3 else {
        print("Max retry attempts reached")
        return
    }

    // Exponential backoff: 1s, 2s, 4s
    let delay = pow(2.0, Double(attempt))

    DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
        self.loadAd()
    }
}

Memory Management

  1. Destroy Ads: Always call destroy() when done with an ad
  2. Weak References: Use [weak self] in closures to avoid retain cycles
  3. Lifecycle Management: Pause/resume banner ads in viewWillDisappear/viewWillAppear
swift
// Destroy banner when view controller is deallocated
deinit {
    bannerAdView?.destroy()
    bannerAdView = nil
}

// Pause/resume banner ads
override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    bannerAdView?.pause()
}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    bannerAdView?.resume()
}

User Experience

  1. Natural Breaks: Show interstitials at natural transition points
  2. Clear Rewards: Clearly communicate rewards before showing rewarded ads
  3. Loading States: Show loading indicators while ads load
  4. Fallback Content: Have alternative content if no ad is available
swift
func showInterstitialAtNaturalBreak() {
    // Good: After level completion
    // Good: After user action (e.g., closing settings)
    // Bad: Mid-gameplay
    // Bad: During active user interaction

    if interstitialAd != nil && !interstitialAd!.isAdInvalidated() {
        showInterstitialAd()
    } else {
        // Fallback: Continue without ad
        proceedToNextScreen()
    }
}

Performance

  1. Main Thread: All SDK APIs must be called on the main thread
  2. Background Loading: SDK handles network calls asynchronously
  3. Resource Cleanup: Remove ads from view hierarchy when destroyed
swift
// ✅ Correct: Call on main thread
DispatchQueue.main.async {
    self.loadBannerAd()
}

// ❌ Wrong: Don't call on background thread
DispatchQueue.global().async {
    self.loadBannerAd()  // May cause crashes
}

Troubleshooting

Issue: Ads Not Loading

Symptoms: onAdFailedToLoad called with NO_FILL error

Solutions:

  1. Check internet connectivity
  2. Verify placement ID is correct
  3. Check if ad inventory is available for your region
  4. Review error logs for specific error codes

Issue: SDK Initialization Failed

Symptoms: SDK initialization callback returns error

Solutions:

  1. Verify Application ID format: pub{}/ep{}/app{}
  2. Check iOS App ID is a valid numeric string
  3. Ensure SDK is initialized before loading ads
  4. Check debug logs for specific error message

Issue: Ads Not Showing

Symptoms: Ad loads successfully but doesn't display

Solutions:

  1. Check if ad has expired: isAdInvalidated()
  2. Ensure view controller is presented (not nil)
  3. Verify ad view is added to view hierarchy
  4. Check Auto Layout constraints
  5. Ensure main thread is used for UI operations

Issue: Crash on Ad Load

Solutions:

  1. Ensure SDK is initialized before loading ads
  2. Check all APIs are called on main thread
  3. Verify placement ID format
  4. Update to latest SDK version
  5. Enable debug logging and check crash logs

Issue: Rewarded Ads Not Granting Rewards

Solutions:

  1. Check onUserRewarded callback is implemented
  2. Verify SSV configuration (if using server-side verification)
  3. Ensure user watches ad completely
  4. Check reward logic implementation
  5. Review SSV callback logs on your server

Migration Guide

From v2.8.x to v2.9.x

Breaking Changes:

  • None

New Features:

  • Enhanced debug logging system
  • Improved bidding support
  • SKAdNetwork 4.0 support

Recommended Actions:

  1. Update pod version to ~> 2.9.1
  2. Enable new logging system during development
  3. Test all ad formats thoroughly

From v2.6.x to v2.7.x

Breaking Changes:

  • Initialization callback signatures changed

Migration Steps:

swift
// Old (v2.6.x)
OpAdxSdkCore.shared.initialize(initConfig: config)

// New (v2.7.x+)
OpAdxSDK.initialize(
    withConfig: config,
    onSuccess: {
        print("SDK initialized")
    },
    onError: { error in
        print("Init failed: \(error)")
    }
)

Support & Resources

Documentation

Contact


Appendix

Minimum SDK Requirements

ComponentMinimum Version
iOS13.0
Xcode14.0
Swift5.0
CocoaPods1.10.0

Third-Party Dependencies

The SDK has no external pod dependencies.

SKAdNetwork Support

The SDK supports SKAdNetwork for ad attribution as a Source App. The SDK automatically handles startImpression / endImpression calls for fullscreen ads (Interstitial, Rewarded, App Open) and Native ads. For Banner ads, attribution is handled via SKOverlay presentation rather than the startImpression / endImpression lifecycle, since banners are continuously displayed views without a distinct dismiss event.

1. Add SKAdNetwork ID to Info.plist (Required)

You must add Opera's SKAdNetworkIdentifier to your app's Info.plist. Without this, the system will silently ignore all attribution for Opera's ad network.

xml
<key>SKAdNetworkItems</key>
<array>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>a2p9lx4jpn.skadnetwork</string>
    </dict>
</array>

Note: If you are already using other ad networks, simply add Opera's identifier to your existing SKAdNetworkItems array.

2. Enable SKAdNetwork in Code (Optional)

SKAdNetwork is enabled by default. You can configure it during initialization:

swift
// SKAdNetwork is enabled by default, disable if needed
OpAdxSDK.setSKAdNetworkEnabled(true)

// Enable debug logging for development
OpAdxSDK.setSKAdNetworkDebugLogEnabled(true)

// Register app for attribution (call once at app launch)
OpAdxSKAdNetworkManager.shared.registerApp()

3. SKOverlay Configuration (Optional)

The SDK can display SKOverlay (in-app App Store overlay) for supported ads:

swift
// Enable/disable SKOverlay (default: true)
OpAdxSKAdNetworkManager.shared.useSKOverlay = true

// Display strategy: .auto (default), .onImpression, .onClick
OpAdxSKAdNetworkManager.shared.overlayDisplayStrategy = .auto
  • auto: Fullscreen ads (interstitial, rewarded, app open) show overlay on impression; non-fullscreen ads (banner, native) show on click
  • onImpression: Always show overlay when ad is displayed
  • onClick: Only show overlay when user clicks the ad

Document Version: 2.9.1 Last Updated: 2026-04-28 SDK Version: 2.9.1