---
title: Announcing the Capacitor AdMob Plugin
description: The new Capacitor AdMob plugin serves banner, interstitial, rewarded and app open ads on Android and iOS, built on the Next-Gen Google Mobile Ads SDK.
date:
  created: 2026-09-10
  updated: 2026-09-10
authors:
  - robingenz
categories:
  - Announcements
  - Capacitor
  - SDKs
links:
  - Capacitor AdMob: sdks/capacitor/admob.md
faq: true
---

# Announcing the Capacitor AdMob Plugin

Today we're releasing the [Capacitor AdMob plugin](../../sdks/capacitor/admob.md), the first Capacitor AdMob plugin built on Google's Next-Gen Mobile Ads SDK. It serves all five AdMob ad formats on Android and iOS through one load-and-show API, places banners in overlay, resize, or inline mode, reports impression-level revenue for all formats, and runs the User Messaging Platform consent flow in a single method call. The plugin is part of Capawesome [Insiders](../../insiders/index.md), a paid subscription.

<!-- more -->

<div class="capawesome-z29o10a">
  <a href="https://capawesome.io/" target="_blank">
    <img alt="Build and deploy your Capacitor app with Capawesome Cloud" src="https://capawesome.io/assets/banners/cloud-build-and-deploy-capacitor-apps.png?t=1" />
  </a>
</div>

## Key Takeaways

- The plugin supports five ad formats: banner, interstitial, rewarded, rewarded interstitial, and app open, all through the same load-and-show API.
- On Android it builds on Google's Next-Gen Mobile Ads SDK (`ads-mobile-sdk` 1.2.1 by default), on iOS on the latest Google Mobile Ads SDK.
- Google gives the legacy Android SDK versions 24 and 25 a deprecation date of June 30, 2027 and a sunset date of June 30, 2028, after which ad serving can be disabled.
- Banner ads run in `overlay`, `resize`, or inline `frame` mode, and several banners can be on screen at the same time, each addressed by its own identifier.
- `requestConsent(...)` runs the full User Messaging Platform flow in one call, and every load method rejects with `CONSENT_NOT_GATHERED` until the consent requirements are met.
- The `adRevenuePaid` event reports value, currency code, and precision for every ad format, ready for an LTV pipeline.

## Why the Plugin Is Built on the Next-Gen SDK

Google now maintains two Android ad SDKs in parallel, and the older one has an expiry date. The legacy Google Mobile Ads SDK, currently at major versions 24 and 25, has a published [deprecation schedule](https://developers.google.com/admob/android/deprecation){:target="_blank"}: both versions reach their deprecation date on June 30, 2027 and their sunset date on June 30, 2028. Google's own wording for a sunset version is that ads are "at risk of not serving", with sunset ad requests returning a no fill. The successor is the [GMA Next-Gen SDK](https://developers.google.com/admob/android/next-gen){:target="_blank"}, which ships as a new Kotlin-first artifact (`com.google.android.libraries.ads.mobile.sdk`) instead of another major version of the old one.

The Capacitor AdMob plugin sits on the Next-Gen SDK on Android from its first release, defaulting to `ads-mobile-sdk` 1.2.1, and on the latest Google Mobile Ads SDK on iOS, where Google has not published a Next-Gen variant yet. Both dependency versions are project variables, so you can pin `$adsMobileSdkVersion` and `$userMessagingPlatformVersion` in your `variables.gradle` if another plugin forces a different version on you.

For comparison, the `@capacitor-community/admob` README states that its v8 pins Google Mobile Ads SDK 25.4.x on Android and 13.6.0 on iOS, and that the Next-Gen SDK waits until the next plugin major version.

## Which ad formats does the Capacitor AdMob plugin support?

The plugin supports the five AdMob ad formats that Google offers for mobile apps, and every one of them follows the same call shape.

| Ad format | Methods | Typical placement |
| --- | --- | --- |
| Banner | [`showBanner(...)`](../../sdks/capacitor/admob.md#showbanner), [`hideBanner(...)`](../../sdks/capacitor/admob.md#hidebanner), [`resumeBanner(...)`](../../sdks/capacitor/admob.md#resumebanner), [`removeBanner(...)`](../../sdks/capacitor/admob.md#removebanner) | A persistent strip at the top or bottom, or inline in scrolling content |
| Interstitial | [`loadInterstitialAd(...)`](../../sdks/capacitor/admob.md#loadinterstitialad), [`showInterstitialAd(...)`](../../sdks/capacitor/admob.md#showinterstitialad) | Full screen at a natural break, for example between two game levels |
| Rewarded | [`loadRewardedAd(...)`](../../sdks/capacitor/admob.md#loadrewardedad), [`showRewardedAd(...)`](../../sdks/capacitor/admob.md#showrewardedad) | Opt-in video that grants coins, lives, or credits |
| Rewarded interstitial | [`loadRewardedInterstitialAd(...)`](../../sdks/capacitor/admob.md#loadrewardedinterstitialad), [`showRewardedInterstitialAd(...)`](../../sdks/capacitor/admob.md#showrewardedinterstitialad) | A reward offered at a transition instead of from a button |
| App open | [`loadAppOpenAd(...)`](../../sdks/capacitor/admob.md#loadappopenad), [`showAppOpenAd(...)`](../../sdks/capacitor/admob.md#showappopenad), [`enableAppOpenAutoShow(...)`](../../sdks/capacitor/admob.md#enableappopenautoshow) | Shown when the user brings the app back to the foreground |

All methods are Android and iOS only. AdMob is a mobile advertising product, so on the web every method rejects with an unimplemented error.

## One Load and Show API for Full-Screen Ads

Every full-screen format uses the same two steps: a load method that returns an identifier, and a show method that takes it. Here is a rewarded ad, with the reward listener registered before the ad is shown:

```typescript
import { Admob } from '@capawesome-team/capacitor-admob';

const showRewardedAd = async () => {
  await Admob.addListener('rewardEarned', ({ amount, type }) => {
    grantReward(amount, type);
  });
  const { id } = await Admob.loadRewardedAd({
    adUnitId: 'ca-app-pub-3940256099942544/5224354917',
  });
  await Admob.showRewardedAd({ id });
};
```

Swap `loadRewardedAd` for `loadInterstitialAd`, `loadRewardedInterstitialAd`, or `loadAppOpenAd` and the rest of the code stays the same. Because each load call returns its own identifier, you can keep several ads in flight at once, for example one interstitial preloaded for the end of the level and one rewarded ad behind a "watch for coins" button. Pass your own `id` if you would rather address ads by a name you control instead of the generated one.

Two option groups apply to all four full-screen formats. `requestOptions` takes `contentUrl` and `keywords` for contextual targeting and brand safety, and both rewarded formats accept `serverSideVerification` so your backend can confirm the reward before granting it:

```typescript
const { id } = await Admob.loadRewardedAd({
  adUnitId: 'ca-app-pub-3940256099942544/5224354917',
  serverSideVerification: {
    userId: 'a1b2c3',
    customData: 'level_7',
  },
});
```

Both values are forwarded to your server-side verification callback, so the reward is granted based on what Google reports rather than what the client claims.

## Banner Ads Without the Overlap

Banner ads are where most Capacitor integrations get messy, because the banner is a native view sitting on top of a web view that knows nothing about it. The plugin offers three placements, and the right one depends on how much your CSS already knows about the banner.

| Mode | What happens | When to use it |
| --- | --- | --- |
| `mode: 'overlay'` (default) | The banner is anchored to the top or bottom edge on top of the web view, aware of the safe area insets | Your layout already reserves space, for example with a fixed footer |
| `mode: 'resize'` | The web view is resized so the banner never covers web content | You want the banner to stay clear of your content without touching your CSS |
| `frame: { x, y, width, height }` | The banner is placed at a frame you measure in CSS pixels | Inline placement inside your content, for example between list items |

Resize mode is the shortest path to a banner that never hides a button. You pass the ad unit, the size, and the position, and the plugin gives back an identifier:

```typescript
import { Admob, BannerSize } from '@capawesome-team/capacitor-admob';

const showBanner = async () => {
  const { id } = await Admob.showBanner({
    adUnitId: 'ca-app-pub-3940256099942544/6300978111',
    size: BannerSize.AdaptiveBanner,
    position: 'bottom',
    mode: 'resize',
  });
  return id;
};
```

For inline placement you measure an anchor element with `getBoundingClientRect()`, pass its rectangle as `frame`, and update it with [`setBannerFrame(...)`](../../sdks/capacitor/admob.md#setbannerframe) whenever the layout shifts. Keep the identifier around: it is what [`hideBanner(...)`](../../sdks/capacitor/admob.md#hidebanner), [`resumeBanner(...)`](../../sdks/capacitor/admob.md#resumebanner), and [`removeBanner(...)`](../../sdks/capacitor/admob.md#removebanner) operate on, and it is what lets you run more than one banner at a time.

Seven sizes are available. `AdaptiveBanner` is the default and matches the screen or frame width with a height chosen by the SDK, `InlineAdaptiveBanner` is capped by the height of the frame you pass, and the fixed sizes cover 320x50, 320x100, 300x250, plus 468x60 and 728x90 for tablets. Set `collapsible: true` for a banner that opens into a larger ad and collapses back, and listen for `bannerSizeChanged` to keep your layout in sync when it does.

If your banner still ends up under a gesture bar or a notch, the cause is usually your app's inset handling rather than the ad. Our [Capacitor edge-to-edge and safe areas guide](./capacitor-edge-to-edge-and-safe-areas-guide.md) covers the CSS and the Capacitor 8.3.x behavior in detail.

## App Open Ads on Autopilot

App open ads have an awkward lifecycle: you have to load one ahead of time, notice that the app returned to the foreground, decide whether enough time has passed, and make sure no other full-screen ad or consent form is in the way. The plugin can run that loop for you:

```typescript
import { Admob } from '@capawesome-team/capacitor-admob';

const enableAppOpenAds = async () => {
  await Admob.enableAppOpenAutoShow({
    adUnitId: 'ca-app-pub-3940256099942544/9257395921',
    minInterval: 14400,
  });
};
```

`minInterval` is the frequency cap in seconds and defaults to 14400, so at most one app open ad every four hours. The plugin loads and shows an app open ad every time the app returns to the foreground, and never shows one while a consent form or another full-screen ad is visible. Call [`disableAppOpenAutoShow()`](../../sdks/capacitor/admob.md#disableappopenautoshow) when the user upgrades to your ad-free tier, or stay on [`loadAppOpenAd(...)`](../../sdks/capacitor/admob.md#loadappopenad) and [`showAppOpenAd(...)`](../../sdks/capacitor/admob.md#showappopenad) if you want to decide every impression yourself.

## Ad Events and Revenue Tracking

Ten events cover the ad lifecycle. Most of them carry the ad's `id` and `format`, so one listener can serve all five formats; `bannerSizeChanged` reports the banner's width and height instead, and `rewardEarned` reports the reward amount and type.

| Event | Fires when |
| --- | --- |
| `adLoaded` | An ad finished loading |
| `adFailedToLoad` | An ad failed to load, with the SDK's numeric `errorCode` and `errorMessage` |
| `adShowed` | An ad was shown |
| `adFailedToShow` | A loaded ad failed to show |
| `adDismissed` | A full-screen ad was dismissed |
| `adClicked` | An ad was clicked |
| `adImpressionRecorded` | An impression was recorded |
| `adRevenuePaid` | An ad earned revenue |
| `bannerSizeChanged` | A banner changed size, for example after a collapsible banner expanded |
| `rewardEarned` | The user earned a reward from a rewarded or rewarded interstitial ad |

The one to wire up first is `adRevenuePaid`. It reports impression-level revenue for every format, which is what LTV models, ROAS dashboards, and cohort analyses run on:

```typescript
import { Admob } from '@capawesome-team/capacitor-admob';

const trackAdRevenue = async () => {
  await Admob.addListener('adRevenuePaid', ({ value, currencyCode, precision, format }) => {
    analytics.track('ad_revenue', { value, currencyCode, precision, format });
  });
};
```

`value` is the amount in the currency's standard unit, `currencyCode` is an ISO 4217 code, and `precision` tells you how much to trust the number: `PRECISE`, `ESTIMATED`, `PUBLISHER_PROVIDED`, or `UNKNOWN`. Mixing estimated and precise values into the same total gives you a figure you cannot reconcile with your AdMob reports.

## Gathering Consent Before the First Ad Request

Google requires consent through the User Messaging Platform before you request a single ad from users in the European Economic Area, the UK, or a regulated US state. The plugin condenses the canonical flow into [`requestConsent(...)`](../../sdks/capacitor/admob.md#requestconsent), which requests the latest consent information and shows the form only when it is required:

```typescript
import { Admob } from '@capawesome-team/capacitor-admob';

const setupAds = async () => {
  const { canRequestAds, privacyOptionsRequired } = await Admob.requestConsent();
  if (canRequestAds) {
    await Admob.initialize();
  }
  return privacyOptionsRequired;
};
```

Call this on every app launch, before [`initialize(...)`](../../sdks/capacitor/admob.md#initialize), because the answer changes over time. Until the consent requirements are met, every load method rejects with `CONSENT_NOT_GATHERED`, so a non-compliant ad request never leaves the device. If `privacyOptionsRequired` comes back `true`, give the user a settings entry that calls [`showPrivacyOptionsForm()`](../../sdks/capacitor/admob.md#showprivacyoptionsform).

The full flow, including the AdMob console setup, the App Tracking Transparency ordering on iOS, and consent error handling, is covered in our guide on [how to handle AdMob GDPR consent in a Capacitor app](./how-to-handle-admob-gdpr-consent-in-a-capacitor-app.md).

## Test Ad Units and Test Devices

Always develop against Google's public test ad units. Requesting production ads from your own device during development counts as invalid traffic and can get your AdMob account suspended.

| Format | Android | iOS |
| --- | --- | --- |
| Banner | `ca-app-pub-3940256099942544/6300978111` | `ca-app-pub-3940256099942544/2934735716` |
| Interstitial | `ca-app-pub-3940256099942544/1033173712` | `ca-app-pub-3940256099942544/4411468910` |
| Rewarded | `ca-app-pub-3940256099942544/5224354917` | `ca-app-pub-3940256099942544/1712485313` |
| Rewarded interstitial | `ca-app-pub-3940256099942544/5354046379` | `ca-app-pub-3940256099942544/6978759866` |
| App open | `ca-app-pub-3940256099942544/9257395921` | `ca-app-pub-3940256099942544/5575463023` |

Once you switch to your own ad units, register your development devices with the `testDeviceIds` option of `initialize(...)` so they keep receiving test ads. The consent flow has its own test switches: `debugGeography` makes a device look like it sits in the EEA, in a regulated US state, or in an unregulated region, and [`resetConsent()`](../../sdks/capacitor/admob.md#resetconsent) clears the stored consent state so you can replay the form as often as you need.

## Typed Error Codes

Every rejection the plugin can classify carries a typed code in `error.code`, alongside the message from the Google Mobile Ads SDK.

| Code | Meaning |
| --- | --- |
| `AD_ALREADY_SHOWING` | The ad is already showing |
| `AD_NOT_LOADED` | No loaded ad was found for the given identifier |
| `APPLICATION_ID_MISSING` | The AdMob application ID is missing in the native project |
| `CONSENT_FORM_UNAVAILABLE` | The consent form is not available |
| `CONSENT_NOT_GATHERED` | Ads cannot be requested because consent has not been gathered yet |
| `CONSENT_REQUEST_FAILED` | The consent information could not be requested |
| `LOAD_FAILED` | The ad could not be loaded |
| `NOT_INITIALIZED` | The Google Mobile Ads SDK has not been initialized |

Branch on the `ErrorCode` enum rather than on message strings. The `errorCode` property on the `adFailedToLoad` and `adFailedToShow` events is not an `ErrorCode` but the numeric code reported by the Google Mobile Ads SDK, documented separately for [Android](https://developers.google.com/admob/android/reference/com/google/android/gms/ads/AdRequest#constant-summary){:target="_blank"} and [iOS](https://developers.google.com/admob/ios/reference/enum/GADErrorCode){:target="_blank"}.

## Platform Notes

The plugin requires Capacitor 8 or later and supports both CocoaPods and Swift Package Manager on iOS. To install it, please refer to the [Installation](../../sdks/capacitor/admob.md/#installation) section in the plugin documentation.

Three native details decide whether your first ad request works:

- **AdMob app ID.** Android needs a `com.google.android.gms.ads.APPLICATION_ID` meta-data entry in `AndroidManifest.xml`, iOS needs `GADApplicationIdentifier` in `Info.plist`. A missing entry crashes the Google Mobile Ads SDK on Android, so the plugin detects it first and rejects `initialize(...)` with a readable message instead. An invalid ID cannot be detected, so double-check the value.
- **SKAdNetwork identifiers.** Add the `SKAdNetworkItems` list from Google's [iOS quick start](https://developers.google.com/admob/ios/quick-start#update_your_infoplist){:target="_blank"} to your `Info.plist` so ad attribution works for Google and for third-party buyers.
- **App Tracking Transparency order.** For personalized ads on iOS, call `requestConsent(...)` first, then request the tracking permission with the [Capacitor App Tracking Transparency plugin](../../sdks/capacitor/app-tracking-transparency.md), then call `initialize(...)`. Requesting in a different order is a common cause of App Store rejections.

Two smaller knobs round out the native side: [`setApplicationMuted(...)`](../../sdks/capacitor/admob.md#setapplicationmuted) and [`setApplicationVolume(...)`](../../sdks/capacitor/admob.md#setapplicationvolume) let video ads respect your app's own volume controls, and `initialize(...)` accepts `maxAdContentRating`, `tagForChildDirectedTreatment` (COPPA), and `tagForUnderAgeOfConsent` (TFUA) for policy-restricted apps.

The plugin is marked experimental in its README. The API surface is complete and typed, but it has not been through extensive production testing yet, so roll it out to a small audience first and [report anything that breaks](https://github.com/capawesome-team/capacitor-plugins/issues){:target="_blank"}.

## Coming from @capacitor-community/admob

`@capacitor-community/admob` is the incumbent and is actively maintained under an MIT license, so switching is a trade rather than an upgrade in every dimension. The table compares what both READMEs document today.

| | Capacitor AdMob plugin | `@capacitor-community/admob` |
| --- | --- | --- |
| Android SDK | Next-Gen Mobile Ads SDK (`ads-mobile-sdk` 1.2.1 by default) | Legacy Google Mobile Ads SDK 25.4.x |
| iOS SDK | Latest Google Mobile Ads SDK | Google Mobile Ads SDK 13.6.0 |
| Ad formats | Banner, interstitial, rewarded, rewarded interstitial, app open | Banner, interstitial, rewarded, rewarded interstitial, app open |
| Banner layout | `overlay`, `resize`, or a frame in CSS pixels | Position and margin in dp or points, on top of the web view |
| Banners at once | Several, each with its own identifier | One |
| Full-screen instances | Identifier per loaded ad, generated or your own | Targeted by ad unit ID, defaulting to the most recently prepared ad |
| Consent flow | `requestConsent(...)` in one call | `requestConsentInfo(...)` followed by `showConsentForm()` |
| App open automation | `enableAppOpenAutoShow(...)` with a frequency cap | Manual load and show |
| Errors | Typed `ErrorCode` plus the SDK message | Numeric SDK error code and message |
| App Tracking Transparency | Separate [App Tracking Transparency plugin](../../sdks/capacitor/app-tracking-transparency.md) | Built into the plugin |
| Revenue data | One `adRevenuePaid` event for every format | `bannerAdPaid` plus per-format impression events |
| License | Capawesome Insiders (paid) | MIT |

The community plugin gives you two things this one does not. Its revenue payload includes the mediation `networkName` and an `impressionId`, and its App Tracking Transparency helpers save you a second dependency on iOS. If your app is a single bottom banner and an occasional interstitial, the incumbent covers it. The Next-Gen SDK, the resize and inline banner modes, and the one-call consent flow are what you move for.

The API mapping is mechanical: `prepareInterstitial` becomes `loadInterstitialAd`, `prepareRewardVideoAd` becomes `loadRewardedAd`, per-format event enums become the shared event names above, and the ad unit IDs you pass through `adId` become `adUnitId`.

## FAQ

### Can I use the Capacitor AdMob plugin with Ionic, React, Vue, or Angular?

Yes. The plugin is framework-agnostic and works in any Capacitor app, including Ionic with Angular, React, or Vue, as well as plain JavaScript projects.

### Does the Capacitor AdMob plugin work on the web?

No. AdMob is a mobile advertising product, so all methods are available on Android and iOS only and reject with an unimplemented error on the web. For web advertising, look at [Google AdSense](https://adsense.google.com/){:target="_blank"} instead.

### Can I show more than one banner ad at the same time?

Yes. `showBanner(...)` returns an identifier for each banner, and `hideBanner(...)`, `resumeBanner(...)`, `removeBanner(...)`, and `setBannerFrame(...)` all take that identifier, so several banners can be on screen at once.

### Why do my ad requests fail with `CONSENT_NOT_GATHERED`?

Because the plugin blocks ad requests until the consent requirements are met. Call `requestConsent(...)` on every app launch and initialize the SDK only when `canRequestAds` is `true`. The [AdMob GDPR consent guide](./how-to-handle-admob-gdpr-consent-in-a-capacitor-app.md) walks through the full flow.

### Which Capacitor version does the plugin require?

Capacitor 8 or later. On iOS both CocoaPods and Swift Package Manager are supported.

## Get Started

The Capacitor AdMob plugin is available now to all Capawesome [Insiders](/insiders/). An Insiders subscription gets you this plugin, the rest of our Insiders-only Capacitor plugins, and priority support from the Capawesome team.

[Become a Capawesome Insider](https://console.cloud.capawesome.io/){ .md-button .md-button--primary }

## Conclusion

If you are starting an AdMob integration today, start on the Next-Gen SDK. Google's sunset date for the legacy Android SDK is June 30, 2028, and rewriting a monetization layer under time pressure is worse than picking the right one now. If you already ship ads with `@capacitor-community/admob` and your layout is a single anchored banner, there is no urgency; revisit the decision when you need resize or inline banners, multiple concurrent ad instances, or revenue events across all formats.

The [API reference](../../sdks/capacitor/admob.md#api) has the full surface area, and the plugin is still marked experimental, so [issues](https://github.com/capawesome-team/capacitor-plugins/issues){:target="_blank"} are genuinely useful right now.

**Related reading:**

- [How to Handle AdMob GDPR Consent (UMP) in a Capacitor App](./how-to-handle-admob-gdpr-consent-in-a-capacitor-app.md)
- [Capacitor Edge-to-Edge & Safe Areas: The Complete Guide](./capacitor-edge-to-edge-and-safe-areas-guide.md)
- [Tips for Setting Up In-App Purchases with Capacitor](./tips-for-setting-up-in-app-purchases-with-capacitor.md)

**Stay in the loop:**

Join the conversation on the [Capawesome Discord server](https://discord.gg/VCXxSVjefW){:target="_blank"} and subscribe to the [Capawesome newsletter](https://capawesome.io/newsletter/){:target="_blank"} to stay updated on the latest news.
