Banner Ads

Banner ads are rectangular ads that occupy a portion of your app's layout. They can refresh automatically and stay on screen while users interact with your app.

Each ad format uses a Zone ID to identify the ad placement. Zone IDs are configured in the Empower dashboard.

Note: All ad status listeners are optional. The SDK handles ad loading and display automatically. Use listeners only if you need to track ad states for analytics, UI updates, or custom logic.


Quick Start

import EmpowerMobileAds
class ViewController: UIViewController, AdStatusDelegate {
@IBOutlet weak var bannerContainer: UIView!
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
loadBanner()
}
func loadBanner() {
EMAManager.shared.loadBannerAd(
viewController: self,
zoneId: "YOUR_BANNER_ZONE_ID",
bannerContainer: bannerContainer,
delegate: self
)
}
func bannerStatusChanged(_ manager: EmpowerBannerManager) {
switch manager.status {
case .ready:
print("Banner is ready and displayed")
case .failed:
print("Banner failed to load")
case .initializing:
print("Banner is loading...")
default:
break
}
}
}

Supported Sizes

SizeDescription
320x50Standard Banner
320x100Large Banner
300x250Medium Rectangle

Container Setup

Interface Builder (Storyboard)

  1. Add a UIView to your view controller
  2. Set constraints for position and height
  3. Connect the outlet to your view controller

Programmatic Setup

// Standard Banner (320x50)
let bannerContainer = UIView()
bannerContainer.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(bannerContainer)
NSLayoutConstraint.activate([
bannerContainer.leadingAnchor.constraint(equalTo: view.leadingAnchor),
bannerContainer.trailingAnchor.constraint(equalTo: view.trailingAnchor),
bannerContainer.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
bannerContainer.heightAnchor.constraint(equalToConstant: 50)
])
// MREC (300x250)
let mrecContainer = UIView()
mrecContainer.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(mrecContainer)
NSLayoutConstraint.activate([
mrecContainer.centerXAnchor.constraint(equalTo: view.centerXAnchor),
mrecContainer.topAnchor.constraint(equalTo: someView.bottomAnchor, constant: 16),
mrecContainer.widthAnchor.constraint(equalToConstant: 300),
mrecContainer.heightAnchor.constraint(equalToConstant: 250)
])

Loading Options

Basic Loading

EMAManager.shared.loadBannerAd(
viewController: self,
zoneId: "YOUR_ZONE_ID",
bannerContainer: bannerContainer,
delegate: self
)

With Keywords

EMAManager.shared.loadBannerAd(
viewController: self,
zoneId: "YOUR_ZONE_ID",
bannerContainer: bannerContainer,
delegate: self,
keywords: "sports,football,news"
)

With Custom Parameters

let customParams: [String: [String]] = [
"article_id": ["12345"],
"section": ["sports"],
"author": ["john_doe"]
]
EMAManager.shared.loadBannerAd(
viewController: self,
zoneId: "YOUR_ZONE_ID",
bannerContainer: bannerContainer,
delegate: self,
adConfiguration: nil,
customParameters: customParams,
category: "sports"
)

Status Handling

AdStatusDelegate

extension ViewController: AdStatusDelegate {
func bannerStatusChanged(_ manager: EmpowerBannerManager) {
let zoneId = manager.bannerModel?.adConstraints.zoneId ?? ""
switch manager.status {
case .initializing:
// Banner is loading
showLoadingIndicator()
case .ready:
// Banner is displayed
hideLoadingIndicator()
print("Banner loaded for zone: \(zoneId)")
case .failed:
// Banner failed to load
hideLoadingIndicator()
hideBannerContainer()
print("Banner failed for zone: \(zoneId)")
default:
break
}
}
// Optional: Track loading progress
func bannerLoadingProgress(loaded: Int, total: Int, fastestAdId: String?) {
print("Loading: \(loaded)/\(total) ad sources")
}
}

Status Values

StatusDescription
.initializingBanner is loading
.readyBanner is displayed
.failedBanner failed to load
.undefinedInitial/destroyed state

SwiftUI Integration

import SwiftUI
import EmpowerMobileAds
// MARK: - Banner View
struct BannerAdView: UIViewControllerRepresentable {
let zoneId: String
let height: CGFloat
func makeUIViewController(context: Context) -> BannerAdViewController {
return BannerAdViewController(zoneId: zoneId)
}
func updateUIViewController(_ uiViewController: BannerAdViewController, context: Context) {}
}
// MARK: - Banner View Controller
class BannerAdViewController: UIViewController, AdStatusDelegate {
private let zoneId: String
private var bannerContainer: UIView!
init(zoneId: String) {
self.zoneId = zoneId
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
setupContainer()
loadBanner()
}
private func setupContainer() {
bannerContainer = UIView()
bannerContainer.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(bannerContainer)
NSLayoutConstraint.activate([
bannerContainer.leadingAnchor.constraint(equalTo: view.leadingAnchor),
bannerContainer.trailingAnchor.constraint(equalTo: view.trailingAnchor),
bannerContainer.topAnchor.constraint(equalTo: view.topAnchor),
bannerContainer.bottomAnchor.constraint(equalTo: view.bottomAnchor)
])
}
private func loadBanner() {
EMAManager.shared.loadBannerAd(
viewController: self,
zoneId: zoneId,
bannerContainer: bannerContainer,
delegate: self
)
}
func bannerStatusChanged(_ manager: EmpowerBannerManager) {
// Handle status changes
}
}
// MARK: - Usage
struct ContentView: View {
var body: some View {
VStack {
Text("Your Content")
Spacer()
// Standard Banner
BannerAdView(zoneId: "YOUR_BANNER_ZONE_ID", height: 50)
.frame(height: 50)
}
}
}
struct ArticleView: View {
var body: some View {
ScrollView {
VStack {
Text("Article Title")
.font(.title)
// MREC in content
BannerAdView(zoneId: "YOUR_MREC_ZONE_ID", height: 250)
.frame(height: 250)
Text("Article content...")
}
}
}
}

Lifecycle Management

Visibility Handling

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Resume banner refresh timer
EMAManager.shared.visible(viewController: self)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// Destroy banner if leaving permanently
if isMovingFromParent || isBeingDismissed {
EMAManager.shared.destroy(controllerIdentifier: self.hash)
}
}

Tab Bar Navigation

When using tab bar controllers, banners automatically pause on inactive tabs:

class TabBarController: UITabBarController, UITabBarControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
delegate = self
}
func tabBarController(_ tabBarController: UITabBarController,
didSelect viewController: UIViewController) {
// Notify SDK of visible tab
EMAManager.shared.visible(viewController: viewController)
}
}

Auto-Refresh

Banner ads automatically refresh based on server configuration. The SDK handles:

  • Pausing refresh when view is not visible
  • Pausing refresh when app is in background
  • Resuming refresh when view becomes visible again

You don't need to manually reload banners for refresh - it's automatic.


Best Practices

1. Container Size

Always set explicit height constraints:

// Good
bannerContainer.heightAnchor.constraint(equalToConstant: 50).isActive = true
// Avoid - may cause layout issues
bannerContainer.heightAnchor.constraint(greaterThanOrEqualToConstant: 50).isActive = true

2. Safe Area

Position banners within safe area:

// Good - respects safe area
bannerContainer.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor)
// Avoid - may overlap with home indicator
bannerContainer.bottomAnchor.constraint(equalTo: view.bottomAnchor)

3. Load in viewWillAppear

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
loadBanner() // Load when view is about to appear
}

4. Handle Failures Gracefully

func bannerStatusChanged(_ manager: EmpowerBannerManager) {
if manager.status == .failed {
// Option 1: Hide container
bannerContainer.isHidden = true
// Option 2: Show fallback content
showFallbackContent()
// Option 3: Collapse container height
bannerHeightConstraint.constant = 0
UIView.animate(withDuration: 0.3) {
self.view.layoutIfNeeded()
}
}
}

Troubleshooting

Banner Not Showing

  1. Check container visibility:
print("Hidden: \(bannerContainer.isHidden)")
print("Alpha: \(bannerContainer.alpha)")
print("Frame: \(bannerContainer.frame)")
  1. Check container is in view hierarchy:
print("Superview: \(bannerContainer.superview)")
  1. Check zone ID is correct

  2. Enable debug logging:

EMASettings.shared.logLevel = .all

Banner Loading Slowly

The SDK loads ads from multiple sources in parallel and selects the best one. This optimization may take a moment. You can show a placeholder:

func bannerStatusChanged(_ manager: EmpowerBannerManager) {
switch manager.status {
case .initializing:
showPlaceholder()
case .ready:
hidePlaceholder()
default:
break
}
}

API Reference

EMAManager.loadBannerAd

func loadBannerAd(
viewController: UIViewController,
zoneId: String,
bannerContainer: UIView,
delegate: AdStatusDelegate?,
adConfiguration: AdConfiguration? = nil,
customParameters: [String: [String]]? = nil,
category: String? = nil,
keywords: String? = nil
) -> EmpowerZoneManager?
ParameterTypeDescription
viewControllerUIViewControllerThe hosting view controller
zoneIdStringYour banner zone ID
bannerContainerUIViewContainer view for the banner
delegateAdStatusDelegate?Callback delegate
customParameters[String: [String]]?Custom targeting parameters
categoryString?Content category
keywordsString?Targeting keywords

Returns: EmpowerZoneManager? - Manager instance for lifecycle control