> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cloudx.io/llms.txt
> Use this file to discover all available pages before exploring further.

# First Look

> Try CloudX first while keeping an existing Android mediation placement as fallback

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.

This example uses an AdMob interstitial fallback. The same pattern applies to other fallback mediators: load CloudX first, load the fallback only if CloudX does not load, and keep the app flow moving when neither source is ready.

<Info>
  Initialize CloudX and Google Mobile Ads before creating the controller. Keep your existing pacing, retry, and placement timing rules around this controller.
</Info>

```kotlin FirstLookInterstitialController.kt theme={null}
import android.app.Activity
import com.google.android.gms.ads.AdError
import com.google.android.gms.ads.AdRequest
import com.google.android.gms.ads.FullScreenContentCallback
import com.google.android.gms.ads.LoadAdError
import com.google.android.gms.ads.interstitial.InterstitialAd
import com.google.android.gms.ads.interstitial.InterstitialAdLoadCallback
import io.cloudx.sdk.CloudX
import io.cloudx.sdk.CloudXAd
import io.cloudx.sdk.CloudXError
import io.cloudx.sdk.CloudXInterstitialAd
import io.cloudx.sdk.CloudXInterstitialListener

class FirstLookInterstitialController(
    private val activity: Activity,
    private val cloudXAdUnitId: String,
    private val adMobAdUnitId: String,
) {
    enum class Source {
        CLOUDX,
        ADMOB,
    }

    interface Listener {
        fun onAdLoaded(source: Source) {}
        fun onAdLoadFailed(source: Source, message: String?) {}
        fun onAdShown(source: Source) {}
        fun onAdShowFailed(source: Source, message: String?) {}
        fun onAdClosed(source: Source) {}
        fun onAdClicked(source: Source) {}
    }

    var listener: Listener? = null

    private val cloudXInterstitial: CloudXInterstitialAd =
        CloudX.createInterstitial(activity, cloudXAdUnitId)

    private var adMobInterstitial: InterstitialAd? = null
    private var isLoadingCloudX = false
    private var isLoadingAdMob = false

    init {
        cloudXInterstitial.listener = createCloudXListener()
    }

    fun load() {
        if (isLoadingCloudX || isLoadingAdMob || cloudXInterstitial.isAdReady || adMobInterstitial != null) {
            return
        }

        isLoadingCloudX = true
        cloudXInterstitial.load()
    }

    fun show(): Boolean {
        if (cloudXInterstitial.isAdReady) {
            cloudXInterstitial.show(activity)
            return true
        }

        return showAdMobFallback()
    }

    fun destroy() {
        cloudXInterstitial.destroy()
        adMobInterstitial = null
        listener = null
    }

    private fun createCloudXListener() = object : CloudXInterstitialListener {
        override fun onAdLoaded(cloudXAd: CloudXAd) {
            isLoadingCloudX = false
            listener?.onAdLoaded(Source.CLOUDX)
        }

        override fun onAdLoadFailed(adUnitId: String, cloudXError: CloudXError) {
            isLoadingCloudX = false
            loadAdMobFallback()
        }

        override fun onAdDisplayed(cloudXAd: CloudXAd) {
            listener?.onAdShown(Source.CLOUDX)
        }

        override fun onAdDisplayFailed(cloudXAd: CloudXAd, cloudXError: CloudXError) {
            if (showAdMobFallback()) {
                return
            }

            listener?.onAdShowFailed(Source.CLOUDX, cloudXError.message)
        }

        override fun onAdHidden(cloudXAd: CloudXAd) {
            listener?.onAdClosed(Source.CLOUDX)
        }

        override fun onAdClicked(cloudXAd: CloudXAd) {
            listener?.onAdClicked(Source.CLOUDX)
        }
    }

    private fun loadAdMobFallback() {
        if (isLoadingAdMob || adMobInterstitial != null) {
            return
        }

        isLoadingAdMob = true
        InterstitialAd.load(
            activity,
            adMobAdUnitId,
            AdRequest.Builder().build(),
            object : InterstitialAdLoadCallback() {
                override fun onAdLoaded(interstitialAd: InterstitialAd) {
                    isLoadingAdMob = false
                    adMobInterstitial = interstitialAd.apply {
                        fullScreenContentCallback = createAdMobFullScreenCallback()
                    }
                    listener?.onAdLoaded(Source.ADMOB)
                }

                override fun onAdFailedToLoad(loadAdError: LoadAdError) {
                    isLoadingAdMob = false
                    adMobInterstitial = null
                    listener?.onAdLoadFailed(Source.ADMOB, loadAdError.message)
                }
            },
        )
    }

    private fun showAdMobFallback(): Boolean {
        val ad = adMobInterstitial ?: return false
        ad.show(activity)
        return true
    }

    private fun createAdMobFullScreenCallback() = object : FullScreenContentCallback() {
        override fun onAdShowedFullScreenContent() {
            adMobInterstitial = null
            listener?.onAdShown(Source.ADMOB)
        }

        override fun onAdDismissedFullScreenContent() {
            adMobInterstitial = null
            listener?.onAdClosed(Source.ADMOB)
        }

        override fun onAdFailedToShowFullScreenContent(adError: AdError) {
            adMobInterstitial = null
            listener?.onAdShowFailed(Source.ADMOB, adError.message)
        }

        override fun onAdClicked() {
            listener?.onAdClicked(Source.ADMOB)
        }
    }
}
```

Use `show()` at the placement moment. If it returns `false`, neither CloudX nor the fallback had a ready ad, so continue the app flow without showing an ad.

```kotlin theme={null}
if (!firstLookInterstitial.show()) {
    continueToNextScreen()
}
```

After a show, close, or terminal failure, call `load()` again when your app is ready to prepare the next placement opportunity.

<Tip>
  This sample keeps the fallback lazy: AdMob loads only after CloudX fails to load. Do not parallel-load both sources unless CloudX recommends a different rollout strategy for your app.
</Tip>
