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 'dart:async';
import 'dart:io';
import 'package:empower_mobile_ads/empower_mobile_ads.dart';
final zoneId = Platform.isAndroid ? 'ANDROID_ZONE_ID' : 'IOS_ZONE_ID';
// Preload the app open ad
EmpowerAds.loadAppOpenAd(zoneId);
// Show when ad is ready
final subscription = EmpowerAds.onAppOpenStatusChanged.listen((event) {
final status = event['status'];
if (status == 'READY') {
EmpowerAds.showAppOpen(zoneId);
}
});

Loading App Open Ads

import 'package:empower_mobile_ads/empower_mobile_ads.dart';
// Load with zone ID
await EmpowerAds.loadAppOpenAd('YOUR_ZONE_ID');

The method returns a Future<bool> that resolves to true when the ad starts loading.


Showing App Open Ads

import 'package:empower_mobile_ads/empower_mobile_ads.dart';
final shown = await EmpowerAds.showAppOpen('YOUR_ZONE_ID');
if (!shown) {
print('App Open ad not ready');
}

Listening to App Open Status (Optional)

import 'dart:async';
import 'package:empower_mobile_ads/empower_mobile_ads.dart';
final zoneId = 'YOUR_ZONE_ID';
final subscription = EmpowerAds.onAppOpenStatusChanged.listen((event) {
final status = event['status'];
switch (status) {
case 'READY':
// Ad is ready to show
break;
case 'FAILED':
// Ad failed to load
break;
case 'SHOWN':
// Ad is being displayed
break;
case 'SKIPPED':
// User dismissed the ad
break;
case 'USED':
// Ad was shown and closed — reload for next time
EmpowerAds.loadAppOpenAd(zoneId);
break;
}
});
// Clean up
subscription.cancel();

Complete Example

Show the app open ad on cold start only (once per session):

import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:empower_mobile_ads/empower_mobile_ads.dart';
bool _appOpenShown = false; // Module-level flag
class MyApp extends StatefulWidget {
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
StreamSubscription? _appOpenSub;
final String _zoneId = Platform.isAndroid ? 'ANDROID_ZONE_ID' : 'IOS_ZONE_ID';
@override
void initState() {
super.initState();
final appId = Platform.isAndroid
? 'your_android_app_identifier'
: 'your_ios_app_identifier';
EmpowerAds.init(EmpowerAdsConfig(
appAdIdentifier: appId,
));
// Preload
EmpowerAds.loadAppOpenAd(_zoneId);
// Show once when ready
_appOpenSub = EmpowerAds.onAppOpenStatusChanged.listen((event) {
final status = event['status'];
if (status == 'READY' && !_appOpenShown) {
_appOpenShown = true;
EmpowerAds.showAppOpen(_zoneId);
}
});
}
@override
void dispose() {
_appOpenSub?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HomeScreen(),
);
}
}

Show on Foreground Return

To show the ad when users return to the app, use Flutter's WidgetsBindingObserver:

import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:empower_mobile_ads/empower_mobile_ads.dart';
class AppOpenHandler extends StatefulWidget {
final Widget child;
const AppOpenHandler({required this.child});
@override
State<AppOpenHandler> createState() => _AppOpenHandlerState();
}
class _AppOpenHandlerState extends State<AppOpenHandler> with WidgetsBindingObserver {
static const _minBackgroundSeconds = 30;
final String _zoneId = Platform.isAndroid ? 'ANDROID_ZONE_ID' : 'IOS_ZONE_ID';
StreamSubscription? _statusSub;
bool _isAdReady = false;
DateTime? _backgroundTime;
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
// Preload
EmpowerAds.loadAppOpenAd(_zoneId);
// Track readiness
_statusSub = EmpowerAds.onAppOpenStatusChanged.listen((event) {
final status = event['status'];
_isAdReady = status == 'READY';
if (status == 'USED') {
EmpowerAds.loadAppOpenAd(_zoneId); // Reload for next time
}
});
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
_statusSub?.cancel();
super.dispose();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.paused) {
_backgroundTime = DateTime.now();
}
if (state == AppLifecycleState.resumed && _backgroundTime != null) {
final elapsed = DateTime.now().difference(_backgroundTime!).inSeconds;
if (elapsed >= _minBackgroundSeconds && _isAdReady) {
EmpowerAds.showAppOpen(_zoneId);
}
}
}
@override
Widget build(BuildContext context) {
return widget.child; // Render nothing extra — this is a logic wrapper
}
}

Usage:

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: AppOpenHandler(
child: HomeScreen(),
),
);
}
}

Best Practices

  • Cold starts — Show on fresh app launches for highest impact
  • Don't show on every return — Only show after meaningful background time (30+ seconds)
  • Respect user experience — Don't interrupt critical user flows (checkout, onboarding, etc.)
  • Always preload — Call loadAppOpenAd after showing to prepare for next time
  • Don't block app launch — Let content load first on cold start
  • Once per session — Consider using a module-level flag to limit to one display per cold start

Ad Status Reference

StatusDescription
INITIALIZINGAd is loading
READYAd is loaded and ready to display
FAILEDAd failed to load
SHOWNAd is being displayed
SKIPPEDUser dismissed the ad
USEDAd was shown and closed