App open ads
App open ads are a special ad format for monetizing your app load screens. These ads can be closed at any time and are designed to be served when users bring your app to the foreground, either at launch or when returning to it from the background.
This guide shows how to integrate app open ads into Unity apps. In addition to code examples and instructions, it includes format-specific recommendations and links to additional resources.
Layout
App open ads include a Go to the app button so users know they're in your app and can close the ad. Here's an example of what an ad looks like:
Prerequisite
- Follow the process in Quick start for integrating the Yandex Mobile Ads Unity Plugin.
- Make sure you're running the latest Yandex Mobile Ads Unity Plugin version. If you're using mediation, make sure you're also running the latest version of the unified build.
Terms and definitions
- Cold start — starting the app when it is not in RAM, creating a new app session.
- Hot start — bringing the app from background (paused in RAM) to foreground.
Implementation
- Create an
AppOpenAdLoaderad loader. - Load an ad with the
AppOpenAdLoader.LoadAd(AdRequest)method usingasync/awaitor callbacks. - Register listeners for user interaction events with the ad.
- Use
AppStateObserverto handle app state changes and show the ad when the app is opened. - Show the ad by calling
AppOpenAd.Show(). - Release resources.
Main steps
-
Create an
AppOpenAdLoaderad loader.using UnityEngine; using YandexMobileAds; using YandexMobileAds.Base; public class YandexMobileAdsAppOpenAdDemoScript : MonoBehaviour { private AppOpenAdLoader appOpenAdLoader; private AppOpenAd appOpenAd; private void SetupLoader() { appOpenAdLoader = new AppOpenAdLoader(); // ... } } -
Load an ad with the
LoadAdmethod.async/awaitCallbacksprivate async void RequestAppOpenAd() { string adUnitId = "demo-appopenad-yandex"; // replace with "R-M-XXXXXX-Y" try { appOpenAd = await appOpenAdLoader.LoadAd(new AdRequest(adUnitId)); } catch (AdLoadingException e) { // Ad failed to load with {e.Message} // Attempting to load a new ad from catch block is strongly discouraged. } }private void RequestAppOpenAd() { string adUnitId = "demo-appopenad-yandex"; // replace with "R-M-XXXXXX-Y" AdRequest adRequest = new AdRequest(adUnitId); appOpenAdLoader.LoadAd( adRequest: adRequest, onLoaded: appOpenAd => { // The ad was loaded successfully. Now you can handle it. this.appOpenAd = appOpenAd; }, onFailed: args => { // Ad failed to load with {args.Message} // Attempting to load a new ad from the onFailed callback is strongly discouraged. }); }adUnitIdis a unique identifier issued in the Yandex Advertising Network interface and looks like this: R-M-XXXXXX-Y.Tip
For testing, you can use the demo ad unit ID: "demo-appopenad-yandex". Before publishing the app, replace it with a real ad unit ID.
You can expand the ad request parameters through the
AdTargetingclass by passing user interests, contextual page data, location, or other data. Additional contextual data can significantly improve ad quality. Read more in Ad Targeting. -
Register listeners for user interaction events with the ad.
using System; // ... appOpenAd.OnAdClicked += HandleAdClicked; appOpenAd.OnAdShown += HandleAdShown; appOpenAd.OnAdFailedToShow += HandleAdFailedToShow; appOpenAd.OnAdDismissed += HandleAdDismissed; appOpenAd.OnAdImpression += HandleImpression; // ... public void HandleAdClicked(object sender, EventArgs args) { // Called when a click is recorded for an ad. } public void HandleAdShown(object sender, EventArgs args) { // Called when ad is shown. } public void HandleAdFailedToShow(object sender, AdFailureEventArgs args) { // Called when an ad failed to show. } public void HandleAdDismissed(object sender, EventArgs args) { // Called when an ad is dismissed. } public void HandleImpression(object sender, ImpressionData impressionData) { // Called when an impression is recorded for an ad. } -
Use
AppStateObserverto handle app state changes and show the ad when the app is opened.using YandexMobileAds; public class YandexMobileAdsAppOpenAdDemoScript : MonoBehaviour { public void Awake() { // Use the AppStateObserver to listen to application open/close events. AppStateObserver.OnAppStateChanged += HandleAppStateChanged; } public void OnDestroy() { // Unsubscribe from the event to avoid memory leaks. AppStateObserver.OnAppStateChanged -= HandleAppStateChanged; } } -
Show the ad by calling
AppOpenAd.Show().private void HandleAppStateChanged(object sender, AppStateChangedEventArgs args) { if (!args.IsInBackground) { ShowAppOpenAd(); } } private void ShowAppOpenAd() { if (appOpenAd != null) { appOpenAd.Show(); } }Note
If the ad has already been served, calling the
AppOpenAd.Show()method will return a display error inHandleAdFailedToShow. -
Call
Destroy()on ads that are no longer needed and clear references if they are not used in the current scene.That releases resources and prevents memory leaks.
public void DestroyAppOpenAd() { if (appOpenAd != null) { appOpenAd.Destroy(); appOpenAd = null; } }
Full code example
using System;
using UnityEngine;
using UnityEngine.UI;
using YandexMobileAds;
using YandexMobileAds.Base;
public class YandexMobileAdsAppOpenAdDemoScript : MonoBehaviour
{
private AppOpenAdLoader appOpenAdLoader;
private AppOpenAd appOpenAd;
private bool isColdStartAdShown = false;
private void Awake()
{
DontDestroyOnLoad(gameObject);
SetupLoader();
AppStateObserver.OnAppStateChanged += HandleAppStateChanged;
RequestAppOpenAd();
}
private void OnDestroy()
{
AppStateObserver.OnAppStateChanged -= HandleAppStateChanged;
}
private void SetupLoader()
{
appOpenAdLoader = new AppOpenAdLoader();
}
private void HandleAppStateChanged(object sender, AppStateChangedEventArgs args)
{
if (!args.IsInBackground)
{
ShowAppOpenAd();
}
}
private void ShowAppOpenAd()
{
if (appOpenAd != null)
{
appOpenAd.Show();
}
}
private async void RequestAppOpenAd()
{
string adUnitId = "demo-appopenad-yandex"; // replace with "R-M-XXXXXX-Y"
try
{
appOpenAd = await appOpenAdLoader.LoadAd(new AdRequest(adUnitId));
// Add events handlers for ad actions
appOpenAd.OnAdClicked += HandleAdClicked;
appOpenAd.OnAdShown += HandleAdShown;
appOpenAd.OnAdFailedToShow += HandleAdFailedToShow;
appOpenAd.OnAdDismissed += HandleAdDismissed;
appOpenAd.OnAdImpression += HandleImpression;
if (!isColdStartAdShown)
{
ShowAppOpenAd();
isColdStartAdShown = true;
}
}
catch (AdLoadingException e)
{
// Ad failed to load with {e.Message}
// Attempting to load a new ad from catch block is strongly discouraged.
}
}
public void HandleAdDismissed(object sender, EventArgs args)
{
// Called when ad is dismissed.
// Clear resources after Ad dismissed.
DestroyAppOpenAd();
// Now you can preload the next ad.
RequestAppOpenAd();
}
public void HandleAdFailedToShow(object sender, AdFailureEventArgs args)
{
// Called when an ad failed to show.
// Clear resources.
DestroyAppOpenAd();
// Now you can preload the next ad.
RequestAppOpenAd();
}
public void HandleAdClicked(object sender, EventArgs args)
{
// Called when a click is recorded for an ad.
}
public void HandleAdShown(object sender, EventArgs args)
{
// Called when ad is shown.
}
public void HandleImpression(object sender, ImpressionData impressionData)
{
// Called when an impression is recorded for an ad.
}
public void DestroyAppOpenAd()
{
if (appOpenAd != null)
{
appOpenAd.Destroy();
appOpenAd = null;
}
}
}
using System;
using UnityEngine;
using UnityEngine.UI;
using YandexMobileAds;
using YandexMobileAds.Base;
public class YandexMobileAdsAppOpenAdDemoScript : MonoBehaviour
{
private AppOpenAdLoader appOpenAdLoader;
private AppOpenAd appOpenAd;
private bool isColdStartAdShown = false;
private void Awake()
{
DontDestroyOnLoad(gameObject);
SetupLoader();
AppStateObserver.OnAppStateChanged += HandleAppStateChanged;
RequestAppOpenAd();
}
private void OnDestroy()
{
AppStateObserver.OnAppStateChanged -= HandleAppStateChanged;
}
private void SetupLoader()
{
appOpenAdLoader = new AppOpenAdLoader();
}
private void HandleAppStateChanged(object sender, AppStateChangedEventArgs args)
{
if (!args.IsInBackground)
{
ShowAppOpenAd();
}
}
private void ShowAppOpenAd()
{
if (appOpenAd != null)
{
appOpenAd.Show();
}
}
private void RequestAppOpenAd()
{
string adUnitId = "demo-appopenad-yandex"; // replace with "R-M-XXXXXX-Y"
AdRequest adRequest = new AdRequest(adUnitId);
appOpenAdLoader.LoadAd(
adRequest: adRequest,
onLoaded: HandleAdLoaded,
onFailed: HandleAdFailedToLoad);
}
public void HandleAdLoaded(AppOpenAd appOpenAd)
{
// The ad was loaded successfully. Now you can handle it.
this.appOpenAd = appOpenAd;
// Add events handlers for ad actions
this.appOpenAd.OnAdClicked += HandleAdClicked;
this.appOpenAd.OnAdShown += HandleAdShown;
this.appOpenAd.OnAdFailedToShow += HandleAdFailedToShow;
this.appOpenAd.OnAdDismissed += HandleAdDismissed;
this.appOpenAd.OnAdImpression += HandleImpression;
if (!isColdStartAdShown)
{
ShowAppOpenAd();
isColdStartAdShown = true;
}
}
public void HandleAdFailedToLoad(AdFailedToLoadEventArgs args)
{
// Ad failed to load with {args.Message}
// Attempting to load a new ad from the onFailed callback is strongly discouraged.
}
public void HandleAdDismissed(object sender, EventArgs args)
{
// Called when ad is dismissed.
// Clear resources after Ad dismissed.
DestroyAppOpenAd();
// Now you can preload the next ad.
RequestAppOpenAd();
}
public void HandleAdFailedToShow(object sender, AdFailureEventArgs args)
{
// Called when an ad failed to show.
// Clear resources.
DestroyAppOpenAd();
// Now you can preload the next ad.
RequestAppOpenAd();
}
public void HandleAdClicked(object sender, EventArgs args)
{
// Called when a click is recorded for an ad.
}
public void HandleAdShown(object sender, EventArgs args)
{
// Called when ad is shown.
}
public void HandleImpression(object sender, ImpressionData impressionData)
{
// Called when an impression is recorded for an ad.
}
public void DestroyAppOpenAd()
{
if (appOpenAd != null)
{
appOpenAd.Destroy();
appOpenAd = null;
}
}
}
Features of app open ad integration
- Loading can take a long time, so do not increase cold start time if the ad fails to load.
- Preload the ad in advance for display on a later hot start.
- We do not recommend loading app open ads and other ad formats at the same time on app start, because the app may be downloading data it needs. That can overload the device and the network and make ad loading slower.
- If loading failed, do not try to load a new ad again. If you must, limit the number of retries. That helps avoid constant failed requests and connection issues when limitations apply.
Testing ad integration at launch
Using demo ad units for ad testing
We recommend using test ads to test your integration for app open ads and your app itself.
To guarantee that test ads are returned for every ad request, we created a special demo ad placement ID. Use it to check your ad integration.
Demo adUnitId: demo-appopenad-yandex.
Warning
Before publishing your app in the store, make sure to replace the demo ad placement ID with a real one obtained from the Yandex Advertising Network interface.
You can find the list of available demo ad placement IDs in the Demo ad units for testing section.
Testing ad integration
You can check your integration of app open ads using the SDK's built-in analyzer.
The tool makes sure your app open ads are integrated properly and outputs a detailed report to the log. To view the report, search for the “YandexAds” keyword in the Logcat tool for Android app debugging.
adb logcat -v brief '*:S YandexAds'
If the integration is successful, you'll see this message:
adb logcat -v brief '*:S YandexAds'
mobileads$ adb logcat -v brief '*:S YandexAds'
I/YandexAds(13719): [Integration] Ad type App Open Ad was integrated successfully
If you're having problems integrating ads, you'll get a detailed report on the issues and recommendations for how to fix them.
Using demo ad units for ad testing
We recommend using test ads to test your integration for app open ads and your app itself.
To guarantee that test ads are returned for every ad request, we created a special demo ad placement ID. Use it to check your ad integration.
Demo adUnitId: demo-appopenad-yandex.
Warning
Before publishing your app in the store, make sure to replace the demo ad placement ID with a real one obtained from the Yandex Advertising Network interface.
You can find the list of available demo ad placement IDs in the Demo ad units for testing section.
Testing ad integration
You can test your ad integration using the native Console tool.
To view detailed logs, call the YandexAds class's enableLogging method.
YandexAds.enableLogging()
To view SDK logs, go to the Console tool and set Subsystem = com.mobile.ads.ads.sdk. You can also filter logs by category and error level.
If you're having problems integrating ads, you'll get a detailed report on the issues and recommendations for how to fix them.
Recommendations
-
Do not show the app open ad before the splash screen.
Showing the splash screen makes the experience smoother and helps the user know they opened the right app. On the same screen you can warn about upcoming advertising using a loading indicator or a short message that content will continue after the ad.
-
If there is a delay between requesting and showing the ad, the user may open your app briefly and then unexpectedly see an ad that does not match the content. That hurts UX; avoid it. One approach is to use a loading screen before the main content and start the ad from that screen. If the app opens content right after the splash, it is better not to show the ad.
-
Wait until new users open the app and use it several times before showing app open ads. Show the ad only to users who meet criteria in the app (e.g., completed a level, opened the app a certain number of times, are not in rewarded flows). Do not show the ad immediately after install.
-
Regulate how often you show the ad based on user behavior. Do not show it on every cold or hot start.
-
Show the ad only if the app stayed in the background for a set period (for example, 30 seconds, 2 minutes, 15 minutes).
-
Test thoroughly: each app is different and needs its own approach to maximize revenue without hurting retention or time in app. User behavior changes over time, so revisit your app open strategies periodically.
Additional resources
-
Link to GitHub.