App open ads appear when your users open or return to your app. Your users can close app open ads at any time. To monetize your app load screen, use app open ads. For details, see App open ad guidance and best practices.
This guide explains how to integrate app open ads into a React Native app.
Prerequisites
Before you continue, do the following:
- Set up Google Mobile Ads SDK for React Native.
- Enable test ads and use the following test ad unit:
Android
ca-app-pub-3940256099942544/9257395921
iOS
ca-app-pub-3940256099942544/5575463023
Understand ad preloading
Ad preloading in Google Mobile Ads SDK for React Native automates ad loading and caching.
Ad preloading provides the following benefits:
- Reference management: maintains references until ads are shown.
- Automatic reloading: loads a new ad when one is retrieved from the cache.
- Managed retries: loads a new ad when one fails to load.
- Expiration handling: refreshes ads before expiring.
- Cache optimization: optimizes the cache order to deliver the highest priority ad.
To load ads manually, see the Load a single app open ad guide.
Start preloading
To start preloading ads, call the
AppOpenAdPreloader.start method and pass
your preloadId value, configuration settings, and event callbacks to monitor
buffer state changes:
export function startAppOpenAdPreloader(
adUnitId: string,
preloadId: string,
customPreloadCallback?: PreloadCallback,
): boolean {
const started = AppOpenAdPreloader.start(
preloadId,
{
request: {adUnitId},
bufferSize: 2,
},
{
// Called when an ad is preloaded into the buffer.
onAdPreloaded: (event) => {
console.log(`App open ad preloaded for ${event.preloadId}`);
customPreloadCallback?.onAdPreloaded?.(event);
},
// Called when an ad fails to preload.
onAdFailedToPreload: (error: LoadAdError) => {
console.error('Failed to preload app open ad:', error.message);
customPreloadCallback?.onAdFailedToPreload?.(error);
},
// Called when all preloaded ads in the buffer have been shown.
onAdsExhausted: () => {
console.log('App open ad buffer exhausted.');
customPreloadCallback?.onAdsExhausted?.();
},
},
);
return started;
}
A preloadId is a string that uniquely identifies an ad preloading
configuration. If the adUnitId is used for only a single preloading
configuration in your app, you can use that ad unit ID as the preload ID. If
your app requires multiple preloaders for the same ad unit ID, pass distinct
strings for each preload ID.
When your app polls a preloaded ad from the buffer, Google Mobile Ads SDK for React Native
requests a replacement ad in the background to refill the buffer. If no
preloaded ads remain in the buffer, Google Mobile Ads SDK for React Native invokes the
onAdsExhausted callback.
Preload cache limits
Google Mobile Ads SDK for React Native enforces an app-wide limit on the total number of preloaded ads:
- Default limit: Google holds a maximum of six preloaded ads in memory.
- We recommend keeping a buffer size of two for each preload ID.
If your app reaches the app-wide limit, background requests for preloaded ads pause until existing ads are polled and displayed or destroyed.
Poll and show the ad
To check for available preloaded ads and retrieve an ad instance, call the
AppOpenAdPreloader.pollAd method.
To listen for full-screen presentation events, register callbacks on the
adEventCallback property of the returned
AppOpenAd instance before calling the
show method:
export function showPreloadedAppOpenAd(
preloadId: string,
customAdEventCallback?: FullScreenAdEventCallback,
) {
if (!AppOpenAdPreloader.isAdAvailable(preloadId)) {
console.log('No preloaded app open ad available right now.');
return;
}
const ad = AppOpenAdPreloader.pollAd(preloadId);
if (!ad) {
return;
}
ad.adEventCallback = {
// Called when the ad is presented on screen.
onAdShowedFullScreenContent: () => {
console.log('Preloaded app open ad showed full screen content.');
customAdEventCallback?.onAdShowedFullScreenContent?.();
},
// Called when the ad is closed by the user.
onAdDismissedFullScreenContent: () => {
console.log('Preloaded app open ad dismissed full screen content.');
customAdEventCallback?.onAdDismissedFullScreenContent?.();
ad.destroy();
},
// Called when presentation fails.
onAdFailedToShowFullScreenContent: (error) => {
console.error('Failed to show preloaded app open ad:', error);
customAdEventCallback?.onAdFailedToShowFullScreenContent?.(error);
ad.destroy();
},
// Called when an impression is recorded.
onAdImpression: () => {
console.log('Preloaded app open ad recorded an impression.');
customAdEventCallback?.onAdImpression?.();
},
// Called when the user taps the ad.
onAdClicked: () => {
console.log('Preloaded app open ad was clicked.');
customAdEventCallback?.onAdClicked?.();
},
// Called when the ad is estimated to have earned money.
onAdPaid: (adValue) => {
console.log(
`Preloaded app open ad paid: ${adValue.amountMicros}` +
` ${adValue.currencyCode}`,
);
customAdEventCallback?.onAdPaid?.(adValue);
},
};
ad.show();
}
To release memory and resources, call the ad.destroy method in the
onAdDismissedFullScreenContent
and
onAdFailedToShowFullScreenContent
callbacks when a user dismisses an ad or the ad fails to show.
Read the response info
To inspect details of the next preloaded ad without removing the ad from the
cache, call the
AppOpenAdPreloader.peekAdResponseInfo
method:
export function peekAppOpenAdResponseInfo(
preloadId: string,
): ResponseInfo | null {
const responseInfo = AppOpenAdPreloader.peekAdResponseInfo(preloadId);
if (responseInfo) {
console.log('Next preloaded app open ad response info:', responseInfo);
}
return responseInfo;
}
Manage app open ads with an app-level manager
Because app open ads are presented globally during app launch and foreground transitions, we recommend managing preloader lifecycle state in an app-level manager outside the React component tree.
Using an app-level manager offers several key advantages:
- Keeps preloader state independent of individual screen navigation and component lifecycle.
- Centralizes ad event callbacks, state tracking, and cleanup in a single shared instance across your app.
- Controls when foreground events are listened to, preventing duplicate presentations upon ad dismissal.
The following example implements an app-level manager using
the AppOpenAdPreloader object:
export class AppOpenAdManager {
private adUnitId: string;
private preloadId: string;
private appStateSubscription?: NativeEventSubscription;
private startTimeoutId?: ReturnType<typeof setTimeout>;
constructor(adUnitId: string, preloadId: string) {
this.adUnitId = adUnitId;
this.preloadId = preloadId;
}
start(): boolean {
if (!AppOpenAdPreloader.getConfiguration(this.preloadId)) {
AppOpenAdPreloader.start(
this.preloadId,
{
request: {adUnitId: this.adUnitId},
bufferSize: 2,
},
{
onAdPreloaded: (event) => {
console.log(`App open ad preloaded for ${event.preloadId}`);
},
onAdFailedToPreload: (error: LoadAdError) => {
console.error('Failed to preload app open ad:', error.message);
},
onAdsExhausted: () => {
console.log('App open ad buffer exhausted.');
},
},
);
}
if (!this.appStateSubscription && !this.startTimeoutId) {
// Delay attaching the listener to ensure native dismissal transitions complete
this.startTimeoutId = setTimeout(() => {
this.startTimeoutId = undefined;
if (!this.appStateSubscription) {
this.appStateSubscription = AppState.addEventListener(
'change',
(nextAppState: AppStateStatus) => {
if (nextAppState === 'active') {
this.showAdIfAvailable();
}
},
);
}
}, APP_STATE_LISTENER_DELAY_MS);
}
return true;
}
pause(): void {
if (this.startTimeoutId) {
clearTimeout(this.startTimeoutId);
this.startTimeoutId = undefined;
}
this.appStateSubscription?.remove();
this.appStateSubscription = undefined;
}
stop(): void {
this.pause();
AppOpenAdPreloader.destroy(this.preloadId);
}
showAdIfAvailable() {
if (!AppOpenAdPreloader.isAdAvailable(this.preloadId)) {
console.log('App open ad is not preloaded or available right now.');
return;
}
const ad = AppOpenAdPreloader.pollAd(this.preloadId);
if (!ad) {
return;
}
// Pause listener while presenting the ad
this.pause();
ad.adEventCallback = {
onAdShowedFullScreenContent: () => {
console.log('Preloaded app open ad showed full screen content.');
},
onAdDismissedFullScreenContent: () => {
console.log('Preloaded app open ad dismissed full screen content.');
ad.destroy();
this.start();
},
onAdFailedToShowFullScreenContent: (error) => {
console.error('Failed to show preloaded app open ad:', error);
ad.destroy();
this.start();
},
};
ad.show();
}
}
Listen to app foregrounding events
To display ads when your app returns to the foreground, register a change
listener on the AppState module in your app's root component,
such as App.tsx. Check when the state transitions to active.
For example, call the start method on your ad manager instance in the
App.tsx component.
Presenting ad overlays or landing pages, such as showing full-screen ads or
tapping a banner ad, pushes your application to the background. When the user
returns to your application, your app receives a new active state event. To
prevent an unintended ad presentation or loop where returning from an ad
presents an app open ad from the cache, do the following:
- Remove the
AppStateevent listener before presenting a full-screen ad. - To make sure listening resumes whether a user dismisses the ad or the ad
fails to show, add the
AppStateevent listener again in theonAdDismissedFullScreenContentandonAdFailedToShowFullScreenContentcallbacks.
For a complete example of controlling when foreground event listeners are paused
and resumed, see the AppOpenAdManager implementation.
Learn cold starts and loading screens
A cold start occurs when your app launches from scratch, for example, when a user opens your app for the first time or after the device closes the app to free memory. During a cold start, you lack a previously loaded app open ad to show next.
Because of ad request delays, your users might interact with your app before an ad appears. Show app open ads on cold starts only from a loading screen while app assets load. If assets finish loading and the user reaches the main content before the ad loads, don't show the ad.
Clean up resources
When preloading is no longer required for a screen or ad unit ID, such as when
navigating away from a screen that preloads ads, call the
AppOpenAdPreloader.destroy method to
release preloader resources and prevent holding unused ad objects in memory:
export function destroyAppOpenAdPreloader(preloadId: string) {
AppOpenAdPreloader.destroy(preloadId);
}
In addition to destroying the preloader queue, make sure to destroy individual polled ad instances when a user dismisses an ad or the ad fails to show. For details, see Poll and show the ad.
View the full example
The following example component starts preloading on mount, tracks available ad counts, and provides controls to show preloaded app open ads:
Replace the following:
- APP_OPEN_AD_UNIT_ID with your ad unit ID.
- PRELOAD_ID with your preloader ID.
Next steps
After you integrate app open ads, explore the following topics: