This guide is intended for publishers integrating app open ads.
App open ads are a special ad format intended for publishers wishing to monetize
their app load screens. App open ads can be closed by your users at any time.
App open ads can be shown when users bring your app to the foreground.
App open ads automatically show a small branding area so users know they're in
your app. Here is an example of what an app open ad looks like:
At a high level, here are the steps required to implement app open ads:
Create a manager class that loads an ad before you need to display it.
Know how to configure your device as atest
device.
Always test with test ads
When building and testing your apps, make sure you use test ads rather than
live, production ads. Failure to do so can lead to suspension of your account.
The easiest way to load test ads is to use our dedicated test ad unit ID for app
open ads:
ca-app-pub-3940256099942544/5575463023
It's been specially configured to return test ads for every request, and you're
free to use it in your own apps while coding, testing, and debugging. Just make
sure you replace it with your own ad unit ID before publishing your app.
For more information about how the Mobile Ads SDK's test ads work, seeTest
Ads.
Implement a manager class
Your ad should show quickly, so it's best to load your ad before you need to
display it. That way, you'll have an ad ready to go as soon as the user enters
your app. Implement a manager class to make ad requests ahead of when you need
to show the ad.
Create a new singleton class calledAppOpenAdManager:
Swift
classAppOpenAdManager:NSObject{/// The app open ad.varappOpenAd:AppOpenAd?/// Maintains a reference to the delegate.weakvarappOpenAdManagerDelegate:AppOpenAdManagerDelegate?/// Keeps track of if an app open ad is loading.varisLoadingAd=false/// Keeps track of if an app open ad is showing.varisShowingAd=false/// Keeps track of the time when an app open ad was loaded to discard expired ad.varloadTime:Date?/// For more interval details, see https://support.google.com/admob/answer/9341964lettimeoutInterval:TimeInterval=4*3_600staticletshared=AppOpenAdManager()
@interfaceAppOpenAdManager()/// The app open ad.@property(nonatomic,strong,nullable)GADAppOpenAd*appOpenAd;/// Keeps track of if an app open ad is loading.@property(nonatomic,assign)BOOLisLoadingAd;/// Keeps track of if an app open ad is showing.@property(nonatomic,assign)BOOLisShowingAd;/// Keeps track of the time when an app open ad was loaded to discard expired ad.@property(nonatomic,strong,nullable)NSDate*loadTime;@end/// For more interval details, see https://support.google.com/admob/answer/9341964staticconstNSIntegerkTimeoutInterval=4;@implementationAppOpenAdManager+(nonnullAppOpenAdManager*)sharedInstance{staticAppOpenAdManager*instance=nil;staticdispatch_once_tonceToken;dispatch_once(&onceToken,^{instance=[[AppOpenAdManageralloc]init];});returninstance;}
And implement itsAppOpenAdManagerDelegateprotocol:
Swift
protocolAppOpenAdManagerDelegate:AnyObject{/// Method to be invoked when an app open ad life cycle is complete (i.e. dismissed or fails to/// show).funcappOpenAdManagerAdDidComplete(_appOpenAdManager:AppOpenAdManager)}
@protocolAppOpenAdManagerDelegate<NSObject>/// Method to be invoked when an app open ad life cycle is complete (i.e. dismissed or fails to/// show).-(void)adDidComplete;@end
funcloadAd()async{// Do not load ad if there is an unused ad or one is already loading.ifisLoadingAd||isAdAvailable(){return}isLoadingAd=truedo{appOpenAd=tryawaitAppOpenAd.load(with:"ca-app-pub-3940256099942544/5575463023",request:Request())appOpenAd?.fullScreenContentDelegate=selfloadTime=Date()}catch{print("App open ad failed to load with error:\(error.localizedDescription)")appOpenAd=nilloadTime=nil}isLoadingAd=false}
-(void)loadAd{// Do not load ad if there is an unused ad or one is already loading.if([selfisAdAvailable]||self.isLoadingAd){return;}self.isLoadingAd=YES;[GADAppOpenAdloadWithAdUnitID:@"ca-app-pub-3940256099942544/5575463023"request:[GADRequestrequest]completionHandler:^(GADAppOpenAd*_NullableappOpenAd,NSError*_Nullableerror){self.isLoadingAd=NO;if(error){NSLog(@"App open ad failed to load with error: %@",error);self.appOpenAd=nil;self.loadTime=nil;return;}self.appOpenAd=appOpenAd;self.appOpenAd.fullScreenContentDelegate=self;self.loadTime=[NSDatedate];}];}
The next step is to show an app open ad. If no ad is available, attempt to
load a new ad.
Swift
funcshowAdIfAvailable(){// If the app open ad is already showing, do not show the ad again.ifisShowingAd{returnprint("App open ad is already showing.")}// If the app open ad is not available yet but is supposed to show, load// a new ad.if!isAdAvailable(){print("App open ad is not ready yet.")// The app open ad is considered to be complete in this example.appOpenAdManagerDelegate?.appOpenAdManagerAdDidComplete(self)// Load a new ad.return}ifletappOpenAd{appOpenAd.present(from:nil)isShowingAd=true}}
-(void)showAdIfAvailable{// If the app open ad is already showing, do not show the ad again.if(self.isShowingAd){NSLog(@"App open ad is already showing.");return;}// If the app open ad is not available yet but is supposed to show, load// a new ad.if(![selfisAdAvailable]){NSLog(@"App open ad is not ready yet.");// The app open ad is considered to be complete in this example.[selfadDidComplete];// Load a new ad.return;}[self.appOpenAdpresentFromRootViewController:nil];self.isShowingAd=YES;}
When the application becomes active, callshowAdIfAvailable()to show an ad if
one is available, or loads a new one.
Swift
funcapplicationDidBecomeActive(_application:UIApplication){// Show the app open ad when the app is foregrounded.AppOpenAdManager.shared.showAdIfAvailable()}
-(void)applicationDidBecomeActive:(UIApplication*)application{// Show the app open ad when the app is foregrounded.[AppOpenAdManager.sharedInstanceshowAdIfAvailable];}
To receive notifications for presentation events, you must assign theGADFullScreenContentDelegateto the fullScreenContentDelegate`s property of
the returned ad:
In particular, you'll want to request the next app open ad once the first one
finishes presenting. The following code shows how to implement the protocol
in yourAppOpenAdManagerfile:
Swift
funcadDidRecordImpression(_ad:FullScreenPresentingAd){print("App open ad recorded an impression.")}funcadDidRecordClick(_ad:FullScreenPresentingAd){print("App open ad recorded a click.")}funcadWillDismissFullScreenContent(_ad:FullScreenPresentingAd){print("App open ad will be dismissed.")}funcadWillPresentFullScreenContent(_ad:FullScreenPresentingAd){print("App open ad will be presented.")}funcadDidDismissFullScreenContent(_ad:FullScreenPresentingAd){print("App open ad was dismissed.")appOpenAd=nilisShowingAd=falseappOpenAdManagerDelegate?.appOpenAdManagerAdDidComplete(self)Task{awaitloadAd()}}funcad(_ad:FullScreenPresentingAd,didFailToPresentFullScreenContentWithErrorerror:Error){print("App open ad failed to present with error:\(error.localizedDescription)")appOpenAd=nilisShowingAd=falseappOpenAdManagerDelegate?.appOpenAdManagerAdDidComplete(self)Task{awaitloadAd()}}
-(void)adDidRecordImpression:(nonnullid<GADFullScreenPresentingAd>)ad{NSLog(@"App open ad recorded an impression.");}-(void)adDidRecordClick:(nonnullid<GADFullScreenPresentingAd>)ad{NSLog(@"App open ad recorded a click.");}-(void)adWillPresentFullScreenContent:(nonnullid<GADFullScreenPresentingAd>)ad{NSLog(@"App open ad will be presented.");}-(void)adWillDismissFullScreenContent:(nonnullid<GADFullScreenPresentingAd>)ad{NSLog(@"App open ad will be dismissed.");}-(void)adDidDismissFullScreenContent:(nonnullid<GADFullScreenPresentingAd>)ad{NSLog(@"App open ad was dismissed.");self.appOpenAd=nil;self.isShowingAd=NO;[selfadDidComplete];[selfloadAd];}-(void)ad:(nonnullid<GADFullScreenPresentingAd>)addidFailToPresentFullScreenContentWithError:(nonnullNSError*)error{NSLog(@"App open ad failed to present with error: %@",error.localizedDescription);self.appOpenAd=nil;self.isShowingAd=NO;[selfadDidComplete];[selfloadAd];}
To make sure you don't show an expired ad, you can add a method to the app
delegate that checks the elapsed time since your ad reference loaded.
In yourAppOpenAdManageradd aDateproperty calledloadTimeand set the
property when your ad loads. You can then add a method that returnstrueif
less than a certain number of hours have passed since your ad loaded. Make sure
you check the validity of your ad reference before you try to show the ad.
Swift
privatefuncwasLoadTimeLessThanNHoursAgo(timeoutInterval:TimeInterval)->Bool{// Check if ad was loaded more than n hours ago.ifletloadTime=loadTime{returnDate().timeIntervalSince(loadTime)<timeoutInterval}returnfalse}privatefuncisAdAvailable()->Bool{// Check if ad exists and can be shown.returnappOpenAd!=nil&&wasLoadTimeLessThanNHoursAgo(timeoutInterval:timeoutInterval)}
-(BOOL)wasLoadTimeLessThanNHoursAgo:(int)n{// Check if ad was loaded more than n hours ago.NSDate*now=[NSDatedate];NSTimeIntervaltimeIntervalBetweenNowAndLoadTime=[nowtimeIntervalSinceDate:self.loadTime];doublesecondsPerHour=3600.0;doubleintervalInHours=timeIntervalBetweenNowAndLoadTime/secondsPerHour;returnintervalInHours<n;}-(BOOL)isAdAvailable{// Check if ad exists and can be shown.return_appOpenAd&&[selfwasLoadTimeLessThanNHoursAgo:kTimeoutInterval];}
The documentation assumes that you only show app open ads when users
foreground your app when it is suspended in memory. "Cold starts" occur when
your app is launched but was not previously suspended in memory.
An example of a cold start is when a user opens your app for the first time.
With cold starts, you won't have a previously loaded app open ad that's ready to
be shown right away. The delay between when you request an ad and receive an ad
back can create a situation where users are able to briefly use your app before
being surprised by an out of context ad. This should be avoided because it is a
bad user experience.
The preferred way to use app open ads on cold starts is to use a loading screen
to load your game or app assets, and to only show the ad from the loading
screen. If your app has completed loading and has sent the user to the main
content of your app, don't show the ad.
Best practices
Google built app open ads to help you monetize your app's loading screen, but
it's important to keep best practices in mind so that your users enjoy using
your app. Make sure to:
Wait to show your first app open ad until after your users have used your
app a few times.
Show app open ads during times when your users would otherwise be waiting
for your app to load.
If you have a loading screen under the app open ad, and your loading screen
completes loading before the ad is dismissed, you may want to dismiss your
loading screen in theadDidDismissFullScreenContentmethod.
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-09-04 UTC."],[[["\u003cp\u003eApp Open Ads monetize app loading screens by displaying closable ads when the app enters the foreground.\u003c/p\u003e\n"],["\u003cp\u003eImplementation involves creating an \u003ccode\u003eAppOpenAdManager\u003c/code\u003e to handle ad loading and display, triggered by foreground events.\u003c/p\u003e\n"],["\u003cp\u003eUse test ads during development with the provided test ad unit ID and replace it with your ad unit ID before publishing to avoid account suspension.\u003c/p\u003e\n"],["\u003cp\u003eEnsure ad validity by checking for expiration and integrating a loading screen for cold starts to provide a smoother user experience.\u003c/p\u003e\n"],["\u003cp\u003eHandle ad presentation events through the \u003ccode\u003eGADFullScreenContentDelegate\u003c/code\u003e to manage ad display, dismissals, and potential errors.\u003c/p\u003e\n"]]],[],null,[]]