Add IAB Standard Size Experiences to an iOS app

Show IAB banner, medium rectangle, half-page, interstitial, and collapsible ads in an iOS app with the IAB Standard Size Experience SDK 0.0.6. You can also serve ads from Pangle, Meta, and Google Ad Manager by adding their optional modules.

You add a Swift package, initialize it with your brand's API key, and place a SwiftUI view that carries a tag ID. The tag identifies an ad placement set up in your Business Account, so campaigns and creatives change without an app update.

What you'll add

ProductImportUse it for
GenuinSDKimport GenuinSDKInitializing the SDK (required)
GenuinInStreamAdsimport GenuinInStreamAdsThe six ad views (required)
GenuinPangleAdsimport GenuinPangleAdsPangle ads (optional)
GenuinMetaAdsimport GenuinMetaAdsMeta Audience Network ads (optional)
GenuinGMAAdsimport GenuinGMAAdsGoogle Ad Manager ads (optional)

Requirements

Minimum
iOS16.0
Xcode26 or later
DevicesiPhone and iPad
Package managerSwift Package Manager
UISwiftUI. UIKit apps host the views in a UIHostingController.
PlatformsiOS only

You also need an API key and a tag ID from your Genuin account. See Step 5.

Step 1: Add the Genuin package

  1. In Xcode, go to File > Add Package Dependencies.
  2. Enter the repository URL https://github.com/genuininc/ios_sdk.
  3. Set Dependency Rule to Exact Version and enter 0.0.6, the latest release.
  4. Click Add Package.
  5. Select GenuinSDK and GenuinInStreamAds, plus the product for each ad network you want: GenuinPangleAds, GenuinMetaAds, or GenuinGMAAds. Assign them to your app target and click Add Package.

Step 2: Add the Google IMA package

GenuinInStreamAds needs Google's Interactive Media Ads (IMA) package, which a binary Swift package can't add for you. Without it the app crashes at launch with Library not loaded: @rpath/GoogleInteractiveMediaAds.framework.

  1. Go to File > Add Package Dependencies again.
  2. Enter https://github.com/googleads/swift-package-manager-google-interactive-media-ads-ios.
  3. Set Dependency Rule to Branch and enter main.
  4. Add the GoogleInteractiveMediaAds product to your app target.

Don't add the Google Mobile Ads package yourself. If you use Google Ad Manager ads, GenuinGMAAds already includes it.

Step 3: Add ad networks (optional)

Skip this step if you only need Genuin ads. Each ad network is a separate, optional module, so apps that don't use it don't carry it. Choose a network to see how to add it:

Each network's page covers its package, its Info.plist keys, and the module to pass in Step 6. Ask your Genuin team to enable a network for your tag IDs.

Step 4: Configure Info.plist and tracking

The SDK reads the App Tracking Transparency (ATT) status for ad measurement, but it never shows the ATT prompt. Add the usage description and request authorization yourself, before the first ad view appears:

Info.plist
xml
<key>NSUserTrackingUsageDescription</key>
<string>We use your data to show you more relevant ads.</string>
Tracking prompt
swift
import AppTrackingTransparency

ATTrackingManager.requestTrackingAuthorization { _ in }

Without authorization, ads still serve but aren't personalized. Ad assets load over HTTPS, so App Transport Security needs no changes.

Step 5: Get your credentials

CredentialPurposeWhere to get it
API keyAuthenticates your app. Passed once to initialize.Business Account > Build > Publish Brand Community > SDK Integration. The Live and QA environments each have their own key.
Tag IDIdentifies one ad slot and its campaigns. Passed to each ad view.The ID of an IAB Standard Tag created in your Business Account under Grow > Off Site > Extended > IAB Standard Tag. Your Genuin team passes it to you.

Keep the API key out of source control, for example in an .xcconfig file or your CI secrets.

Step 6: Initialize the SDK

Call Genuin.shared.initialize once at launch and pass every module you use. Adding a product isn't enough: a module you don't pass isn't registered, and its ads are skipped silently. Without BGInStreamAds.module, every ad view fails with BGTagError.adsManagerUnavailable.

MyApp.swift
swift
import SwiftUI
import GenuinSDK
import GenuinInStreamAds
// Also import GenuinPangleAds, GenuinMetaAds, or GenuinGMAAds for each ad network you use

@main
struct MyApp: App {
    init() {
        Genuin.shared.initialize(
            modules: [
                BGInStreamAds.module
                // Add BGPangleAds.module, BGMetaAds.module, or BGGMAAds.module for each ad network you use
            ],
            apiKey: "<<YOUR_API_KEY>>"
        ) { result in
            if case .failure(let error) = result { print("Genuin init failed: \(error)") }
        }
    }

    var body: some Scene {
        WindowGroup { ContentView() }
    }
}

In a UIKit app, make the same call in application(_:didFinishLaunchingWithOptions:).

Initialization parameters

ParameterRequiredDescription
modulesYesThe modules to register: BGInStreamAds.module, plus the module of each ad network you use (BGPangleAds.module, BGMetaAds.module, or BGGMAAds.module).
apiKeyYesYour brand's API key for the environment.
configNoenvironment is .prod (default) or .qa. navigationStyle is .system (default), .custom, or .hidden.
completionNoCalled once initialization succeeds or fails.

Note: A QA key only works with environment: .qa. Don't ship a build that points at QA; the two environments have separate brands, tags, and campaigns.

Step 7: Display an ad

Each ad view is a SwiftUI view. Wrap it in BGNavigationRoot and pass the tag ID:

AdView.swift
swift
import SwiftUI
import GenuinInStreamAds
import Core

struct ContentView: View {
    var body: some View {
        BGNavigationRoot {
            BG320x50AdView(tagID: "{{TAG_ID}}")
        }
        .padding()
    }
}

The view loads as soon as it appears and sets its own height. Give it at least the slot's width: 320 points for the banners and interstitial, 300 points for the medium rectangle and half page. You don't set a frame.

Ad viewSize (points)Description
BG320x50AdView320 × 50Compact single-row banner
BG320x100AdView320 × 100Large banner
BG300x250AdView300 × 250Medium rectangle
BGCollapsibleAdView300 × 250, collapsing to a rowCollapses after playback or when the user taps the chevron
BG320x480AdView320 × 480Mobile interstitial
BG300x600AdView300 × 600Half page

All six take a tagID and an optional delegate.

Host an ad view in UIKit

Wrap the view in a UIHostingController and add it as a child:

UIKit host
swift
let hosting = UIHostingController(rootView: BGNavigationRoot { BG300x250AdView(tagID: "{{TAG_ID}}") })
addChild(hosting)
hosting.view.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(hosting.view)
NSLayoutConstraint.activate([
    hosting.view.leadingAnchor.constraint(equalTo: view.leadingAnchor),
    hosting.view.trailingAnchor.constraint(equalTo: view.trailingAnchor),
    hosting.view.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
])
hosting.didMove(toParent: self)

Step 8: Observe lifecycle events

Pass an object that conforms to BGAdDelegate to react to loading, playback, and taps. Every method is optional. Keep a strong reference to the object, because the view doesn't own its delegate.

AdTracker.swift
swift
import GenuinInStreamAds
import _FeedCore

final class AdTracker: BGAdDelegate {
    func iabAdUnitDidLoad(_ unit: BGAdUnitInfo, mediaCount: Int) {
        print("Loaded \(mediaCount) item(s)")
    }
    func iabAdUnitDidReceiveNoAds(_ unit: BGAdUnitInfo) { /* hide or resize the slot */ }
    func iabAdUnitDidFailToLoad(_ unit: BGAdUnitInfo, error: any Error) { print("Ad failed: \(error)") }
    func iabAdCTATapped(_ mediaItem: BGMediaInfo, url: URL) { print("CTA tapped: \(url)") }
}
ContentView.swift
swift
struct ContentView: View {
    @State private var tracker = AdTracker()

    var body: some View {
        BGNavigationRoot {
            BG300x250AdView(tagID: "{{TAG_ID}}", delegate: tracker)
        }
    }
}
MethodFires when
iabAdUnitDidLoad(_:mediaCount:)The unit has ads to show
iabAdUnitDidReceiveNoAds(_:)The unit resolved but has no ads
iabAdUnitDidFailToLoad(_:error:)Loading failed. The error is a BGTagError for tag problems.
iabAdMediaDidStart(_:)An ad started playing
iabAdAllMediaDidComplete(_:)The unit played through once
iabAdCTATapped(_:url:)The user tapped the call to action
iabAdDidEnterFullscreen(_:), iabAdDidExitFullscreen(_:)Full-screen playback opened or closed
iabAdDidCollapse(_:reason:), iabAdDidExpand(_:)A collapsible unit collapsed or expanded

BGAdDelegate has more callbacks than these. When a unit fails or has no ads, it keeps its size and shows a placeholder; to reclaim the space, hide the slot from iabAdUnitDidReceiveNoAds or iabAdUnitDidFailToLoad.

Troubleshooting

SymptomCauseFix
The app crashes at launch with Library not loaded: @rpath/GoogleInteractiveMediaAds.frameworkThe Google IMA package isn't linked to the app targetComplete Step 2.
Every slot shows the placeholder and reports .adsManagerUnavailableinitialize was called without BGInStreamAds.module, or after the first ad view appearedPass the module and initialize at launch.
No ad network ads appearThe network's module isn't passed to initialize, the network isn't enabled for your tag, or its setup is incompleteFollow the network's page (Step 3), check each step, and ask your Genuin team to enable the network for your tag IDs.
.invalidTagIDThe tag ID is empty or malformedPass the tag ID exactly as your Genuin team provided it.
iabAdUnitDidReceiveNoAds fires for a valid tagThe tag has no active campaign, or the key belongs to the other environmentCheck the tag in your Business Account and match the environment to the key.
Build error: no such module GenuinSDK, GenuinInStreamAds, _FeedCore, or CoreA product isn't added to the app target, the deployment target is below iOS 16, or a shared module isn't importedAdd the products to the target, set iOS 16.0 or later, and add import _FeedCore for BGAdDelegate and import Core for BGNavigationRoot.
The ad plays but isn't personalizedATT authorization wasn't requested or was deniedRequest authorization before the first ad view (Step 4).

Limitations

  • iOS 16 and later, iOS only: There's no macOS or Mac Catalyst support.
  • SwiftUI first: UIKit apps host each slot in a UIHostingController.
  • Google IMA is yours to add: Every app adds the Google IMA package itself.
  • Ad networks are optional: Each one has its own setup page (Step 3).
  • Six fixed sizes: There's no flexible or landscape view yet.
  • Tag-only delivery: Every ad comes from a tag ID managed in your Business Account.
  • Pre-1.0 versioning: Releases are 0.0.x. Pin an exact version, because 0.x releases can change the API.

See also

TRUST AND COMPLIANCE

© 2026 Genuin Inc.

Genuin Footer