App Open Ads

App open ads appear when users bring your app to the foreground, providing a monetization opportunity during app launches.

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
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
private let zoneId = "YOUR_APP_OPEN_ZONE_ID"
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Initialize the SDK
EMAManager.shared.initialize(appAdIdentifier: "your_app_identifier")
// Preload the App Open ad
EMAManager.shared.loadAppOpen(zoneId: zoneId)
return true
}
func applicationDidBecomeActive(_ application: UIApplication) {
// Show the ad when the app becomes active
if EMAManager.shared.isAppOpenReady(zoneId: zoneId),
let rootVC = window?.rootViewController {
EMAManager.shared.showAppOpen(zoneId: zoneId, from: rootVC)
}
// Preload for next time
EMAManager.shared.loadAppOpen(zoneId: zoneId)
}
}

Implementation

Only show an App Open ad when the user returns after a meaningful time in the background, and never on the very first cold start (let your content load first).

AppDelegate

import EmpowerMobileAds
@main
class AppDelegate: UIResponder, UIApplicationDelegate, AdStatusDelegate {
var window: UIWindow?
private var backgroundTime: Date?
private let zoneId = "YOUR_APP_OPEN_ZONE_ID"
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
EMAManager.shared.initialize(appAdIdentifier: "your_app_identifier")
EMAManager.shared.loadAppOpen(zoneId: zoneId, delegate: self)
return true
}
func applicationDidEnterBackground(_ application: UIApplication) {
backgroundTime = Date()
}
func applicationDidBecomeActive(_ application: UIApplication) {
showAppOpenAdIfAppropriate()
}
private func showAppOpenAdIfAppropriate() {
if let backgroundTime = backgroundTime,
Date().timeIntervalSince(backgroundTime) >= 30, // at least 30 seconds
EMAManager.shared.isAppOpenReady(zoneId: zoneId),
let rootVC = window?.rootViewController {
EMAManager.shared.showAppOpen(zoneId: zoneId, from: rootVC)
}
backgroundTime = nil
// Always preload for next time
EMAManager.shared.loadAppOpen(zoneId: zoneId, delegate: self)
}
// MARK: - AdStatusDelegate (optional)
func empowerAppOpenStatusChanged(adStatus: AdStatus) {
switch adStatus {
case .ready:
print("App Open ad is ready")
case .failed:
print("App Open ad failed to load")
DispatchQueue.main.asyncAfter(deadline: .now() + 60) { [weak self] in
guard let self = self else { return }
EMAManager.shared.loadAppOpen(zoneId: self.zoneId, delegate: self)
}
case .shown:
print("App Open ad is showing")
case .closed:
print("App Open ad closed")
default:
break
}
}
}

SceneDelegate (iOS 13+)

For apps using UISceneDelegate, wire the same logic into the scene lifecycle:

import EmpowerMobileAds
class SceneDelegate: UIResponder, UIWindowSceneDelegate, AdStatusDelegate {
var window: UIWindow?
private var backgroundTime: Date?
private let zoneId = "YOUR_APP_OPEN_ZONE_ID"
func scene(_ scene: UIScene,
willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions) {
EMAManager.shared.loadAppOpen(zoneId: zoneId, delegate: self)
}
func sceneDidEnterBackground(_ scene: UIScene) {
backgroundTime = Date()
}
func sceneDidBecomeActive(_ scene: UIScene) {
if let backgroundTime = backgroundTime,
Date().timeIntervalSince(backgroundTime) >= 30,
EMAManager.shared.isAppOpenReady(zoneId: zoneId),
let rootVC = window?.rootViewController {
EMAManager.shared.showAppOpen(zoneId: zoneId, from: rootVC)
}
backgroundTime = nil
EMAManager.shared.loadAppOpen(zoneId: zoneId, delegate: self)
}
func empowerAppOpenStatusChanged(adStatus: AdStatus) {
// Handle status changes if needed
}
}

Status Values

Swift (AdStatus)Objective-C (EMAAdStatusType)Description
.initializingEMAAdStatusTypeInitializingAd is loading
.readyEMAAdStatusTypeReadyAd is ready to show
.shownEMAAdStatusTypeShownAd is currently showing
.failed(Error?)EMAAdStatusTypeFailedAd failed to load
.closedEMAAdStatusTypeClosedAd was shown and closed

In Swift, adopt AdStatusDelegate and implement empowerAppOpenStatusChanged(adStatus:). In Objective-C, adopt EMAAdObserver and implement appOpenStatusChanged:.


Best Practices

  1. Don't show on every return — only after a meaningful background time (30+ seconds).
  2. Respect user experience — don't interrupt critical user flows.
  3. Always preload — call the load method again after showing to prepare for next time.
  4. Don't block app launch — let content load first on cold start.
  5. Skip during critical flows — don't show during checkout, onboarding, etc.

Troubleshooting

print("Ad ready: \(EMAManager.shared.isAppOpenReady(zoneId: "YOUR_ZONE_ID"))")
print("SDK initialized: \(EMAManager.shared.isSdkInitialized)")
EMASettings.shared.logLevel = .all

API Reference

func loadAppOpen(zoneId: String, delegate: AdStatusDelegate? = nil)
func isAppOpenReady(zoneId: String) -> Bool
func showAppOpen(zoneId: String, from viewController: UIViewController)

Objective-C selectors

SwiftObjective-C selector
loadAppOpen(zoneId:delegate:)loadAppOpenAdWithZoneId:observer:
isAppOpenReady(zoneId:)isAppOpenReadyForZoneId:
showAppOpen(zoneId:from:)showAppOpenWithZoneId:fromViewController: