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.

This example uses an AdMob interstitial fallback through react-native-google-mobile-ads. 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.

useFirstLookInterstitial.ts
import { useCallback, useEffect, useRef } from 'react';
import { useInterstitialAd } from 'react-native-google-mobile-ads';
import { useCloudXInterstitial } from 'cloudx-react-native';

export function useFirstLookInterstitial(
  cloudXAdUnitId: string,
  adMobAdUnitId: string,
) {
  const {
    error: cloudXError,
    isLoaded: isCloudXLoaded,
    isLoading: isCloudXLoading,
    load: loadCloudX,
    show: showCloudX,
  } = useCloudXInterstitial(cloudXAdUnitId);
  const {
    error: adMobError,
    isClosed: isAdMobClosed,
    isLoaded: isAdMobLoaded,
    load: loadAdMob,
    show: showAdMob,
  } = useInterstitialAd(adMobAdUnitId);
  const adMobLoadRequested = useRef(false);
  const state = useRef({
    isAdMobLoaded,
    isCloudXLoaded,
    isCloudXLoading,
  });

  state.current = {
    isAdMobLoaded,
    isCloudXLoaded,
    isCloudXLoading,
  };

  useEffect(() => {
    if (
      cloudXError &&
      !isAdMobLoaded &&
      !adMobLoadRequested.current
    ) {
      adMobLoadRequested.current = true;
      loadAdMob();
    }
  }, [cloudXError, isAdMobLoaded, loadAdMob]);

  useEffect(() => {
    if (adMobError || isAdMobClosed) {
      adMobLoadRequested.current = false;
    }
  }, [adMobError, isAdMobClosed]);

  const load = useCallback(() => {
    const current = state.current;

    if (
      current.isCloudXLoading ||
      current.isCloudXLoaded ||
      current.isAdMobLoaded ||
      adMobLoadRequested.current
    ) {
      return;
    }

    loadCloudX();
  }, [loadCloudX]);

  const show = useCallback((): boolean => {
    const current = state.current;

    if (current.isCloudXLoaded) {
      showCloudX();
      return true;
    }

    if (current.isAdMobLoaded) {
      showAdMob();
      return true;
    }

    return false;
  }, [showAdMob, showCloudX]);

  return {
    isReady: isCloudXLoaded || isAdMobLoaded,
    load,
    show,
  };
}

Call load() when the screen is ready to prepare the placement. At the placement moment, call show(). If it returns false, neither CloudX nor the fallback had a ready ad, so continue the app flow without showing an ad.

GameScreen.tsx
const firstLookInterstitial = useFirstLookInterstitial(
  CLOUDX_INTERSTITIAL_AD_UNIT_ID,
  ADMOB_INTERSTITIAL_AD_UNIT_ID,
);

useEffect(() => {
  firstLookInterstitial.load();
}, [firstLookInterstitial.load]);

const continueToNextScreen = () => {
  if (!firstLookInterstitial.show()) {
    navigation.navigate('NextScreen');
  }
};

After a show, close, or terminal failure, call load() again when your app is ready to prepare the next placement opportunity. Both underlying hooks release their event subscriptions when the component unmounts; the CloudX hook also destroys its interstitial instance.