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@mainclass AppDelegate: UIResponder, UIApplicationDelegate, AdStatusDelegate {var window: UIWindow?private let zoneId = "YOUR_APP_OPEN_ZONE_ID"func application(_ application: UIApplication,didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {// Initialize SDKEMAManager.shared.initAd("your_app_identifier")// Preload App Open adEMAManager.shared.loadAppOpen(zoneId: zoneId)return true}func applicationDidBecomeActive(_ application: UIApplication) {// Show ad when app becomes activeEMAManager.shared.MAManager.shared.showAppOpen(from: rootVC)// Preload for next timeEMAManager.shared.loadAppOpen(zoneId: zoneId)}}
Implementation
AppDelegate (iOS 12 and earlier)
import EmpowerMobileAds@mainclass 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 {// Initialize SDKEMAManager.shared.initAd("your_app_identifier")// Setup App Open ad with delegate (optional)EmpowerAppOpenManager.shared.delegate = selfEMAManager.shared.loadAppOpen(zoneId: zoneId)return true}func applicationDidEnterBackground(_ application: UIApplication) {backgroundTime = Date()}func applicationDidBecomeActive(_ application: UIApplication) {showAppOpenAdIfAppropriate()}private func showAppOpenAdIfAppropriate() {// Only show if user was in background for a meaningful timeif let backgroundTime = backgroundTime {let timeInBackground = Date().timeIntervalSince(backgroundTime)if timeInBackground >= 30 { // At least 30 secondsMAManager.shared.showAppOpen(from: rootVC)}}backgroundTime = nil// Always preload for next timeEMAManager.shared.loadAppOpen(zoneId: zoneId)}// MARK: - AdStatusDelegate (Optional)func empowerAppOpenStatusChanged(_ manager: EmpowerAppOpenManager) {switch manager.status {case .ready:print("App Open ad is ready")case .failed:print("App Open ad failed to load")// Retry after delayDispatchQueue.main.asyncAfter(deadline: .now() + 60) { [weak self] inguard let self = self else { return }EMAManager.shared.loadAppOpen(zoneId: self.zoneId)}case .present:print("App Open ad is showing")case .used:print("App Open ad closed")// Ad is automatically reloaded after showdefault:break}}}
SceneDelegate (iOS 13+)
For apps using UISceneDelegate:
import EmpowerMobileAdsclass 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) {// Setup App Open ad with delegate (optional)EmpowerAppOpenManager.shared.delegate = selfEMAManager.shared.loadAppOpen(zoneId: zoneId)}func sceneDidEnterBackground(_ scene: UIScene) {backgroundTime = Date()}func sceneDidBecomeActive(_ scene: UIScene) {showAppOpenAdIfAppropriate()}private func showAppOpenAdIfAppropriate() {if let backgroundTime = backgroundTime {let timeInBackground = Date().timeIntervalSince(backgroundTime)if timeInBackground >= 30 {MAManager.shared.showAppOpen(from: rootVC)}}backgroundTime = nilEMAManager.shared.loadAppOpen(zoneId: zoneId)}func empowerAppOpenStatusChanged(_ manager: EmpowerAppOpenManager) {// Handle status changes if needed}}
Status Handling
AdStatusDelegate
func empowerAppOpenStatusChanged(_ manager: EmpowerAppOpenManager) {switch manager.status {case .initializing:print("App Open ad loading...")case .ready:print("App Open ad ready to show")case .failed:print("App Open ad failed to load")retryLoad()case .present:print("App Open ad is displaying")// Optionally pause contentcase .used:print("App Open ad was closed")// Ad is automatically reloadeddefault:break}}
Status Values
| Status | Description |
|---|---|
.initializing | Ad is loading |
.ready | Ad is ready to show |
.present | Ad is currently showing |
.failed | Ad failed to load |
.used | Ad was shown and closed |
SwiftUI Integration
import SwiftUIimport EmpowerMobileAds// MARK: - App Open Ad Managerclass AppOpenAdManager: NSObject, ObservableObject, AdStatusDelegate {static let shared = AppOpenAdManager()@Published var isReady = falseprivate var backgroundTime: Date?private let zoneId = "YOUR_ZONE_ID"private let minimumBackgroundDuration: TimeInterval = 30override init() {super.init()EmpowerAppOpenManager.shared.delegate = selfpreload()}func preload() {EMAManager.shared.loadAppOpen(zoneId: zoneId)}func appDidEnterBackground() {backgroundTime = Date()}func appDidBecomeActive() {defer {backgroundTime = nilpreload()}guard let backgroundTime = backgroundTime else { return }let duration = Date().timeIntervalSince(backgroundTime)guard duration >= minimumBackgroundDuration else { return }MAManager.shared.showAppOpen(from: rootVC)}func empowerAppOpenStatusChanged(_ manager: EmpowerAppOpenManager) {DispatchQueue.main.async {self.isReady = manager.status == .ready}}}// MARK: - SwiftUI App@mainstruct MyApp: App {@StateObject private var appOpenManager = AppOpenAdManager.shared@Environment(\.scenePhase) private var scenePhaseinit() {EMAManager.shared.initAd("your_app_identifier")}var body: some Scene {WindowGroup {ContentView().onChange(of: scenePhase) { newPhase inswitch newPhase {case .active:appOpenManager.appDidBecomeActive()case .background:appOpenManager.appDidEnterBackground()default:break}}}}}
Best Practices
- Don't Show on Every Return - Only show after meaningful background time (30+ seconds)
- Respect User Experience - Don't interrupt critical user flows
- Always Preload - Call
loadAppOpenafter showing to prepare for next time - Don't Block App Launch - Let content load first on cold start
- Skip During Critical Flows - Don't show during checkout, onboarding, etc.
Troubleshooting
Ad Not Showing
Check availability:
print("Ad available: \(EMAManager.shared.isAppOpenReady())")
Enable debug logging:
EMASettings.shared.logLevel = .all
Ad Not Loading
- Check zone ID is correct
- Check network connectivity
- Check SDK is initialized:
print("SDK initialized: \(EMAManager.shared.isSdkInitialized())")
AdStatusDelegate
| Method | Description |
|---|---|
empowerAppOpenStatusChanged(_:) | Called when App Open ad status changes |