App Open Ads
Stay organized with collections
Save and categorize content based on your preferences.
AI-generated Key Takeaways
-
App open ads are displayed on app launch or when resuming from background and are implemented using the Google Mobile Ads SDK.
-
An
AppOpenAdManager
handles ad loading, availability checks, and display logic, whileApplication.ActivityLifecycleCallbacks
tracks the current activity for ad display. -
Ads should be preloaded to minimize disruption and displayed during natural loading times, avoiding immediate display upon cold starts.
-
The
DefaultLifecycleObserver
'sonStart()
event is used to trigger ad display when the app returns to the foreground, ensuring ads are shown at appropriate times. -
To maintain a positive user experience, delay showing the initial ad, respect user interaction, and dismiss loading screens promptly to avoid unnecessary delays.
This guide is intended for publishers integrating app open ads using Google Mobile Ads SDK.
App open ads are a special ad format intended for publishers wishing to monetize their app load screens. App open ads can be closed at any time, and are designed to be shown when your 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:
Prerequisites
- Complete the Get started guide.
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/9257395921
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 Google Mobile Ads SDK test ads work, see Enable test ads.
Extend the Application class
Create a new class that extends the Application
class. This provides a
lifecycle-aware way to manage ads that are tied to the application's state
rather than a single Activity
:
Java
publicclass MyApplicationextendsApplication
implementsActivityLifecycleCallbacks,DefaultLifecycleObserver{
privateAppOpenAdManagerappOpenAdManager;
privateActivitycurrentActivity;
@Override
publicvoidonCreate(){
super.onCreate();
this.registerActivityLifecycleCallbacks(this);
ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
appOpenAdManager=newAppOpenAdManager();
}
Kotlin
classMyApplication:
MultiDexApplication(),Application.ActivityLifecycleCallbacks,DefaultLifecycleObserver{
privatelateinitvarappOpenAdManager:AppOpenAdManager
privatevarcurrentActivity:Activity? =null
overridefunonCreate(){
super<MultiDexApplication>.onCreate()
registerActivityLifecycleCallbacks(this)
ProcessLifecycleOwner.get().lifecycle.addObserver(this)
appOpenAdManager=AppOpenAdManager()
}
Next, add the following code to your AndroidManifest.xml
:
<!--TODO:Updatetoreferenceyouractualpackagename.-->
<application
android:name="com.google.android.gms.example.appopendemo.MyApplication"...>
...
</application>
Implement your utility component
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 your user enters into your app.
Implement a utility component AppOpenAdManager
to encapsulate the work related
to loading and showing App Open ads:
Java
privateclass AppOpenAdManager{
privatestaticfinalStringLOG_TAG="AppOpenAdManager";
privatestaticfinalStringAD_UNIT_ID="ca-app-pub-3940256099942544/9257395921";
privateAppOpenAdappOpenAd=null;
privatebooleanisLoadingAd=false;
privatebooleanisShowingAd=false;
/** Keep track of the time an app open ad is loaded to ensure you don't show an expired ad. */
privatelongloadTime=0;
/** Constructor. */
publicAppOpenAdManager(){}
Kotlin
privateinnerclassAppOpenAdManager{
privatevarappOpenAd:AppOpenAd? =null
privatevarisLoadingAd=false
varisShowingAd=false
/** Keep track of the time an app open ad is loaded to ensure you don't show an expired ad. */
privatevarloadTime:Long=0
To use the AppOpenAdManager
, call the public wrapper methods on the singleton
MyApplication
instance. The Application
class interfaces with the rest of
the code, delegating the work of loading and showing the ad to the manager.
Load an ad
The next step is to fill out the loadAd()
method and handle the ad load
callbacks.
Java
AppOpenAd.load(
context,
"AD_UNIT_ID",
newAdRequest.Builder().build(),
newAppOpenAdLoadCallback(){
@Override
publicvoidonAdLoaded(AppOpenAdad){
// Called when an app open ad has loaded.
Log.d(LOG_TAG,"App open ad loaded.");
appOpenAd=ad;
isLoadingAd=false;
loadTime=(newDate()).getTime();
}
@Override
publicvoidonAdFailedToLoad(LoadAdErrorloadAdError){
// Called when an app open ad has failed to load.
Log.d(LOG_TAG,"App open ad failed to load with error: "+loadAdError.getMessage());
isLoadingAd=false;
}
});
Kotlin
AppOpenAd.load(
context,
"AD_UNIT_ID",
AdRequest.Builder().build(),
object:AppOpenAdLoadCallback(){
overridefunonAdLoaded(ad:AppOpenAd){
// Called when an app open ad has loaded.
Log.d(LOG_TAG,"App open ad loaded.")
appOpenAd=ad
isLoadingAd=false
loadTime=Date().time
}
overridefunonAdFailedToLoad(loadAdError:LoadAdError){
// Called when an app open ad has failed to load.
Log.d(LOG_TAG,"App open ad failed to load with error: "+loadAdError.message)
isLoadingAd=false
}
},
)
Replace AD_UNIT_ID with your own ad unit ID.
Show the ad
The most common app open implementation is to attempt to show an app open ad near app launch, start app content if the ad isn't ready, and preload another ad for the next app open opportunity. See App open ad guidance for implementation examples.
The following code shows and subsequently reloads an ad:
Java
publicvoidshowAdIfAvailable(
@NonNullfinalActivityactivity,
@NonNullOnShowAdCompleteListeneronShowAdCompleteListener){
// If the app open ad is already showing, do not show the ad again.
if(isShowingAd){
Log.d(TAG,"The app open ad is already showing.");
return;
}
// If the app open ad is not available yet, invoke the callback then load the ad.
if(appOpenAd==null){
Log.d(TAG,"The app open ad is not ready yet.");
onShowAdCompleteListener.onShowAdComplete();
// Load an ad.
return;
}
isShowingAd=true;
appOpenAd.show(activity);
}
Kotlin
funshowAdIfAvailable(activity:Activity,onShowAdCompleteListener:OnShowAdCompleteListener){
// If the app open ad is already showing, do not show the ad again.
if(isShowingAd){
Log.d(TAG,"The app open ad is already showing.")
return
}
// If the app open ad is not available yet, invoke the callback then load the ad.
if(appOpenAd==null){
Log.d(TAG,"The app open ad is not ready yet.")
onShowAdCompleteListener.onShowAdComplete()
// Load an ad.
return
}
isShowingAd=true
appOpenAd?.show(activity)
}
Set the FullScreenContentCallback
The FullScreenContentCallback
handles events related to displaying your
AppOpenAd
. Before showing AppOpenAd
, make sure to set the callback:
Java
appOpenAd.setFullScreenContentCallback(
newFullScreenContentCallback(){
@Override
publicvoidonAdDismissedFullScreenContent(){
// Called when full screen content is dismissed.
Log.d(TAG,"Ad dismissed fullscreen content.");
// Don't forget to set the ad reference to null so you
// don't show the ad a second time.
appOpenAd=null;
isShowingAd=false;
onShowAdCompleteListener.onShowAdComplete();
// Load an ad.
}
@Override
publicvoidonAdFailedToShowFullScreenContent(@NonNullAdErroradError){
// Called when full screen content failed to show.
Log.d(TAG,adError.getMessage());
appOpenAd=null;
// Don't forget to set the ad reference to null so you
// don't show the ad a second time.
isShowingAd=false;
onShowAdCompleteListener.onShowAdComplete();
// Load an ad.
}
@Override
publicvoidonAdShowedFullScreenContent(){
Log.d(TAG,"Ad showed fullscreen content.");
}
@Override
publicvoidonAdImpression(){
// Called when an impression is recorded for an ad.
Log.d(TAG,"The ad recorded an impression.");
}
@Override
publicvoidonAdClicked(){
// Called when ad is clicked.
Log.d(TAG,"The ad was clicked.");
}
});
Kotlin
appOpenAd?.fullScreenContentCallback=
object:FullScreenContentCallback(){
overridefunonAdDismissedFullScreenContent(){
// Called when full screen content is dismissed.
Log.d(TAG,"Ad dismissed fullscreen content.")
// Don't forget to set the ad reference to null so you
// don't show the ad a second time.
appOpenAd=null
isShowingAd=false
onShowAdCompleteListener.onShowAdComplete()
// Load an ad.
}
overridefunonAdFailedToShowFullScreenContent(adError:AdError){
// Called when full screen content failed to show.
Log.d(TAG,adError.message)
// Don't forget to set the ad reference to null so you
// don't show the ad a second time.
appOpenAd=null
isShowingAd=false
onShowAdCompleteListener.onShowAdComplete()
// Load an ad.
}
overridefunonAdShowedFullScreenContent(){
Log.d(TAG,"Ad showed fullscreen content.")
}
overridefunonAdImpression(){
// Called when an impression is recorded for an ad.
Log.d(TAG,"The ad recorded an impression.")
}
overridefunonAdClicked(){
// Called when ad is clicked.
Log.d(TAG,"The ad was clicked.")
}
}
Consider ad expiration
To make sure you don't show an expired ad, add a method to the AppOpenAdManager
that checks how long it has been since your ad reference loaded. Then, use that
method to check if the ad is still valid.
Java
/** Check if ad was loaded more than n hours ago. */
privatebooleanwasLoadTimeLessThanNHoursAgo(longnumHours){
longdateDifference=(newDate()).getTime()-loadTime;
longnumMilliSecondsPerHour=3600000;
return(dateDifference < (numMilliSecondsPerHour*numHours));
}
/** Check if ad exists and can be shown. */
privatebooleanisAdAvailable(){
// For time interval details, see: https://support.google.com/admob/answer/9341964
returnappOpenAd!=null && wasLoadTimeLessThanNHoursAgo(4);
}
Kotlin
/** Check if ad was loaded more than n hours ago. */
privatefunwasLoadTimeLessThanNHoursAgo(numHours:Long):Boolean{
valdateDifference:Long=Date().time-loadTime
valnumMilliSecondsPerHour:Long=3600000
returndateDifference < numMilliSecondsPerHour*numHours
}
/** Check if ad exists and can be shown. */
privatefunisAdAvailable():Boolean{
// For time interval details, see: https://support.google.com/admob/answer/9341964
returnappOpenAd!=null && wasLoadTimeLessThanNHoursAgo(4)
}
Keep track of current activity
To show the ad, you'll need an Activity
context. To keep track of the most
current activity being used, register for and implement the
Application.ActivityLifecycleCallbacks
.
Java
@Override
publicvoidonActivityCreated(@NonNullActivityactivity,@NullableBundlesavedInstanceState){}
@Override
publicvoidonActivityStarted(@NonNullActivityactivity){
// An ad activity is started when an ad is showing, which could be AdActivity class from Google
// SDK or another activity class implemented by a third party mediation partner. Updating the
// currentActivity only when an ad is not showing will ensure it is not an ad activity, but the
// one that shows the ad.
if(!appOpenAdManager.isShowingAd){
currentActivity=activity;
}
}
@Override
publicvoidonActivityResumed(@NonNullActivityactivity){}
@Override
publicvoidonActivityPaused(@NonNullActivityactivity){}
@Override
publicvoidonActivityStopped(@NonNullActivityactivity){}
@Override
publicvoidonActivitySaveInstanceState(@NonNullActivityactivity,@NonNullBundleoutState){}
@Override
publicvoidonActivityDestroyed(@NonNullActivityactivity){}
Kotlin
overridefunonActivityCreated(activity:Activity,savedInstanceState:Bundle?){}
overridefunonActivityStarted(activity:Activity){
// An ad activity is started when an ad is showing, which could be AdActivity class from Google
// SDK or another activity class implemented by a third party mediation partner. Updating the
// currentActivity only when an ad is not showing will ensure it is not an ad activity, but the
// one that shows the ad.
if(!appOpenAdManager.isShowingAd){
currentActivity=activity
}
}
overridefunonActivityResumed(activity:Activity){}
overridefunonActivityPaused(activity:Activity){}
overridefunonActivityStopped(activity:Activity){}
overridefunonActivitySaveInstanceState(activity:Activity,outState:Bundle){}
overridefunonActivityDestroyed(activity:Activity){}
registerActivityLifecycleCallbacks
lets you listen for all Activity
events. By listening for when activities
are started and destroyed, you can keep track of a reference to the current
Activity
, which you then will use in presenting your app open ad.
Listen for app foregrounding events
To listen for app foreground events, do the following steps:
Add the libraries to your gradle file
To be notified of app foregrounding events, you need to register a
DefaultLifecycleObserver
. Add its dependency to your app-level build file:
Kotlin
dependencies{ implementation("com.google.android.gms:play-services-ads:24.7.0") implementation("androidx.lifecycle:lifecycle-process:2.8.3") }
Groovy
dependencies{ implementation'com.google.android.gms:play-services-ads:24.7.0' implementation'androidx.lifecycle:lifecycle-process:2.8.3' }
Implement the lifecycle observer interface
You can listen for foregrounding events by implementing the
DefaultLifecycleObserver
interface.
Implement the onStart()
to show the app open ad.
Java
@Override
publicvoidonStart(@NonNullLifecycleOwnerowner){
DefaultLifecycleObserver.super.onStart(owner);
// Show the ad (if available) when the app moves to foreground.
appOpenAdManager.showAdIfAvailable(currentActivity);
}
Kotlin
overridefunonStart(owner:LifecycleOwner){
super.onStart(owner)
currentActivity?.let{
// Show the ad (if available) when the app moves to foreground.
appOpenAdManager.showAdIfAvailable(it)
}
}
Cold starts and loading screens
The documentation thus far 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
App open ads help you monetize your app's loading screen, when the app first launches and during app switches, but it's important to keep best practices in mind so that your users enjoy using your app. It's best to:
- Show your first app open ad 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 the
onAdDismissedFullScreenContent()
method.
Examples on GitHub
Next steps
Explore the following topics: