---
title: Rewarded ads
description: Display full-screen rewarded ads that reward users for completing an action, with optional server-side verification.
---

Rewarded Ads are full-screen ads that cover the interface of an app until closed by the user. The content of a rewarded
advert is controlled via the Google AdMob dashboard.

The purpose of a rewarded ad is to reward users with _something_ after completing an action inside of the advert, such
as watching a video or submitting an option via an interactive form. If the user completes the action, you can reward them
with something (e.g. in-game currency).

<img
  width="300"
  src="https://developers.google.com/static/admob/images/format-rewarded.svg"
  alt="Rewarded ad offering an in-app reward"
/>

<Warning>
  Complete consent and SDK initialization before calling `load()`. See [Consent & privacy
  basics](/consent-basics) and the shared [load best
  practices](/ad-formats#load-and-refresh-best-practices).
</Warning>

To create a new rewarded ad, call the `createForAdRequest` method from the `RewardedAd` class. The first argument
of the method is the "Ad Unit ID". For testing, we can use a Test ID, however for production the ID from the
Google AdMob dashboard under "Ad units" should be used:

```js
import { RewardedAd, TestIds } from 'react-native-google-mobile-ads';

const adUnitId = __DEV__ ? TestIds.REWARDED : 'ca-app-pub-xxxxxxxxxxxxx/yyyyyyyyyyyyyy';

const rewarded = RewardedAd.createForAdRequest(adUnitId, {
  keywords: ['fashion', 'clothing'],
});
```

The second argument is additional optional request options object to be sent whilst loading an advert, such as keywords & location.
Setting additional request options helps AdMob choose better tailored ads from the network.
View the [`RequestOptions`](https://github.com/invertase/react-native-google-mobile-ads/blob/main/packages/core/src/types/RequestOptions.ts) source code to see the full range of options available.

The call to `createForAdRequest` returns an instance of the [`RewardedAd`](https://github.com/invertase/react-native-google-mobile-ads/blob/main/packages/core/src/ads/RewardedAd.ts) class,
which provides a number of utilities for loading and displaying rewarded ads.

To listen to events, such as when the advert from the network has loaded or when an error occurs, we can subscribe via the
`addAdEventListener` method:

```js
import React, { useEffect, useState } from 'react';
import { Button } from 'react-native';
import {
  AdEventType,
  RewardedAd,
  RewardedAdEventType,
  TestIds,
} from 'react-native-google-mobile-ads';

const adUnitId = __DEV__ ? TestIds.REWARDED : 'ca-app-pub-xxxxxxxxxxxxx/yyyyyyyyyyyyyy';

const rewarded = RewardedAd.createForAdRequest(adUnitId, {
  keywords: ['fashion', 'clothing'],
});

function App() {
  const [loaded, setLoaded] = useState(false);

  useEffect(() => {
    const unsubscribeLoaded = rewarded.addAdEventListener(RewardedAdEventType.LOADED, () => {
      setLoaded(true);
    });
    const unsubscribeEarned = rewarded.addAdEventListener(
      RewardedAdEventType.EARNED_REWARD,
      reward => {
        console.log('User earned reward of ', reward);
      },
    );
    const unsubscribePaid = rewarded.addAdEventListener(AdEventType.PAID, event => {
      console.log('Rewarded revenue', event.value, event.currency);
    });
    const unsubscribeClosed = rewarded.addAdEventListener(AdEventType.CLOSED, () => {
      setLoaded(false);
      // Preload the next ad on the same instance.
      rewarded.load();
    });

    // Start loading the rewarded ad straight away
    rewarded.load();

    // Unsubscribe from events on unmount
    return () => {
      unsubscribeLoaded();
      unsubscribeEarned();
      unsubscribePaid();
      unsubscribeClosed();
    };
  }, []);

  // No advert ready to show yet
  if (!loaded) {
    return null;
  }

  return (
    <Button
      title="Show Rewarded Ad"
      onPress={() => {
        // Not loaded, already showing, or a platform decline reject; a destroyed ad throws.
        rewarded.show().catch(console.warn);
      }}
    />
  );
}
```

The code above subscribes to the rewarded ad events (via `addAdEventListener()`) and immediately starts to load a new advert from
the network (via `load()`). Once an advert is available, local state is set, re-rendering the component showing a `Button`.
When pressed, the `show` method on the rewarded ad instance is called and the advert is shown over-the-top of your
application.

Like Interstitial Ads, you can listen to the events with the `addAdEventListener` such as when the user clicks the advert or closes
the advert and returns back to your app. However, you can listen to an extra `EARNED_REWARD` event which is triggered when user completes the
advert action. An additional `reward` payload is sent with the event, containing the amount and type of rewarded (specified via the dashboard).

To learn more, view the [`RewardedAdEventType`](https://github.com/invertase/react-native-google-mobile-ads/blob/main/packages/core/src/RewardedAdEventType.ts) source code.

The sample reuses the same `RewardedAd` instance: after `CLOSED`, it calls `load()` again so the next
advert is ready when the user next opts in.
Forward `AdEventType.PAID` payloads to your
[revenue telemetry](/revenue-telemetry-and-auction-diagnostics) pipeline.

## Server-side verification (SSV)

While the `EARNED_REWARD` event only occurs on the client, Server Side Verification (or SSV) can be used for confirming a user completed an advert action. For this, you have to specify the Server Side Verification callback URL in your Ads dashboard.

You can customize SSV parameters when your SSV callback is called by setting the `serverSideVerificationOptions` field in your [`RequestOptions`](https://github.com/invertase/react-native-google-mobile-ads/blob/main/packages/core/src/types/RequestOptions.ts) parameter.

```js
const rewardedAd = RewardedAd.createForAdRequest(adUnitId, {
  serverSideVerificationOptions: {
    userId: '9999',
    customData: 'my-custom-data',
  },
});
```

If you request an Advert as in the example above, AdMob will call your server with the `userId` and `customData` fields as shown below:

```
[14/Aug/2020 12:51:43] "GET /views/admob-ssv/?ad_network=...&ad_unit=...&custom_data=my-custom-data&reward_amount=1&reward_item=test_reward_item&timestamp=1597377102267&transaction_id=148cc85...&user_id=9999&signature=MEUCIQCQSi3cQ2PlxlEAkpN...&key_id=3335... HTTP/1.1" 200 0
```

You still need to verify these incoming requests yourself to ensure they are genuine. To learn more about callback parameters and verifying, see the [AdMob SDK Server Side Verification(SSV) documentation](https://developers.google.com/admob/android/rewarded-video-ssv).

## Caveats / limitations

### Android: rewarded close / progress chrome (high-engagement creatives)

Rewarded (and rewarded interstitial) creatives — including close controls, countdown / progress chrome, and any second
creative that plays inside a **single** `show()` presentation — are rendered by Google's `AdActivity` and the Google
Mobile Ads creative UI (classic: remote GMS ads module). This package's Android show path only:

- calls `RewardedAd.show(activity, …)` / `RewardedInterstitialAd.show(activity, …)` (and the same for interstitial /
  app open),
- optionally forwards `show({ immersiveModeEnabled })` to the SDK `setImmersiveMode(boolean)` API (Android system UI
  immersive mode — **not** AdMob
  [High-engagement ads](https://support.google.com/admob/answer/15525707) under App settings),

then forwards Google's fullscreen and reward callbacks. Separately, `serverSideVerificationOptions` from
[`RequestOptions`](https://github.com/invertase/react-native-google-mobile-ads/blob/main/packages/core/src/types/RequestOptions.ts)
are applied when the rewarded ad is loaded / wired — that is SSV setup, not chrome ownership. Tip's `AndroidManifest`
meta-data and Expo config plugin do **not** host an overlay, draw a close button, or restyle that chrome. Local classic
`play-services-ads-api` public `RewardedAd` surfaces expose no close-button, progress-bar, or “high-engagement” knobs —
only load / show / immersive / SSV / callbacks / placement / metadata.

If the close control is **invisible but still receives taps**, or a progress bar vanishes when a second creative starts
within one `rewarded.show()`, and the issue is intermittent across creatives (especially with
[High-engagement ads](https://support.google.com/admob/answer/15525707) enabled under AdMob **App settings** — app-level
fill / exit-step policy, not a per-unit creative toggle):

1. Confirm you are not drawing a React Native `Modal`, absolute-positioned view, or Expo status-bar / system UI layer
   above the ad — Google's `AdActivity` is a separate activity; package JS does not insert chrome on top of it.
2. Distinguish `immersiveModeEnabled` (this package's only Android show option) from AdMob **App settings →
   High-engagement ads** (app-level fill / exit-step policy). Toggling the show option does not enable or disable
   high-engagement creatives.
3. Re-test on a current Google Mobile Ads SDK / Play services build (tip pins: `packages/core/package.json`
   `sdkVersions`). Classic fullscreen layout is still delivered by the remote GMS module, so Play services updates can
   change chrome without a package bump.
4. If edge-to-edge drawing on API 35+ puts chrome under the system bars and makes it hard to see, see
   [Android: interstitial content under the system navigation bar (API 35+)](#android-interstitial-content-under-the-system-navigation-bar-api-35)
   — that is a different, layout-inset class of issue.
5. Capture Mobile Ads SDK logs, device / OS, GMA SDK version, whether High-engagement ads is enabled under App
   settings, and whether the tap still dismisses the ad, then escalate to Google. This React Native package cannot pad,
   recolor, or force-show Google's rewarded chrome.
