Skip to content

iOS SDK ​

The ADBNK iOS SDK serves ads in native iOS apps. Its API is modeled on Google Mobile Ads (AdMob): you'll find AdRequest, FullScreenContentCallback, a reward listener and the other familiar pieces.

Version: the version of the SDK package you received.

Requirements ​

ItemRequirement
iOS12.0+
Swift5.0+
FrameworksLinked automatically. ATT and StoreKit are weak-linked, so the SDK still runs on iOS 12.

Each placement also needs a zone ID. To get one, create an App SDK zone in the publisher console, open Zones, and click Get code.

Installation ​

The SDK is delivered as a signed binary AdbnkSDK.xcframework. To get the SDK package, contact your ADBNK account manager.

  1. Drag AdbnkSDK.xcframework into your Xcode project and add it to your app target.
  2. In the target's General → Frameworks, Libraries, and Embedded Content, set it to Embed & Sign.
  3. Make sure the target's minimum deployment version is iOS 12.0 or later.

The system frameworks the SDK uses are linked automatically.

The SDK's PrivacyInfo.xcprivacy privacy manifest is embedded in the xcframework, and Xcode merges it into your app's privacy report automatically.

Initialization ​

Initialize the SDK once at launch, before you load any ad:

swift
import AdbnkSDK

func application(_ application: UIApplication,
                 didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    AdbnkSDK.shared.initialize(
        appId: Bundle.main.bundleIdentifier ?? "your.app.id"    // your app identifier
    )
    return true
}

WARNING

Loading an ad before initialize is a programming error and stops the app at a precondition. Always initialize first.

AdbnkConfig fields (all optional):

FieldDefaultDescription
testModefalseSee Test mode
gdprConsentnilGDPR consent. nil means unknown and is treated as not consented. See Privacy
coppaCompliancefalseTreats every request as child-directed

AdbnkSDK.shared also exposes getAppId(), getConfig(), updateConfig(_:), setGDPRConsent(_:), setCOPPACompliance(_:), setTestMode(_:) and setIdfaSyncEnabled(_:).

AdRequest ​

Every load method takes an optional AdRequest. Each field is optional too.

swift
let request = AdRequest.Builder()
    .addKeyword("sports")
    .setContentUrl("https://example.com/article/123")
    .setNonPersonalizedAds(false)
    .setTagForChildDirected(nil)          // true / false / nil = unspecified
    .setTagForUnderAgeOfConsent(nil)
    .putExtra("placement", "home_feed")
    .build()

AdRequest.default() returns a request with every field left at its default.

Ad formats ​

FormatClassStyle
BannerBannerAdViewA UIView in your layout
Float banner (pinned to the top or bottom)FloatBannerAdOverlay window
NativeNativeAdYou render the assets yourself
InterstitialInterstitialAdFull screen
RewardedRewardedAdFull screen, with reward
Rewarded interstitialRewardedInterstitialAdFull screen, with reward
SplashSplashAdFull screen at launch
App openAppOpenAdFull screen when the app returns to the foreground
PopupPopupAdDialog-style overlay

Use a zone whose format matches the class you load.

Full-screen formats: shared pattern ​

Interstitial, rewarded, rewarded interstitial, splash, app open and popup ads all work the same way:

  1. Call XxxAd.load(zoneId:request:completion:). request defaults to nil.
  2. Attach a FullScreenContentCallback with setFullScreenContentCallback(_:).
  3. Call show(from: viewController).

Each ad object can be shown once, and isReady() turns false after it is shown or once it expires. Load a new ad for every impression.

swift
public protocol FullScreenContentCallback: AnyObject {
    func onAdShowedFullScreenContent()
    func onAdDismissedFullScreenContent()
    func onAdFailedToShowFullScreenContent(_ error: AdError)
    func onAdImpression()
    func onAdClicked()
}   // every method has a default empty implementation

Keep strong references

The SDK holds fullScreenContentCallback and adListener weakly. Keep both the ad object and its callback or listener object alive, for example as properties of your view controller, until the ad is dismissed.

Interstitial ​

swift
import AdbnkSDK

final class GameViewController: UIViewController, FullScreenContentCallback {
    private var interstitial: InterstitialAd?

    func loadInterstitial() {
        InterstitialAd.load(zoneId: "YOUR_ZONE_ID") { [weak self] ad, error in
            guard let self = self, let ad = ad else { return }
            ad.setFullScreenContentCallback(self)
            self.interstitial = ad
        }
    }

    func showInterstitial() {
        guard let ad = interstitial, ad.isReady() else { return }
        ad.show(from: self)
    }

    func onAdDismissedFullScreenContent() {
        interstitial = nil
        loadInterstitial()            // preload the next one
    }

    func onAdFailedToShowFullScreenContent(_ error: AdError) {
        interstitial = nil
    }
}

There is also an AdMob-style generic overload: load(zoneId:adRequest:callback:). It takes any object that conforms to AdLoadCallback with Ad set to the matching ad class.

Rewarded and rewarded interstitial ​

RewardedAd and RewardedInterstitialAd share the same API. Grant the reward inside the reward listener. The SDK calls it at most once per ad.

swift
private var rewardedAd: RewardedAd?

func loadRewarded() {
    RewardedAd.load(zoneId: "YOUR_ZONE_ID") { [weak self] ad, error in
        guard let self = self, let ad = ad else { return }
        ad.setOnUserEarnedRewardListener { reward in
            self.grantReward(amount: reward.amount, type: reward.type)
        }
        ad.setFullScreenContentCallback(self)
        self.rewardedAd = ad
    }
}

func showRewarded() {
    guard let ad = rewardedAd, ad.isReady() else { return }
    ad.show(from: self)
}

You set the reward amount and type on the zone in the publisher console. They reach the listener as RewardItem(amount: Int, type: String).

Splash ​

Load the splash ad early in launch. Show it once it loads, then move on to your main UI when it is dismissed or fails.

swift
SplashAd.load(zoneId: "YOUR_ZONE_ID") { [weak self] ad, error in
    guard let self = self else { return }
    guard let ad = ad else { self.goToMain(); return }
    self.splashAd = ad
    ad.setFullScreenContentCallback(self)   // call goToMain() in onAdDismissed / onAdFailedToShow
    ad.show(from: self)
}

The splash ad shows a countdown with a skip button.

App open ​

You can load and show it manually, the same way as an interstitial:

swift
AppOpenAd.load(zoneId: "YOUR_ZONE_ID") { ad, _ in self.appOpenAd = ad }
// later:
if let ad = appOpenAd, ad.isReady() { ad.show(from: rootViewController) }

Or let the SDK handle it. Call setup once after initialize, and the SDK preloads an ad and shows it each time the app becomes active:

swift
AppOpenAd.setup(zoneId: "YOUR_ZONE_ID")
swift
PopupAd.load(zoneId: "YOUR_ZONE_ID") { [weak self] ad, _ in
    guard let self = self, let ad = ad else { return }
    self.popupAd = ad
    ad.show(from: self)
}
swift
final class FeedViewController: UIViewController, BannerAdListener {
    private let banner = BannerAdView(frame: CGRect(x: 0, y: 0, width: 320, height: 50))

    override func viewDidLoad() {
        super.viewDidLoad()
        banner.zoneId = "YOUR_ZONE_ID"
        banner.bannerSize = .banner           // 320x50
        banner.adListener = self              // weak reference
        view.addSubview(banner)
        banner.loadAd()
    }

    override func viewWillAppear(_ animated: Bool)    { super.viewWillAppear(animated); banner.resume() }
    override func viewWillDisappear(_ animated: Bool) { banner.pause(); super.viewWillDisappear(animated) }
    deinit { banner.destroy() }

    func onAdLoaded() {}
    func onAdFailedToLoad(_ error: AdError) {}
    func onAdImpression() {}
    func onAdClicked() {}
}

BannerSize values: .banner (320×50), .largeBanner (320×100), .mediumRectangle (300×250), .fullBanner (468×60), .leaderboard (728×90) and .adaptive. Pick the one that matches your zone, and give the view a frame or constraints of that size.

Auto-refresh uses the interval set on the zone in the console. If the zone has none, the refreshInterval property applies (in seconds; 0 turns refresh off).

Float banner ​

FloatBannerAd floats in its own window at the top or bottom of the screen, so it takes up no layout space. It shows itself as soon as it loads.

swift
let floatBanner = FloatBannerAd()
floatBanner.zoneId = "YOUR_ZONE_ID"
floatBanner.position = .bottom
floatBanner.showCloseButton = true
floatBanner.margin = 0
floatBanner.autoHideAfter = 0           // seconds, 0 = never
floatBanner.adListener = self           // weak reference
floatBanner.loadAd()

// floatBanner.hide() / show() / isCurrentlyShowing() / isCurrentlyLoaded()
// floatBanner.pause() / resume() / destroy()

Keep a strong reference to floatBanner for as long as it should stay on screen.

Native ​

The SDK returns the native ad's assets and you lay them out in your own views:

swift
final class FeedCell: UITableViewCell, NativeAdListener {
    private var nativeAd: NativeAd?

    func loadAd() {
        NativeAd.load(zoneId: "YOUR_ZONE_ID") { [weak self] ad, error in
            guard let self = self, let ad = ad else { return }
            self.nativeAd = ad
            self.titleLabel.text = ad.getHeadline()
            self.bodyLabel.text = ad.getBody()
            self.ctaButton.setTitle(ad.getCallToAction(), for: .normal)
            self.sponsoredLabel.text = ad.getSponsoredLabel()   // always show an ad label
            ad.loadIcon { image in self.iconView.image = image }
            ad.loadMainImage { image in self.mainImageView.image = image }
            ad.setListener(self)

            // Required: lets the SDK measure impressions and handle clicks
            ad.registerViewForInteraction(container: self.contentView,
                                          clickableViews: [self.ctaButton, self.mainImageView])
        }
    }

    override func prepareForReuse() {
        super.prepareForReuse()
        nativeAd?.destroy()
        nativeAd = nil
    }

    func onAdClicked() {}
    func onAdImpression() {}
}
MethodContent
getHeadline()Title
getBody()Description
getCallToAction()Button text
getAdvertiser()Advertiser or sponsor
getIconUrl() / loadIcon(completion:)Icon
getMainImageUrl() / loadMainImage(completion:)Main image
getRating()Rating from 1 to 5 (optional)
getPrice()Price (optional)
getSponsoredLabel()Ad label text
getAssets()All assets as NativeAdAssets

If clickableViews is empty, the whole container is clickable. If you can't use registerViewForInteraction, call recordClick() only from a real user tap on the ad.

Click handling ​

Clicks need no code from you. The SDK records the click, then opens the ad's app deep link or universal link if there is one. If that can't be opened, it opens the landing page.

Privacy and compliance ​

The SDK never shows a consent prompt or the ATT dialog itself. Your app decides when to ask.

App Tracking Transparency (ATT)

  • To use the IDFA for personalized ads and attribution, request authorization yourself at a moment that makes sense in your app, and add NSUserTrackingUsageDescription to Info.plist.
  • If the user doesn't grant authorization, the SDK neither reads nor sends the IDFA. Ads still serve normally.
  • To keep the SDK from using the IDFA even after the user authorizes it, call AdbnkSDK.shared.setIdfaSyncEnabled(false).
swift
import AppTrackingTransparency

if #available(iOS 14, *) {
    ATTrackingManager.requestTrackingAuthorization { _ in }
}

GDPR (EEA and UK users). Until you set it, consent is unknown and the SDK treats it as not consented. Collect consent with your CMP, then pass the result (true or false) to the SDK before you load ads:

swift
AdbnkSDK.shared.setGDPRConsent(userConsented)

Non-personalized ads. Use AdRequest.Builder().setNonPersonalizedAds(true).

COPPA and child-directed apps:

swift
AdbnkSDK.shared.setCOPPACompliance(true)                          // whole app
AdRequest.Builder().setTagForChildDirected(true).build()          // per request
AdRequest.Builder().setTagForUnderAgeOfConsent(true).build()      // under age of consent

When consent is withheld, or for child-directed or non-personalized requests, the SDK does not use the IDFA or other advertising identifiers. Limited technical data is still processed to keep traffic safe.

App Store privacy labels. The SDK ships its own privacy manifest. Use it, together with your own data use, to fill in your App Privacy answers.

Test mode ​

  • testMode / setTestMode(true) marks requests as test traffic. ADBNK doesn't yet serve dedicated test creatives, so the ads you see during development are live. Don't click ads over and over on your own devices.
  • The SDK handles traffic-quality protection automatically. There is nothing to configure.

Error codes ​

AdError conforms to Swift Error and has code and message.

CodeMeaning
1001Zone ID is empty or invalid
1002No fill: no ad available right now. Retry later, and don't retry in a tight loop
1003Network error
1004Internal error
1005Ad expired or isn't ready. Load a new one
1006This ad object has already been shown
1007A load is already in progress
1008This SDK version doesn't support the zone's ad format

FAQ ​

Every request returns 1002. Check three things: you copied the zone ID from Get code, the zone is an App SDK zone whose format matches the class you're loading, and the zone is active.

Callbacks never fire. The callback or listener object has most likely been deallocated, because the SDK only holds it weakly. Store it in a property.

Can I keep using the listener: parameter of show(from:listener:)? Yes. The legacy FullScreenAdListener and RewardedAdListener protocols still work but are deprecated. Prefer FullScreenContentCallback and setOnUserEarnedRewardListener.

What should I send support? Every full-screen ad has getResponseInfo().responseId. Include it when you contact support.

Documentation released under the MIT License.