First Look
Give CloudX the first chance to fill an ad placement, then fall back to your existing mediation setup
First Look gives CloudX the first chance to fill a placement while preserving your existing mediation setup as the fallback path. Start with one placement, verify load and show behavior, then expand to more placements.
These examples use an AdMob fallback through the Google Mobile Ads Unity Plugin. The same pattern applies to other fallback mediators: load CloudX first, load the fallback only if CloudX does not load, and keep the game flow moving when neither source is ready.
There are two shapes to the rule, and this page covers one controller for each:
- Banner — an inline ad stays on screen and is never consumed, so the controller needs an explicit pass cycle to give CloudX another first look. MREC follows this controller exactly.
- Interstitial — a fullscreen ad is consumed by being shown, so the SDKs’ own “is an ad ready” answers go false on their own and the next
Load()starts at CloudX again. Rewarded follows this controller exactly.
Banner
A banner is not the interstitial with different method names. A fullscreen ad is consumed by being shown, so its readiness checks go false on their own and the next Load() starts at CloudX again — the interstitial below rests on that. An inline ad is never consumed: CloudX banners report load and click, with no show or close callback. Left alone, the first fill owns the placement until the scene is destroyed, so a single CloudX no-fill hands the slot to your fallback for the rest of the session.
The controller solves that with a pass cycle. One pass is one ad opportunity: CloudX first, AdMob only if CloudX fails, winner displayed. Displaying the winner ends the pass and raises PassSpent; you start the next one, and it begins at CloudX again.
FirstLookBannerController.cs
Which SDK fills a pass. The complete controller, commented at the lines that matter.
FirstLookBannerCycle.cs
When the next pass starts. The scene’s half of the contract, as a MonoBehaviour.
FirstLookSource.cs
The CloudX / AdMob enum every event reports.
Copy all three. Between them they are the whole flow.
They live in the CloudX Unity demo app, which is the version under CI and verified on device, so it is the one that gets fixed when something is wrong. Read them there rather than from a copy on this page — a copy would drift, and it would be the stale one.
Why the host is a separate file
The controller is a plain class with no clock — no Update, no coroutine, no Invoke — so it cannot decide when the next pass starts. FirstLookBannerCycle is that clock, and the three rules it keeps are the ones an integration gets wrong:
- Start the next pass on
PassSpent, after a cooldown. 30 seconds is a normal banner interval. Starting it immediately is a request loop, because the new ad renders into the visible slot and ends the next pass at once. - Cancel that pending pass when the banner is hidden. Otherwise a hidden slot keeps requesting for the rest of the session.
- Do not retry a failed load while it is hidden. Cancelling alone does not cover this: a load already in flight when the player hides completes after it. A fill is harmless — it is banked for the next
Show(). A failure is not: its retry would start the requests up again, and by thenCancelInvokehas nothing left to cancel.
Take the cycle component as it is and you get all three; the cooldown, the backoff and the hide handling are implemented and commented there. Which SDK wins a pass, and how a fill is banked until the slot is shown, is the controller’s side and is commented in that file.
Using it in your scene
Add FirstLookBannerCycle to a GameObject, then in the Inspector:
- drag that component into the host’s
bannerfield, - fill in
cloudXBannerAdUnitIdandadMobBannerAdUnitId— all three are serialized fields and start empty, andBeginneeds both ids, - point your button’s
OnClickatOnBannerButton.
Then call BeginFirstLook once CloudX has answered — initialized, failed, or past a timeout of your own. Everything else — cooldown, backoff, cancelling on hide — is inside the cycle.
You do not need to wait for Google Mobile Ads as well. It queues loads issued while it is still initializing, and the fallback is lazy in any case, so waiting on it would only delay the first pass.
using UnityEngine;
public class BannerButton : MonoBehaviour
{
[SerializeField] private FirstLookBannerCycle banner;
[SerializeField] private string cloudXBannerAdUnitId;
[SerializeField] private string adMobBannerAdUnitId;
void Start()
{
banner.AdShown += source => Debug.Log($"First Look banner shown: {source}");
}
/*
* Call this from your CloudX initialization result - initialized, failed,
* or past your own timeout - passing whether CloudX actually came up.
* Not from Start(): that runs when the object is enabled, which says
* nothing about whether the SDK has answered yet.
*
* Begin preloads one pass, so an ad is ready the first time the player
* asks for one.
*/
public void BeginFirstLook(bool cloudXAvailable)
{
banner.Begin(cloudXBannerAdUnitId, adMobBannerAdUnitId, cloudXAvailable);
}
// Hook this to your button.
public void OnBannerButton() => banner.Toggle();
}Pass cloudXAvailable: false if CloudX initialization failed; the cycle then serves the fallback directly instead of waiting for load callbacks that will never arrive.
The demo does the same in FirstLookScreen.cs, calling Begin from the CloudX initialization result rather than from Start. It differs in one detail that is not a requirement: it adds the cycle with AddComponent at runtime instead of keeping it in the scene, because it builds the whole banner flow only once initialization has answered. Its ad unit ids are compile-time constants — the value it waits for is cloudXAvailable.
Interstitial
The simpler of the two, because showing consumes the ad: no flag has to be cleared and no cycle has to be driven. Rewarded is this controller with the rewarded calls substituted, plus the reward callback.
FirstLookInterstitialController.cs
The complete controller, commented at the lines that matter. Copy it as is.
FirstLookSource.cs
The CloudX / AdMob enum every event reports. Copy it too.
Call Show() at the placement moment. If it returns false, neither CloudX nor the fallback had a ready ad, so continue the game flow without showing an ad.
if (!firstLookInterstitial.Show())
{
ContinueToNextScene();
}After a show, close, or terminal failure, call Load() again when your game is ready to prepare the next placement opportunity. Call Dispose() from the owning MonoBehaviour when it is destroyed.
Check your integration
The controller decides the order. What it cannot decide is whether your app key, your ad unit ids, your dashboard configuration and — for the banner — your scene wiring are right, and those live in your project. When one of them is wrong the symptom is silent: the fallback serves, ads appear, and everything looks healthy.
One check covers it. Log the source, which every event already carries:
banner.AdLoaded += (source) => Debug.Log($"First Look banner loaded: {source}");Run with your real ad unit ids and look for CloudX on a fill. If you only ever see AdMob, CloudX is not filling at all — check the app key, the ad unit ids and the dashboard configuration before you look at the controller.
For a banner, watch for longer than one cooldown: a fresh CloudX attempt should precede every AdMob fill, not just the first. If CloudX is asked once and never again, PassSpent is not wired, or something other than hiding is cancelling the pending pass.
To exercise the fallback on purpose — to confirm your AdMob unit is configured before you ship — point the CloudX ad unit id at a string that is not in your dashboard, so every CloudX load fails and the fallback has to serve.