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 EmpowerMobileAdsclass 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(status: AdStatus, zoneId: String, adUnitId: String) {switch status {case .ready:print("Banner is ready and displayed for zone: \(zoneId)")case .failed(let error):print("Banner failed to load: \(error?.localizedDescription ?? "unknown")")case .initializing:print("Banner is loading...")default:break}}}
Supported Sizes
| Size | Description |
|---|---|
| 320x50 | Standard Banner |
| 320x100 | Large Banner |
| 300x250 | Medium Rectangle |
Container Setup
Interface Builder (Storyboard)
- Add a
UIViewto your view controller - Set constraints for position and height
- Connect the outlet to your view controller
Programmatic Setup
// Standard Banner (320x50)let bannerContainer = UIView()bannerContainer.translatesAutoresizingMaskIntoConstraints = falseview.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 = falseview.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")
Legacy Loading (without ViewController)
Note: It's recommended to use the method that accepts a
viewControllerparameter for proper lifecycle management.
EMAManager.shared.loadBannerAd(zoneId: "YOUR_ZONE_ID",container: bannerContainer,delegate: self,customParameters: "sports,football")
Status Handling
AdStatusDelegate
extension ViewController: AdStatusDelegate {func bannerStatusChanged(status: AdStatus, zoneId: String, adUnitId: String) {switch status {case .initializing:// Banner is loadingshowLoadingIndicator()case .ready:// Banner is displayedhideLoadingIndicator()print("Banner loaded for zone: \(zoneId), adUnit: \(adUnitId)")case .failed(let error):// Banner failed to loadhideLoadingIndicator()hideBannerContainer()print("Banner failed for zone: \(zoneId), error: \(error?.localizedDescription ?? "unknown")")case .clicked:print("Banner clicked for zone: \(zoneId)")case .impression:print("Banner impression recorded for zone: \(zoneId)")default:break}}}
Status Values
| Status | Description |
|---|---|
.initializing | Banner is loading |
.ready | Banner is displayed |
.failed(Error?) | Banner failed to load (with optional error) |
.clicked | Banner was clicked |
.impression | Impression was recorded |
.undefined | Initial/destroyed state |
SwiftUI Integration
import SwiftUIimport EmpowerMobileAds// MARK: - Banner Viewstruct BannerAdView: UIViewControllerRepresentable {let zoneId: Stringlet height: CGFloatfunc makeUIViewController(context: Context) -> BannerAdViewController {return BannerAdViewController(zoneId: zoneId)}func updateUIViewController(_ uiViewController: BannerAdViewController, context: Context) {}}// MARK: - Banner View Controllerclass BannerAdViewController: UIViewController, AdStatusDelegate {private let zoneId: Stringprivate var bannerContainer: UIView!init(zoneId: String) {self.zoneId = zoneIdsuper.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 = falseview.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(status: AdStatus, zoneId: String, adUnitId: String) {// Handle status changes}}// MARK: - Usagestruct ContentView: View {var body: some View {VStack {Text("Your Content")Spacer()// Standard BannerBannerAdView(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 contentBannerAdView(zoneId: "YOUR_MREC_ZONE_ID", height: 250).frame(height: 250)Text("Article content...")}}}}
Lifecycle Management
Zone Control
// Pause banner refresh timerEMAManager.shared.pauseBannerZone(zoneId: "YOUR_ZONE_ID")// Resume banner refresh timerEMAManager.shared.resumeBannerZone(zoneId: "YOUR_ZONE_ID")// Destroy banner zone completelyEMAManager.shared.destroyBannerZone(zoneId: "YOUR_ZONE_ID")
Tab Bar Navigation
When using tab bar controllers, pause and resume banners on inactive tabs:
class TabBarController: UITabBarController, UITabBarControllerDelegate {override func viewDidLoad() {super.viewDidLoad()delegate = self}func tabBarController(_ tabBarController: UITabBarController,didSelect viewController: UIViewController) {// Pause all banners on previously visible tabs// Resume banners on the newly selected tab}}
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:
// GoodbannerContainer.heightAnchor.constraint(equalToConstant: 50).isActive = true// Avoid - may cause layout issuesbannerContainer.heightAnchor.constraint(greaterThanOrEqualToConstant: 50).isActive = true
2. Safe Area
Position banners within safe area:
// Good - respects safe areabannerContainer.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor)// Avoid - may overlap with home indicatorbannerContainer.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(status: AdStatus, zoneId: String, adUnitId: String) {if case .failed = status {// Option 1: Hide containerbannerContainer.isHidden = true// Option 2: Show fallback contentshowFallbackContent()// Option 3: Collapse container heightbannerHeightConstraint.constant = 0UIView.animate(withDuration: 0.3) {self.view.layoutIfNeeded()}}}
Troubleshooting
Banner Not Showing
- Check container visibility:
print("Hidden: \(bannerContainer.isHidden)")print("Alpha: \(bannerContainer.alpha)")print("Frame: \(bannerContainer.frame)")
- Check container is in view hierarchy:
print("Superview: \(bannerContainer.superview)")
Check zone ID is correct
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(status: AdStatus, zoneId: String, adUnitId: String) {switch status {case .initializing:showPlaceholder()case .ready:hidePlaceholder()default:break}}
API Reference
EMAManager.loadBannerAd (Recommended)
func loadBannerAd(viewController: UIViewController,zoneId: String,bannerContainer: UIView,delegate: AdStatusDelegate? = nil,keywords: String? = nil)
| Parameter | Type | Description |
|---|---|---|
viewController | UIViewController | The hosting view controller (for lifecycle management) |
zoneId | String | Your banner zone ID |
bannerContainer | UIView | Container view for the banner |
delegate | AdStatusDelegate? | Callback delegate |
keywords | String? | Targeting keywords |
EMAManager.loadBannerAd (Legacy)
func loadBannerAd(zoneId: String,container: UIView,delegate: AdStatusDelegate? = nil,customParameters: String? = nil)
| Parameter | Type | Description |
|---|---|---|
zoneId | String | Your banner zone ID |
container | UIView | Container view for the banner |
delegate | AdStatusDelegate? | Callback delegate |
customParameters | String? | Custom targeting parameters |
Zone Management
func pauseBannerZone(zoneId: String)func resumeBannerZone(zoneId: String)func destroyBannerZone(zoneId: String)