Unit

Configure Banner Ads in iOS

Learn how to integrate, configure, lay out, test, and manage adaptive banner ads in UIKit and SwiftUI iOS apps while handling privacy and failures.

What banner advertising does

A banner ad is a persistent display advertisement shown within part of an app screen. The advertising SDK sends an ad request to an ad service, receives an ad when inventory is available, and renders it inside a banner view.

Banner advertising can create revenue without requiring the user to leave the current screen. The trade-off is that the banner consumes screen space and can distract from controls or content. Treat the banner as part of the layout rather than placing it on top of the interface after the interface has already been designed.

  • Revenue: money earned from advertising activity, usually measured using impressions, clicks, or other provider-specific events.
  • Fill rate: the proportion of ad requests that receive an ad response.
  • Impression: an advertisement display recorded under the provider's measurement rules.
  • Click: a user interaction with the advertisement that may open an advertiser destination.
  • Viewability: whether the ad was sufficiently visible and on screen for the provider to count it.
Banner Types and Sizing Behavior
Banner TypeSizing MethodTypical LocationWhen to Use It
Fixed-sizeUses a predefined width and heightReserved ad slot or legacy layoutWhen the provider and design require a known size
AdaptiveChooses dimensions from the available widthMost modern screen-edge placementsWhen the interface must support different devices
Anchored adaptiveAdaptive size attached to the top or bottom edgeBelow a navigation bar or above a tab barFor persistent screen-level advertising
InlineUses a size suitable for a position in scrolling contentBetween rows, cards, or paragraphsWhen the ad should scroll with the content
Banner Placement Options
PlacementBest Use CaseLayout ConsiderationsPotential UX Risks
Bottom anchoredPersistent content screensPin to the bottom safe area and reserve vertical spaceCan cover tab bars, keyboard input, or home-indicator space
Top anchoredScreens without a prominent top toolbarAccount for the status area, navigation bar, and safe areaCan compete with titles and navigation controls
InlineLong lists and feedsGive the banner its own content item and loading spaceCan interrupt reading or scrolling if inserted too often

Prerequisites and project preparation

You should know basic Swift, Xcode project structure, UIKit view controllers or SwiftUI composition, Auto Layout and safe areas, the iOS app lifecycle, dependency management, and basic App Store privacy concepts. Review iOS access fundamentals if you need a refresher on iOS development concepts.

  1. Choose an ad network or mediation platform that supports iOS.
  2. Create an account and register the app. The platform normally supplies an App ID, which associates the SDK integration with the application.
  3. Create a banner placement. Its ad unit ID identifies the specific location where banner requests are made.
  4. Check the provider's supported iOS versions, Swift requirements, and SDK release notes.
  5. Choose a dependency method. Swift Package Manager is generally the simplest option for a new project; CocoaPods or another provider-supported method may also be available.

Add the SDK with Swift Package Manager

In Xcode, select File > Add Package Dependencies, enter the package repository address supplied by the chosen provider, select a compatible version rule, and add the provider's iOS product to the app target. Do not mix dependency methods for the same SDK unless the provider explicitly supports that arrangement.

Application configuration

Providers commonly require an application identifier in Info.plist. They may also require network configuration, mediation adapter entries, privacy manifest support, or provider-specific settings. Use the exact key and value format from the SDK documentation. A Google Mobile Ads-style configuration, for example, has this representative form:

<key>GADApplicationIdentifier</key>
<string>ca-app-pub-XXXXXXXXXXXXXXXX~YYYYYYYYYY</string>

<key>NSUserTrackingUsageDescription</key>
<string>This identifier helps us provide relevant advertising.</string>

The tracking usage description is required before requesting App Tracking Transparency authorization. It must accurately explain the app's intended use. The ad SDK and any mediation adapters must also satisfy current privacy-manifest and App Store disclosure requirements.

Initialize the advertising SDK

Initialize the SDK once, early in the application lifecycle, and provide the application key if the provider requires one. The exact API differs by SDK. The following UIKit example uses a Google Mobile Ads-style API as a concrete pattern; replace names and identifiers when using another provider.

import GoogleMobileAds

@main
final class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions options: [UIApplication.LaunchOptionsKey: Any]? = nil
    ) -> Bool {
        MobileAds.shared.start { status in
            if let error = status.adapterStatusesByClassName.first(where: {
                $0.value.state == .notReady
            }) {
                print("An ad adapter is not ready: \(error.key)")
            }
        }
        return true
    }
}

Some SDKs complete initialization asynchronously and return an error or adapter status. Store that state if the app needs to decide whether a placement can load. Do not create repeated initialization calls from every view controller. If initialization fails, keep the main content usable, log a non-sensitive diagnostic, and follow the provider's retry guidance.

Create a bottom-anchored UIKit banner

A view controller should own the banner for the duration of the placement. Set its ad unit ID, root or presenting view controller when required, delegate or callback handler, and test-device settings. The test identifier below is a commonly supplied Google test banner ID; use the official test ID for your selected provider.

import UIKit
import GoogleMobileAds

final class ArticleViewController: UIViewController, BannerViewDelegate {
    private let bannerView = BannerView(adSize: AdSizeBanner)
    private var bannerBottomConstraint: NSLayoutConstraint!

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .systemBackground

        bannerView.translatesAutoresizingMaskIntoConstraints = false
        bannerView.adUnitID = "ca-app-pub-3940256099942544/243528117011"
        bannerView.rootViewController = self
        bannerView.delegate = self
        view.addSubview(bannerView)

        bannerBottomConstraint = bannerView.bottomAnchor.constraint(
            equalTo: view.safeAreaLayoutGuide.bottomAnchor
        )
        NSLayoutConstraint.activate([
            bannerView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
            bannerView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
            bannerBottomConstraint
        ])

        let request = Request()
        bannerView.load(request)
    }

    func bannerViewDidReceiveAd(_ bannerView: BannerView) {
        print("Banner loaded")
        // Update content constraints or insets here if the screen reserves space dynamically.
    }

    func bannerView(_ bannerView: BannerView, didFailToReceiveAdWithError error: Error) {
        print("Banner failed: \(error.localizedDescription)")
        // Keep the article usable; do not show an empty blocking container.
    }
}

For a production adaptive banner, calculate the provider's anchored adaptive size from the current safe-area width rather than using AdSizeBanner. The names vary by SDK, but the sequence is consistent: obtain available width, create an anchored adaptive size, assign it, then load the request.

Safe-area and content constraints

Pinning to view.safeAreaLayoutGuide.bottomAnchor avoids the home-indicator region. It does not automatically prevent overlap with a tab bar or custom toolbar. If a tab bar belongs to the same screen, place the banner above that control or incorporate the control's top anchor into the constraint plan.

// Example when the banner must sit above a custom bottom control:
NSLayoutConstraint.activate([
    bannerView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
    bannerView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
    bannerView.bottomAnchor.constraint(equalTo: bottomToolbar.topAnchor)
])

When the ad loads, either reserve the banner's height from the beginning or animate a height constraint from zero to the loaded height. When loading fails, collapse or hide the reserved area so the app does not show an unexplained blank strip.

Adaptive layout during rotation and resizing

Device rotation, iPad split view, multitasking, and trait changes can change the available width. Recalculate an adaptive banner size during a size transition instead of reusing a fixed portrait dimension.

override func viewWillTransition(
    to size: CGSize,
    with coordinator: UIViewControllerTransitionCoordinator
) {
    super.viewWillTransition(to: size, with: coordinator)

    coordinator.animate(alongsideTransition: { _ in
        let width = self.view.safeAreaLayoutGuide.layoutFrame.width
        self.bannerView.adSize = currentAnchoredAdaptiveSize(for: width)
        self.bannerView.load(Request())
        self.view.layoutIfNeeded()
    })
}

currentAnchoredAdaptiveSize represents the selected provider's adaptive-size API; its name and return type are SDK-specific. Avoid reloading on every SwiftUI update or every insignificant layout pass. Reload only when the effective width changes and the provider's policy permits it.

Load requests safely

Create one request for the intended load operation and submit it after SDK initialization and the privacy state are ready.

let request = Request()
// Apply only provider-supported options after checking consent and app policy.
// Examples can include content rating, child-directed treatment,
// and other targeting controls.
bannerView.load(request)
  • Use the provider's test ad unit IDs during development.
  • Register simulator or physical test devices through the SDK's approved test-device mechanism when required.
  • Set content-rating and child-directed treatment options according to the app and audience; do not guess these values.
  • Do not put personal data into request parameters unless the provider, consent state, and legal basis permit it.
  • Do not request a new ad on every appearance callback, state update, or failed frame layout.
  • Allow the provider's normal refresh behavior unless its policy explicitly documents a configurable refresh interval.

Ad lifecycle and event handling

Banner Ad Lifecycle Events
EventMeaningRecommended App Behavior
Initialization completeThe SDK and adapters report readinessPermit requests, or record the failure and keep content available
Load successA banner is availableShow it, update reserved space, and log non-sensitive diagnostics
Load failureNo banner was returnedHide or collapse it and use controlled retry behavior
ImpressionThe provider counted a displayAllow provider measurement; send approved analytics only
Click or presentationThe user interacted and an ad destination may openDo not interfere with the provider's transition
Return to appThe ad destination closed or backgrounded the appRestore app state and avoid duplicate loads

Delegates or callbacks may be called on a particular queue specified by the SDK. Update UIKit and SwiftUI state on the main thread when necessary. A load failure is normal: network access, inventory, configuration, or policy checks can prevent a response.

Failure handling and cleanup

func bannerView(_ bannerView: BannerView, didFailToReceiveAdWithError error: Error) {
    let nsError = error as NSError
    print("domain=\(nsError.domain), code=\(nsError.code)")
    bannerView.isHidden = true
    // Retry later with backoff only if the provider permits it.
}

deinit {
    bannerView.delegate = nil
    bannerView.rootViewController = nil
}

When dismissing a screen, remove observers, clear delegates, and release banner instances that are not reused. If a banner is shared across screens, define one clear owner and do not attach it simultaneously to multiple view hierarchies.

Use a banner from SwiftUI

Many advertising SDKs expose UIKit views. Wrap the banner with UIViewRepresentable, and let the wrapper update only when the available width or relevant configuration changes.

import SwiftUI
import GoogleMobileAds

struct BannerContainer: UIViewRepresentable {
    let adUnitID: String
    let availableWidth: CGFloat

    func makeUIView(context: Context) -> BannerView {
        let banner = BannerView(
            adSize: currentAnchoredAdaptiveSize(for: availableWidth)
        )
        banner.adUnitID = adUnitID
        banner.rootViewController = topViewController()
        banner.delegate = context.coordinator
        banner.load(Request())
        return banner
    }

    func updateUIView(_ banner: BannerView, context: Context) {
        guard banner.adSize != currentAnchoredAdaptiveSize(for: availableWidth) else {
            return
        }
        banner.adSize = currentAnchoredAdaptiveSize(for: availableWidth)
        banner.load(Request())
    }

    func makeCoordinator() -> Coordinator { Coordinator() }
    final class Coordinator: NSObject, BannerViewDelegate { }
}

The helper functions in this example stand for your provider's adaptive-size and view-controller lookup APIs. In a real SwiftUI screen, measure the actual available width with a layout tool such as GeometryReader, apply a minimum valid width, and ensure the banner has an explicit vertical placement. Do not trigger a load merely because SwiftUI recomputed the body.

Privacy, consent, and compliance

App Tracking Transparency is Apple's permission framework for tracking users across apps and websites. If the app or an SDK performs tracking as defined by Apple's rules, add the required usage description and request authorization at an appropriate point in the user experience. A permission prompt must not be used as a substitute for a consent notice.

For applicable privacy regulations, show the required consent flow before enabling personalized advertising or transmitting data that requires consent. Determine the user's consent state first, configure the SDK with that state, and then request ads. If consent is denied or unavailable, use the provider's non-personalized or restricted mode where supported.

  • Audit the advertising SDK and mediation adapters for privacy-manifest requirements.
  • Keep App Store privacy disclosures consistent with actual SDK data collection and sharing.
  • Apply age-appropriate ad settings and content ratings.
  • Do not collect, log, or target with personal data before the required authorization or consent.
  • Re-check consent when the user changes privacy choices.

Privacy-aware request flow

func prepareAdsThenLoad() {
    consentManager.determineStatus { status in
        trackingManager.requestAuthorizationIfAppropriate {
            configureProvider(for: status)
            DispatchQueue.main.async {
                self.bannerView.load(Request())
            }
        }
    }
}

The consent manager and tracking manager above are application components, not universal SDK APIs. The important ordering is to determine applicable consent and authorization, configure the provider, then request the banner.

Testing and release validation

Development Versus Production Configuration
SettingDevelopmentProductionReason
Ad unit IDProvider test IDRegistered production banner IDPrevents invalid test traffic and accidental clicks
Test devicesSimulator and approved physical devicesNormal users; no test modeLimits test behavior to development
LoggingDetailed SDK and layout diagnosticsLimited, privacy-safe diagnosticsAvoids exposing identifiers or user data
Consent dataControlled test statesReal consent and privacy choicesValidates policy behavior
Retry behaviorShort, controlled test intervalsProvider-compliant backoff and refreshAvoids excessive requests
  1. Test on the simulator for layout, but also test on physical devices for network, permission, and SDK behavior.
  2. Check small and large iPhones, iPad widths, portrait and landscape orientations, safe-area insets, and split-screen resizing.
  3. Verify that content remains usable when the banner is hidden or fails to load.
  4. Disable network access and test timeouts, empty inventory, and return-to-app behavior.
  5. Use only test ads while developing. Never click production ads or generate artificial impressions.
  6. Before release, replace test IDs and test-device settings with production configuration, then verify the registered App ID, ad unit, consent behavior, and privacy disclosures.

Common integration failures

Common Integration Failures
SymptomLikely CauseHow to DiagnoseResolution
Banner does not appearInvalid ID, uninitialized SDK, missing view, zero-size constraints, no inventory, or no networkInspect callbacks, identifiers, initialization logs, view hierarchy, and constraintsUse test IDs, initialize once, add the view visibly, and fix size or network issues
Banner overlaps controlsScreen-edge constraint or no reserved content spaceInspect safe-area, tab-bar, toolbar, and keyboard geometryUse safe-area or control-relative anchors and update content insets
Wrong size after rotationFixed dimensions or stale adaptive widthLog available width during size transitionsRecalculate size and reload only when the effective width changes
Works in development but not releaseTest settings, incorrect production IDs, consent differences, or unpropagated registrationCompare release configuration and platform dashboard statusCorrect production values and validate privacy and registration status
Privacy review is incompleteMissing tracking description, consent, privacy manifest, or audience settingsAudit SDK documentation, manifests, disclosures, and runtime behaviorComplete the privacy flow and use age-appropriate settings
Repeated loads hurt performanceLoads from every update or immediate retry loopsCount banner instances and request callsUse one owner, controlled retries, and provider-compliant refresh

Exam-relevant checklist

  • Know that an App ID identifies the application while an ad unit ID identifies a particular placement.
  • Know that an adaptive banner uses the current available width; a fixed banner does not.
  • Anchor banners to safe areas and reserve content space to prevent overlap.
  • Initialize the SDK before submitting requests.
  • Use test ads and approved test devices during development.
  • Handle both success and failure callbacks without making the app depend on ad availability.
  • Determine consent and tracking authorization before enabling behavior that requires them.
  • Remove delegates and observers when a screen or banner is destroyed.