Adding Ads to a Unity Game: A Practical Guide
How to add rewarded, interstitial and banner ads to a Unity game with the Ads Mediation package (LevelPlay), plus testing, privacy and the AdMob alternative.
12 min read · Updated
For a new Unity game, the current route to ads is the Ads Mediation package (package name com.unity.services.levelplay), which installs Unity LevelPlay. You create your app and ad units on the LevelPlay platform, initialize with LevelPlay.Init, and then create rewarded, interstitial and banner objects that you load and show. Unity Ads still exists, but as one ad network inside that stack rather than as a standalone SDK you integrate by hand.
That is a change from older tutorials, and a lot of search results still teach the old way. If you see Advertisement.Initialize(gameId, testMode, this) in a video or blog post, it belongs to the Advertisement Legacy package. Unity's package manual now says that direct integration of the Unity Ads SDK through that package is no longer supported for monetization, as of January 31, 2026. Unity's migration guide words it more gently: direct integrations might see reduced ad performance starting April 1, 2026, and the Unity Ads network will keep filling them. The two pages disagree on tone, and both point the same direction.
This guide walks through the dashboard setup, installation, a working script for rewarded and interstitial ads, a banner, testing, privacy settings and the AdMob alternative. Revenue figures come from our benchmark tables and are estimates.
Pick the path before you write code
Four routes are common for a Unity game, and they overlap less than people expect.
| Path | What it is | Use it when |
|---|---|---|
| Ads Mediation package (LevelPlay) | Unity's mediation SDK, with Unity Ads and ironSource Ads among the networks | You want the current Unity-recommended route and several networks competing |
| Advertisement Legacy package | The old direct Unity Ads SDK (com.unity.ads) | Only to keep an old project running while you migrate |
| Google Mobile Ads Unity plugin | AdMob's own SDK for Unity | You already use AdMob, or want its demand and reporting first |
| AppLovin MAX | A separate mediation platform | You prefer its tooling; see our AppLovin MAX guide |
The short version is that LevelPlay is the default for Unity-first teams, and AdMob is the sensible alternative for people who already have an AdMob account from a mobile app. You can also run AdMob as a network inside LevelPlay, because Google AdMob is on its list of mediated networks with banner, interstitial and rewarded support.
Our guide to LevelPlay and ironSource explains how the platform and the networks relate, and mediation versus a single network covers the case for adding more than one source of demand.
Set up the app on the LevelPlay platform
Code comes second. The LevelPlay dashboard produces the strings your code needs.
- Log in to the LevelPlay platform and choose Add App. Do Android and iOS as separate apps.
- Open Ad Units for the app and create the formats you plan to use: rewarded, interstitial, banner.
- Save the App Key and each Ad Unit ID from the Apps page.
The app key goes into LevelPlay.Init. The ad unit IDs go into the constructors of the ad objects. Unity's migration page lists exactly these steps, and its remark that LevelPlay needs you to create an ad instance per ad unit is the biggest structural difference from the old API. There is no global Advertisement.Show("Rewarded_Android") any more. Each placement is an object you keep.
In the same dashboard you will later set up networks, mediation groups and any floor prices. For a first build, the defaults are fine. When you get to that stage, bidding vs waterfall is worth reading before you touch the numbers.
Install the Ads Mediation package
In the Unity Editor, open Window > Package Manager, switch to Packages: Unity Registry, search for Ads Mediation and install it. There is also a downloadable .unitypackage on Unity's GitHub for teams that avoid the registry, but the registry route is the recommended one.
LevelPlay needs a dependency resolver for Android. If Unity offers to install the Mobile Dependency Resolver, say yes. If your project already has the External Dependency Manager for Unity, keep it. After you change anything in the network manager, run Assets > Mobile Dependency Manager > Android Resolver > Resolve so the Gradle dependencies update.
Once installed, an Ads Mediation entry appears in the top menu bar. That is where you add or update ad networks. The Unity Ads adapter comes installed by default alongside ironSource Ads, so you do not have to add Unity's own network as a separate step.
If you are migrating, do not leave both packages in the project. Unity's migration guide warns that installing LevelPlay beside the Advertisement Legacy package might cause the project to malfunction. Map your old calls first, confirm ads work, then remove Advertisement Legacy from Packages: In Project.
Two platform notes from the integration docs. On Android, apps that target API level 33 or higher must declare the advertising ID permission, com.google.android.gms.permission.AD_ID, in the manifest. On iOS, recent package versions (9.1.0 onward) manage the SKAdNetwork entries for the networks you install, and Apple's privacy manifest requirements apply as well. Check Unity's package integration page for the exact manifest and plist details, since they move with each release.
Initialize the SDK
Register the listeners before you call Init, and create ad objects only after OnInitSuccess fires. Unity's docs are firm on that order.
using Unity.Services.LevelPlay;
using UnityEngine;
public class AdsManager : MonoBehaviour
{
const string AppKey = "YOUR_APP_KEY";
void Start()
{
DontDestroyOnLoad(gameObject);
LevelPlay.OnInitSuccess += OnInitSuccess;
LevelPlay.OnInitFailed += OnInitFailed;
LevelPlay.Init(AppKey);
}
void OnInitFailed(LevelPlayInitError error)
{
Debug.LogWarning($"LevelPlay init failed: {error}");
}
// OnInitSuccess is shown in the next section.
}
If initialization fails, the docs recommend trying again later, when the connection is back or the cause is resolved. Do not loop. Retry when the app returns to the foreground or when the player reaches the next menu.
If you use server-to-server reward callbacks, LevelPlay.Init also accepts a user ID as its second argument.
Rewarded and interstitial ads in C#
Here is a single AdsManager that handles both formats. It follows the shape in Unity's rewarded and interstitial pages: create the object, subscribe to events, call LoadAd, check IsAdReady before ShowAd, and load again after the ad closes.
LevelPlayRewardedAd rewarded;
LevelPlayInterstitialAd interstitial;
System.Action pendingReward;
void OnInitSuccess(LevelPlayConfiguration config)
{
rewarded = new LevelPlayRewardedAd("YOUR_REWARDED_AD_UNIT_ID");
rewarded.OnAdLoaded += info => Debug.Log("Rewarded ready");
rewarded.OnAdLoadFailed += error => Debug.Log($"Rewarded load failed: {error}");
rewarded.OnAdDisplayed += info => AudioListener.pause = true;
rewarded.OnAdDisplayFailed += (info, error) => AudioListener.pause = false;
rewarded.OnAdRewarded += (info, reward) =>
{
pendingReward?.Invoke();
pendingReward = null;
};
rewarded.OnAdClosed += info =>
{
AudioListener.pause = false;
rewarded.LoadAd();
};
rewarded.LoadAd();
interstitial = new LevelPlayInterstitialAd("YOUR_INTERSTITIAL_AD_UNIT_ID");
interstitial.OnAdLoadFailed += error => Debug.Log($"Interstitial load failed: {error}");
interstitial.OnAdDisplayed += info => AudioListener.pause = true;
interstitial.OnAdClosed += info =>
{
AudioListener.pause = false;
interstitial.LoadAd();
};
interstitial.LoadAd();
}
public void ShowRewarded(System.Action onReward)
{
if (rewarded != null && rewarded.IsAdReady())
{
pendingReward = onReward;
rewarded.ShowAd();
}
}
public void ShowInterstitial()
{
if (interstitial != null && interstitial.IsAdReady())
interstitial.ShowAd();
}
Paste those members into the class from the previous section. A few details are worth stating.
OnAdRewarded and OnAdClosed are asynchronous, and Unity's docs tell you to grant the reward even if OnAdRewarded arrives after OnAdClosed. That is why the reward lives in its own pending callback and is not tied to the close event. The reward event fires when the player completes the video, so a player who skips out never gets paid.
The object is reusable. You do not recreate it for every load, you call LoadAd again. Each ad object should also have its own listener methods rather than sharing handlers across objects.
The display-failed event passes both the ad info and an error on the interstitial and rewarded pages. Unity's migration page shows a different parameter type for the rewarded version of that event, so if your compiler complains about a signature, trust the error message and your IDE's autocomplete over any single tutorial, including this one.
Pausing audio on display is a habit, not a requirement from the docs. Some ads start with sound while your music keeps playing underneath, and a game that fights with its own ads gets bad reviews. Test it on a real phone.
If you set up placements in the dashboard for pacing and capping, pass the placement name to ShowAd and check LevelPlayRewardedAd.IsPlacementCapped(name) first. Placement names must match the dashboard exactly.
Adding a banner
Banners are the least interesting format in a game, because the screen is usually full. If your genre has a menu or a puzzle board with room at the bottom, one is straightforward:
LevelPlayBannerAd banner;
void CreateBanner()
{
var config = new LevelPlayBannerAd.Config.Builder()
.SetSize(LevelPlayAdSize.CreateAdaptiveAdSize())
.SetPosition(LevelPlayBannerPosition.BottomCenter)
.SetDisplayOnLoad(true)
.Build();
banner = new LevelPlayBannerAd("YOUR_BANNER_AD_UNIT_ID", config);
banner.LoadAd();
}
Unity recommends the adaptive size. A destroyed banner cannot be shown again, so DestroyAd() it when you are done and create a new object if you need one later. The docs describe the banner APIs as beta, so skim the page for changes before you ship.
Where ads belong in a game
Code is the easy part. Placement decides whether players tolerate the ads and whether the money is good.
Rewarded ads work when the player asks for them. Offer a continue after a loss, a double-coin multiplier on the results screen, or a free hint. Never gate core progress behind a video. Our rewarded vs interstitial guide explains why players accept the first and resent the second, and the rewarded format page shows how well it pays in each region.
Interstitials belong at breaks the player already expects: after a level ends, before a retry, on returning to the main menu. Not mid-action, and not on the first launch. A starting rule many teams use is a minimum gap, say 60 to 120 seconds between interstitials, and no interstitial in the first session. That is a starting point to tune against retention, not a Unity requirement.
Keep one ad per natural break. Two interstitials back to back is the quickest way to turn a good game into a deleted one. And before you decide the numbers, remember that ad-funded play lives or dies by what each daily player earns, which is the subject of ARPDAU and LTV for ad-funded apps.
What this might earn: a worked example
This is an example with stated assumptions, not a forecast. Take a casual game (our category multiplier is 0.95) with 10,000 daily active users. Each player sees 2 rewarded ads and 3 interstitials a day. We use the Unity Ads rewarded and interstitial figures in our benchmark tables and assume every request fills.
| Audience | Rewarded (2 per user) | Interstitial (3 per user) | Daily total after 0.95 |
|---|---|---|---|
| Tier 1 (eCPM $13.00 / $9.00) | 20,000 x $13.00 / 1,000 = $260 | 30,000 x $9.00 / 1,000 = $270 | about $503 |
| Tier 3 (eCPM $1.30 / $0.90) | 20,000 x $1.30 / 1,000 = $26 | 30,000 x $0.90 / 1,000 = $27 | about $50 |
The same game with the same behavior earns roughly ten times less when the audience sits in Tier 3. Over 30 days the Tier 1 row is near $15,000 and the Tier 3 row near $1,500. Where your players live matters more than any placement tweak, so work out your likely audience mix before you plan a budget. Our Unity Ads revenue calculator lets you swap in your own audience mix, and the answer page on daily players runs a similar case.
Test before you release
Unity gives you three ways to test, and you should use all of them in order.
The first is mock ads in the Editor. After initialization, the LevelPlay APIs can show mock banner, interstitial and rewarded ads in Play mode, using the same calls as production. Unity's mock ads page uses LevelPlay.Init("editor") and a banner ID of editor_banner for this. They do not simulate network delay, load failures or reward logic, so they only prove your flow and layout.
The second is the integration test suite, on a device build. Enable it before initialization, then launch it after init succeeds:
LevelPlay.SetMetaData("is_test_suite", "enable"); // before Init
// later, after initialization succeeds:
LevelPlay.LaunchTestSuite();
The suite checks your integration and lets you load and show ads from each configured network. It requires portrait orientation, and the page marks the metadata flag as beta. For bidding networks it has a Live and Test toggle, while non-bidding networks always use live ads, so be careful about tapping through them on a device tied to your account. The same test suite page lists the status colors. LevelPlay.ValidateIntegration() is a separate internal check of your package and dependencies.
The third is a plain release-like build on a real phone, with no test tools, watching the logs. Check that OnAdLoaded fires, that the reward is granted once, and that the game resumes cleanly after the ad. Do not click live ads yourself. See invalid traffic for what happens when you do.
Consent, kids and platform privacy settings
Privacy calls should go in before ads load. LevelPlay exposes them through LevelPlayPrivacySettings. On SDK 9.5.0 and later, SetGDPRConsent(true) passes a consent flag, and from 9.4.0 there are SetCCPA and SetCOPPA. The regulation page also says GDPR consent is shared automatically from Google's UMP or a CMP that supports Google Additional Consent, starting with SDK 7.7.0, so you do not have to hand-write it if you already run a compliant consent message. Method names have changed over the SDK's life, and older ones are marked deprecated, so check Unity's regulation page for your version.
If your game is aimed at children, or has a mixed audience, the rules change completely, and you should read ads in kids apps before enabling any ad format. For everyone else in Europe, consent messages setup covers what the message has to do. On iOS, the tracking prompt affects what advertisers will pay, and ATT and iOS ad earnings explains how much.
AdMob in Unity: the alternative
Google ships its own Unity plugin, and for an indie team that already has an AdMob account it is a sound route. The Unity quick start asks for Unity 2019.4 or newer (2022.2 or newer recommended), Android minimum API level 24, and for iOS a target of 13.0 or higher with Xcode 16. Install through OpenUPM with openupm add com.google.ads.mobile, or import the .unitypackage from GitHub, then enter your AdMob app IDs in Assets > Google Mobile Ads > Settings.
The code looks different from LevelPlay. Ads are loaded with static calls, and a loaded ad is single use:
using GoogleMobileAds.Api;
RewardedAd rewardedAd;
void LoadRewarded(string adUnitId)
{
RewardedAd.Load(adUnitId, new AdRequest(), (RewardedAd ad, LoadAdError error) =>
{
if (error != null) return;
rewardedAd = ad;
});
}
void ShowRewarded()
{
if (rewardedAd != null && rewardedAd.CanShowAd())
rewardedAd.Show(reward => Debug.Log("Reward earned"));
}
Call MobileAds.Initialize once at launch, before the first load, and set any consent or child-directed flags before that call because ads can preload during initialization. The plugin raises ad events on a background thread, so anything that touches Unity objects inside a callback has to be scheduled on the main thread, using MobileAdsEventExecutor.ExecuteInUpdate. That is the usual first bug. Use Google's published demo ad unit IDs while developing, from Google's Unity test ads page, and never your real ones.
Which should you pick? A pure Unity game with no AdMob history tends to land on LevelPlay. A studio that ships Android apps and Unity games and wants one reporting view may prefer AdMob. The AdMob vs Unity comparison puts our estimates side by side,.
Common questions
Is Unity Ads shut down?
No. The Unity Ads network is still active, and it is an available network inside LevelPlay. What Unity has moved away from is direct integration through the Advertisement Legacy package, which it says is no longer supported for monetization. Check the package manual for the current status.
Do I need to rewrite everything to migrate?
Mostly yes for the ad code, but it is a small amount of code. Unity publishes a mapping table from the old Advertisement calls to the LevelPlay equivalents in its migration guide. The bigger job is the dashboard setup and the testing.
Can I use LevelPlay and AdMob in the same game?
Yes, by adding AdMob as a network inside LevelPlay, which uses AdMob's demand through LevelPlay's mediation. Running both SDKs separately for the same placements is possible but messy, and it makes your reports harder to read.
Why do I see no ads in the Editor?
The Editor shows mock ads, not real ones. Use them for layout and flow, and a device build for everything else.
What to do next
Create the app and three ad units on the LevelPlay platform, install the Ads Mediation package, and get a rewarded ad working in a device build using the test suite. That is a single afternoon of work for most games.
Then decide where the rewarded offer sits, and write that on paper before you code it. After you have a few days of real data, plug your own daily users and impressions per user into the Unity Ads revenue calculator or the LevelPlay revenue calculator, and compare against what the dashboard reports. If the two are far apart, check your impressions per user first. If your next project uses a different engine, AdMob in Flutter covers the Flutter equivalent.