cap-admob-advanced
v1.1.0
Published
Advanced AdMob plugin for Capacitor 7+ with full ad format support, consent management, and revenue tracking.
Maintainers
Readme
cap-admob-advanced
Advanced AdMob plugin for Capacitor 7+ with full ad format support, UMP consent management, impression-level revenue tracking, and App Tracking Transparency.
Table of Contents
- Features
- Supported Platforms
- Installation
- Configuration
- Usage
- API Reference
- Events Reference
- Enums Reference
- Mediation Setup
- Test Ad Unit IDs
- Migration from @capacitor-community/admob
- Troubleshooting
- Contributing
- Updating the Plugin
- License
Features
- Banner Ads -- Standard, adaptive, and collapsible banners with top/bottom positioning and overlapping/non-overlapping modes
- Interstitial Ads -- Full-screen interstitials with preload-and-show pattern
- Rewarded Ads -- Rewarded video ads with reward earned/skipped detection
- Rewarded Interstitial Ads -- Rewarded interstitials with full reward lifecycle
- App Open Ads -- Splash-style ads for app launch and resume
- UMP Consent Management -- Built-in Google User Messaging Platform integration for GDPR/CCPA compliance
- Privacy Options Form -- Show and force-display the Google-rendered privacy form
- IAB TCF v2.0 -- Read IAB Transparency & Consent Framework values from local storage
- Impression-Level Ad Revenue -- Real-time revenue data (micros, currency, precision) for every ad impression across all formats
- iOS App Tracking Transparency -- Native ATT/IDFA permission request
- Ad Personalization Control -- Enable, disable, or use default ad personalization state
- COPPA / Child-Directed Targeting -- Tag requests for child-directed treatment and under-age-of-consent users
- Content Rating Filtering -- Set maximum ad content rating (G, PG, T, MA)
- Global Audio Settings -- Mute video ads or set custom volume levels
- Test Device Support -- Configure test device IDs for development
- Google Ad Manager (GAM) -- Optional support for Ad Manager requests
- Mediation Ready -- Works with Google's mediation framework and third-party adapters
- Android 15 Edge-to-Edge Workaround -- Automatic fix for AdActivity rendering under system bars on API 35+
- Web Stub -- No-op web implementation for seamless
ionic servedevelopment - Non-Personalized Ads (NPA) -- Per-request NPA flag for GDPR compliance on individual ad loads
- Banner Margin -- Configurable pixel margin from screen edge for banner positioning
- Immersive Mode -- Android-only fullscreen immersive mode for interstitial, rewarded, and app open ads
- Ad Inspector -- Built-in Google Ad Inspector for debugging ad serving issues
- Migration Aliases -- Drop-in method aliases matching @capacitor-community/admob API names for easy migration (
showBannerAd,prepareInterstitial,prepareRewardVideoAd,showRewardVideoAd,resumeBanner) - Type-Safe Event Enums -- Exported event name enums (
BannerAdPluginEvents,InterstitialAdPluginEvents,RewardAdPluginEvents, etc.) for autocomplete and refactoring safety
Supported Platforms
| Platform | Minimum Version | Ad SDK Version |
| -------- | ----------------------------------- | -------------------------------------------------------------------------- |
| Android | API 23 (Android 6.0), compileSdk 35 | play-services-ads:24.9.0, user-messaging-platform:4.0.0 |
| iOS | 14.0 | Google-Mobile-Ads-SDK ~> 12.14.0, GoogleUserMessagingPlatform ~> 3.1.0 |
| Web | N/A (stub only) | No-op implementation for browser development |
Installation
1. Install the package
If the plugin is published to npm:
npm install cap-admob-advanced
npx cap syncIf you are developing locally (the plugin lives alongside your app):
# In your app's package.json, add a file: dependency
npm install file:./cap-admob-advanced
npx cap sync2. Android Setup
Add your AdMob App ID to AndroidManifest.xml
Open android/app/src/main/AndroidManifest.xml and add the following inside the <application> tag:
<application>
<!-- ... existing content ... -->
<!-- AdMob App ID (replace with your real App ID) -->
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-XXXXXXXXXXXXXXXX~YYYYYYYYYY" />
<!-- Required AdActivity for full-screen ads -->
<activity
android:name="com.google.android.gms.ads.AdActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"
android:theme="@android:style/Theme.Translucent" />
</application>Important: Replace
ca-app-pub-XXXXXXXXXXXXXXXX~YYYYYYYYYYwith your actual AdMob App ID from the AdMob console.
3. iOS Setup
Add your AdMob App ID to Info.plist
Open ios/App/App/Info.plist and add:
<key>GADApplicationIdentifier</key>
<string>ca-app-pub-XXXXXXXXXXXXXXXX~YYYYYYYYYY</string>Add App Tracking Transparency description
Required for iOS 14+ to request IDFA:
<key>NSUserTrackingUsageDescription</key>
<string>This identifier will be used to deliver personalized ads to you.</string>Add SKAdNetwork identifiers
Required for proper ad attribution. Add all relevant SKAdNetwork IDs to Info.plist:
<key>SKAdNetworkItems</key>
<array>
<!-- Google -->
<dict>
<key>SKAdNetworkIdentifier</key>
<string>cstr6suwn9.skadnetwork</string>
</dict>
<!-- Add additional SKAdNetwork IDs from: -->
<!-- https://developers.google.com/admob/ios/quick-start#update_your_infoplist -->
</array>Refer to Google's official SKAdNetwork ID list for the full set of identifiers required by AdMob and its mediation partners.
Configuration
Test Device IDs
Pass test device IDs during initialization so your development devices receive test ads instead of live ones. Find your device ID in the logcat/console output when you first request an ad.
import {AdMobAdvanced} from "cap-admob-advanced";
await AdMobAdvanced.initialize({
testDeviceIds: ["YOUR_ANDROID_TEST_DEVICE_HASH", "YOUR_IOS_TEST_DEVICE_HASH"],
});Targeting (COPPA / Content Rating)
Configure child-directed treatment and content rating for all subsequent ad requests:
import {AdMobAdvanced, MaxAdContentRating} from "cap-admob-advanced";
await AdMobAdvanced.setTargeting({
childDirectedTreatment: true,
underAgeOfConsent: true,
contentRating: MaxAdContentRating.G,
});Global Settings (Audio)
Control video ad audio globally:
import {AdMobAdvanced} from "cap-admob-advanced";
await AdMobAdvanced.setGlobalSettings({
setAppMuted: true, // Mute all video ads
setAppVolume: 0.5, // 50% volume (0.0 to 1.0)
pubIdEnabled: false, // Disable publisher-provided identifier
});Ad Personalization
Control whether ads are personalized:
import {AdMobAdvanced} from "cap-admob-advanced";
// Options: "default", "enabled", "disabled"
await AdMobAdvanced.setPersonalizationState({state: "disabled"});Usage
6.1 Initialization & Consent
The initialize() method must be called before loading any ads. All load*() methods will reject with an error if the SDK has not been initialized. The method initializes the Google Mobile Ads SDK and runs the UMP consent flow automatically.
Note: All
show*()methods (interstitial, rewarded, rewarded interstitial, app open) resolve their promise when the ad is actually displayed on screen, and reject if it fails to show. This means you can safelyawaitthem to know the ad was shown.
import {AdMobAdvanced} from "cap-admob-advanced";
import type {SdkInitResult, ConsentInfo} from "cap-admob-advanced";
async function initializeAdMob(): Promise<void> {
// Listen for SDK initialization
await AdMobAdvanced.addListener(
"onSdkInitialized",
(result: SdkInitResult) => {
console.log("SDK version:", result.version);
console.log("Consent status:", result.consentStatus);
console.log("Adapters:", result.adapters);
},
);
// Listen for consent info updates
await AdMobAdvanced.addListener(
"onConsentInfoUpdate",
(info: ConsentInfo) => {
console.log("Consent status:", info.status);
console.log("Can request ads:", info.canRequestAds);
if (info.canRequestAds) {
// Safe to load ads
loadAds();
}
},
);
// Initialize the SDK
const result = await AdMobAdvanced.initialize({
testDeviceIds: ["YOUR_DEVICE_ID"],
isConsentDebug: false, // Set to true for testing consent in non-EEA regions
});
console.log("Initialization result:", result);
}
// Show the privacy options form (e.g., from a settings button)
async function showPrivacySettings(): Promise<void> {
await AdMobAdvanced.showPrivacyOptionsForm();
}
// Force the consent form to display regardless of current status
async function forceShowConsent(): Promise<void> {
await AdMobAdvanced.forceDisplayPrivacyForm();
}
// Reset consent (useful during development/testing)
async function resetConsent(): Promise<void> {
await AdMobAdvanced.consentReset();
}
// Check current consent status at any time
async function checkConsent(): Promise<void> {
const consentInfo = await AdMobAdvanced.getConsentStatus();
console.log("Status:", consentInfo.status);
console.log("Can request ads:", consentInfo.canRequestAds);
}
// Read IAB TCF v2.0 values
async function readTcfValues(): Promise<void> {
const tcf = await AdMobAdvanced.getIabTcf();
console.log("CMP SDK ID:", tcf.IABTCF_CmpSdkID);
console.log("GDPR applies:", tcf.IABTCF_gdprApplies);
console.log("Purpose consents:", tcf.IABTCF_PurposeConsents);
console.log("TC string:", tcf.IABTCF_TCString);
}6.2 Banner Ads
Banner ads are displayed at the top or bottom of the screen. They support multiple sizes, collapsible mode, and overlapping/non-overlapping layout.
import {
AdMobAdvanced,
AdMobBannerSize,
BannerPosition,
} from "cap-admob-advanced";
import type {
BannerLoadResult,
AdErrorInfo,
AdRevenueInfo,
CollapsibleResult,
} from "cap-admob-advanced";
async function setupBannerListeners(): Promise<void> {
await AdMobAdvanced.addListener(
"onBannerLoaded",
(result: BannerLoadResult) => {
console.log("Banner loaded, height:", result.height, "dp");
},
);
await AdMobAdvanced.addListener("onBannerFailed", (error: AdErrorInfo) => {
console.error("Banner failed:", error.code, error.message);
// Retry after a delay
setTimeout(() => loadBanner(), 30000);
});
await AdMobAdvanced.addListener("onBannerClicked", () => {
console.log("Banner clicked");
});
await AdMobAdvanced.addListener("onBannerImpression", () => {
console.log("Banner impression recorded");
});
await AdMobAdvanced.addListener("onBannerOpened", () => {
console.log("Banner overlay opened");
});
await AdMobAdvanced.addListener("onBannerClosed", () => {
console.log("Banner overlay closed");
});
await AdMobAdvanced.addListener(
"onBannerCollapsible",
(info: CollapsibleResult) => {
console.log("Is collapsible:", info.isCollapsible);
},
);
await AdMobAdvanced.addListener("onAdRevenue", (revenue: AdRevenueInfo) => {
console.log("Revenue:", revenue.micros, revenue.currency);
});
}
// Standard adaptive banner at the bottom
async function loadBanner(): Promise<void> {
const result = await AdMobAdvanced.loadBanner({
adUnitId: "ca-app-pub-3940256099942544/6300978111",
position: BannerPosition.BOTTOM_CENTER,
size: AdMobBannerSize.ANCHORED_ADAPTIVE,
autoShow: true,
isOverlapping: false, // Push app content above the banner
});
console.log("Banner height:", result.height);
}
// Collapsible banner at the bottom
async function loadCollapsibleBanner(): Promise<void> {
await AdMobAdvanced.loadBanner({
adUnitId: "ca-app-pub-3940256099942544/2014213617",
position: BannerPosition.BOTTOM_CENTER,
size: AdMobBannerSize.ANCHORED_ADAPTIVE,
collapsible: "bottom", // Collapses toward the bottom edge
autoShow: true,
isOverlapping: true,
});
}
// Banner at the top of the screen
async function loadTopBanner(): Promise<void> {
await AdMobAdvanced.loadBanner({
adUnitId: "ca-app-pub-3940256099942544/6300978111",
position: BannerPosition.TOP_CENTER,
size: AdMobBannerSize.BANNER, // Fixed 320x50
autoShow: true,
isOverlapping: true, // Overlaps app content
});
}
// Banner with margin and non-personalized ads
async function loadBannerWithMargin(): Promise<void> {
await AdMobAdvanced.loadBanner({
adUnitId: "ca-app-pub-3940256099942544/6300978111",
position: BannerPosition.BOTTOM_CENTER,
size: AdMobBannerSize.ANCHORED_ADAPTIVE,
margin: 60, // 60px margin from bottom edge (e.g., for tab bar)
npa: true, // Non-personalized ads
autoShow: true,
});
}
// Manually control banner visibility
async function hideBanner(): Promise<void> {
await AdMobAdvanced.hideBanner(); // Keeps the ad loaded but hidden
}
async function showBanner(): Promise<void> {
await AdMobAdvanced.showBanner(); // Shows a previously hidden banner
}
async function removeBanner(): Promise<void> {
await AdMobAdvanced.removeBanner(); // Destroys the banner completely
}Banner Size Options:
| Size | Constant | Dimensions |
| ------------------- | --------------------- | ------------------------------------- |
| Standard Banner | BANNER | 320 x 50 |
| Large Banner | LARGE_BANNER | 320 x 100 |
| Medium Rectangle | MEDIUM_RECTANGLE | 300 x 250 |
| Full Banner | FULL_BANNER | 468 x 60 |
| Leaderboard | LEADERBOARD | 728 x 90 |
| Responsive Adaptive | RESPONSIVE_ADAPTIVE | Full width, auto height |
| Anchored Adaptive | ANCHORED_ADAPTIVE | Full width, fixed to edge |
| Inline Adaptive | INLINE_ADAPTIVE | Full width, within scrollable content |
6.3 Interstitial Ads
Interstitial ads are full-screen ads that cover the entire app UI. Use a preload-then-show pattern for best performance.
import {AdMobAdvanced} from "cap-admob-advanced";
import type {AdErrorInfo, AdRevenueInfo} from "cap-admob-advanced";
let interstitialReady = false;
async function setupInterstitialListeners(): Promise<void> {
await AdMobAdvanced.addListener("onInterstitialLoaded", () => {
console.log("Interstitial loaded and ready");
interstitialReady = true;
});
await AdMobAdvanced.addListener(
"onInterstitialFailed",
(error: AdErrorInfo) => {
console.error("Interstitial failed to load:", error.message);
interstitialReady = false;
// Retry after delay
setTimeout(() => preloadInterstitial(), 30000);
},
);
await AdMobAdvanced.addListener("onInterstitialShowed", () => {
console.log("Interstitial is now visible");
});
await AdMobAdvanced.addListener("onInterstitialDismissed", () => {
console.log("Interstitial dismissed");
interstitialReady = false;
// Preload the next one
preloadInterstitial();
});
await AdMobAdvanced.addListener("onInterstitialClicked", () => {
console.log("Interstitial clicked");
});
await AdMobAdvanced.addListener("onInterstitialImpression", () => {
console.log("Interstitial impression recorded");
});
await AdMobAdvanced.addListener(
"onInterstitialFailedToShow",
(error: AdErrorInfo) => {
console.error("Interstitial failed to show:", error.message);
interstitialReady = false;
preloadInterstitial();
},
);
await AdMobAdvanced.addListener("onAdRevenue", (revenue: AdRevenueInfo) => {
console.log("Ad revenue:", revenue.micros / 1_000_000, revenue.currency);
});
}
async function preloadInterstitial(): Promise<void> {
await AdMobAdvanced.loadInterstitial({
adUnitId: "ca-app-pub-3940256099942544/1033173712",
autoShow: false, // Load only; show manually when appropriate
});
}
// With immersive mode (Android only)
async function preloadInterstitialImmersive(): Promise<void> {
await AdMobAdvanced.loadInterstitial({
adUnitId: "ca-app-pub-3940256099942544/1033173712",
autoShow: false,
immersiveMode: true, // Hides system navigation on Android
});
}
async function showInterstitialIfReady(): Promise<void> {
if (interstitialReady) {
await AdMobAdvanced.showInterstitial();
} else {
console.log("Interstitial not ready yet");
}
}
// Typical usage: show between levels, after completing a task, etc.
async function onLevelComplete(): Promise<void> {
await showInterstitialIfReady();
}6.4 Rewarded Ads
Rewarded ads let users opt-in to watch a video ad in exchange for an in-app reward. The plugin emits onRewardEarned when the user completes the ad and onRewardedSkipped when they dismiss early.
import {AdMobAdvanced} from "cap-admob-advanced";
import type {
AdErrorInfo,
RewardInfo,
AdRevenueInfo,
} from "cap-admob-advanced";
let rewardedReady = false;
async function setupRewardedListeners(): Promise<void> {
await AdMobAdvanced.addListener("onRewardedLoaded", () => {
console.log("Rewarded ad loaded");
rewardedReady = true;
});
await AdMobAdvanced.addListener("onRewardedFailed", (error: AdErrorInfo) => {
console.error("Rewarded ad failed to load:", error.message);
rewardedReady = false;
setTimeout(() => preloadRewarded(), 30000);
});
await AdMobAdvanced.addListener("onRewardedShowed", () => {
console.log("Rewarded ad is now visible");
});
await AdMobAdvanced.addListener("onRewardedDismissed", () => {
console.log("Rewarded ad dismissed");
rewardedReady = false;
// Preload the next one
preloadRewarded();
});
await AdMobAdvanced.addListener("onRewardedClicked", () => {
console.log("Rewarded ad clicked");
});
await AdMobAdvanced.addListener("onRewardedImpression", () => {
console.log("Rewarded ad impression");
});
await AdMobAdvanced.addListener(
"onRewardedFailedToShow",
(error: AdErrorInfo) => {
console.error("Rewarded ad failed to show:", error.message);
rewardedReady = false;
preloadRewarded();
},
);
// The key event: user earned the reward
await AdMobAdvanced.addListener("onRewardEarned", (reward: RewardInfo) => {
console.log(`Reward earned: ${reward.amount} ${reward.type}`);
// Grant the reward to the user
grantReward(reward.type, reward.amount);
});
// User closed without earning the reward
await AdMobAdvanced.addListener("onRewardedSkipped", () => {
console.log("User skipped the rewarded ad");
});
// Track revenue
await AdMobAdvanced.addListener("onAdRevenue", (revenue: AdRevenueInfo) => {
console.log("Revenue:", revenue.micros / 1_000_000, revenue.currency);
});
}
async function preloadRewarded(): Promise<void> {
await AdMobAdvanced.loadRewarded({
adUnitId: "ca-app-pub-3940256099942544/5224354917",
autoShow: false,
});
}
async function showRewardedAd(): Promise<void> {
if (rewardedReady) {
await AdMobAdvanced.showRewarded();
} else {
console.log("Rewarded ad not ready. Loading now...");
await AdMobAdvanced.loadRewarded({
adUnitId: "ca-app-pub-3940256099942544/5224354917",
autoShow: true, // Show immediately once loaded
});
}
}
function grantReward(type: string, amount: number): void {
// Your reward logic: add coins, unlock content, etc.
console.log(`Granting ${amount} ${type} to user`);
}6.5 Rewarded Interstitial Ads
Rewarded interstitial ads combine the full-screen experience of an interstitial with an optional reward. Unlike standard rewarded ads, the user does not need to opt in -- the ad can appear at natural transition points.
import {AdMobAdvanced} from "cap-admob-advanced";
import type {AdErrorInfo, RewardInfo} from "cap-admob-advanced";
let rewardedInterstitialReady = false;
async function setupRewardedInterstitialListeners(): Promise<void> {
await AdMobAdvanced.addListener("onRewardedInterstitialLoaded", () => {
console.log("Rewarded interstitial loaded");
rewardedInterstitialReady = true;
});
await AdMobAdvanced.addListener(
"onRewardedInterstitialFailed",
(error: AdErrorInfo) => {
console.error("Rewarded interstitial failed:", error.message);
rewardedInterstitialReady = false;
},
);
await AdMobAdvanced.addListener("onRewardedInterstitialShowed", () => {
console.log("Rewarded interstitial showing");
});
await AdMobAdvanced.addListener("onRewardedInterstitialDismissed", () => {
console.log("Rewarded interstitial dismissed");
rewardedInterstitialReady = false;
preloadRewardedInterstitial();
});
await AdMobAdvanced.addListener("onRewardedInterstitialClicked", () => {
console.log("Rewarded interstitial clicked");
});
await AdMobAdvanced.addListener("onRewardedInterstitialImpression", () => {
console.log("Rewarded interstitial impression");
});
await AdMobAdvanced.addListener(
"onRewardedInterstitialFailedToShow",
(error: AdErrorInfo) => {
console.error("Rewarded interstitial failed to show:", error.message);
rewardedInterstitialReady = false;
},
);
await AdMobAdvanced.addListener(
"onRewardedInterstitialRewardEarned",
(reward: RewardInfo) => {
console.log(`Reward: ${reward.amount} ${reward.type}`);
grantReward(reward.type, reward.amount);
},
);
await AdMobAdvanced.addListener("onRewardedInterstitialSkipped", () => {
console.log("Rewarded interstitial skipped (no reward)");
});
}
async function preloadRewardedInterstitial(): Promise<void> {
await AdMobAdvanced.loadRewardedInterstitial({
adUnitId: "ca-app-pub-3940256099942544/5354046379",
autoShow: false,
});
}
async function showRewardedInterstitialIfReady(): Promise<void> {
if (rewardedInterstitialReady) {
await AdMobAdvanced.showRewardedInterstitial();
}
}
function grantReward(type: string, amount: number): void {
console.log(`Granting ${amount} ${type}`);
}6.6 App Open Ads
App open ads are designed to be shown when users bring your app to the foreground. They display a branded loading screen that can be dismissed at any time.
Note: App open ads expire after 4 hours. If you try to show an expired ad, the
onAppOpenFailedToShowevent will fire with an expiry message. Always preload a fresh ad after dismissal.
import {AdMobAdvanced} from "cap-admob-advanced";
import {App} from "@capacitor/app";
import type {AdErrorInfo} from "cap-admob-advanced";
let appOpenReady = false;
async function setupAppOpenAds(): Promise<void> {
// Set up listeners
await AdMobAdvanced.addListener("onAppOpenLoaded", () => {
console.log("App open ad loaded");
appOpenReady = true;
});
await AdMobAdvanced.addListener("onAppOpenFailed", (error: AdErrorInfo) => {
console.error("App open ad failed:", error.message);
appOpenReady = false;
// Retry loading
setTimeout(() => preloadAppOpen(), 30000);
});
await AdMobAdvanced.addListener("onAppOpenShowed", () => {
console.log("App open ad showing");
});
await AdMobAdvanced.addListener("onAppOpenDismissed", () => {
console.log("App open ad dismissed");
appOpenReady = false;
// Preload the next one for the next resume
preloadAppOpen();
});
await AdMobAdvanced.addListener(
"onAppOpenFailedToShow",
(error: AdErrorInfo) => {
console.error("App open ad failed to show:", error.message);
appOpenReady = false;
preloadAppOpen();
},
);
// Preload on app start
await preloadAppOpen();
// Show on app resume using the Capacitor App plugin
App.addListener("appStateChange", async ({isActive}) => {
if (isActive && appOpenReady) {
await AdMobAdvanced.showAppOpen();
}
});
}
async function preloadAppOpen(): Promise<void> {
await AdMobAdvanced.loadAppOpen({
adUnitId: "ca-app-pub-3940256099942544/9257395921",
autoShow: false,
});
}6.7 Impression-Level Revenue
Every ad format emits an onAdRevenue event when an impression generates revenue. Use this data to feed analytics platforms like Firebase, Adjust, or AppsFlyer.
import {AdMobAdvanced} from "cap-admob-advanced";
import type {AdRevenueInfo} from "cap-admob-advanced";
async function setupRevenueTracking(): Promise<void> {
await AdMobAdvanced.addListener("onAdRevenue", (revenue: AdRevenueInfo) => {
// revenue.micros -- Revenue in micros (e.g., 15000000 = $15.00)
// revenue.currency -- ISO 4217 currency code (e.g., "USD")
// revenue.precision -- 0 = unknown, 1 = estimated, 2 = publisher-provided, 3 = precise
// revenue.adUnitId -- The ad unit that generated the revenue
const dollars = revenue.micros / 1_000_000;
console.log(
`Revenue: $${dollars} ${revenue.currency} (precision: ${revenue.precision})`,
);
console.log(`Ad unit: ${revenue.adUnitId}`);
// Forward to Firebase Analytics
// FirebaseAnalytics.logEvent({
// name: 'ad_impression_revenue',
// params: {
// value: dollars,
// currency: revenue.currency,
// ad_unit_id: revenue.adUnitId,
// precision: revenue.precision,
// },
// });
});
}Revenue precision values:
| Value | Meaning | | ----- | ------------------ | | 0 | Unknown | | 1 | Estimated | | 2 | Publisher-provided | | 3 | Precise |
6.8 iOS IDFA / App Tracking Transparency
On iOS 14+, you must request permission before accessing the device's Identifier for Advertisers (IDFA). Call requestIDFA() before initializing ads for best results.
Note: On Android,
requestIDFA()is a no-op that always resolves with{ status: 3 }(authorized), since Android has no ATT equivalent. You can safely call it on both platforms without platform checks.
import {AdMobAdvanced} from "cap-admob-advanced";
import {Capacitor} from "@capacitor/core";
async function requestTrackingPermission(): Promise<void> {
// Only relevant on iOS
if (Capacitor.getPlatform() !== "ios") {
return;
}
const result = await AdMobAdvanced.requestIDFA();
// ATTrackingManager.AuthorizationStatus values:
// 0 = notDetermined
// 1 = restricted
// 2 = denied
// 3 = authorized
switch (result.status) {
case 0:
console.log("Tracking: not determined");
break;
case 1:
console.log("Tracking: restricted");
break;
case 2:
console.log("Tracking: denied");
break;
case 3:
console.log("Tracking: authorized");
break;
}
}
// Recommended initialization order:
async function startApp(): Promise<void> {
await requestTrackingPermission();
await AdMobAdvanced.initialize({
testDeviceIds: ["YOUR_TEST_DEVICE_ID"],
});
}API Reference
Methods
| Method | Parameters | Returns | Description |
| ----------------------------------- | ------------------------------------------------- | ------------------------------- | ---------------------------------------------------------------------------- |
| initialize(options?) | InitializeOptions | Promise<SdkInitResult> | Initialize the Google Mobile Ads SDK. Must be called before loading any ads. |
| setTargeting(options) | TargetingOptions | Promise<void> | Configure COPPA / under-age targeting for subsequent ad requests. |
| setGlobalSettings(options) | GlobalSettingsOptions | Promise<void> | Apply global SDK-level settings (muting, volume, etc.). |
| setPersonalizationState(options) | { state: "default" \| "enabled" \| "disabled" } | Promise<void> | Set the ad personalization state. |
| showPrivacyOptionsForm() | -- | Promise<void> | Show the Google-rendered privacy options form (UMP). |
| forceDisplayPrivacyForm() | -- | Promise<void> | Force-display the privacy/consent form regardless of status. |
| consentReset() | -- | Promise<void> | Reset the UMP consent state (useful for testing). |
| getConsentStatus() | -- | Promise<ConsentInfo> | Retrieve the current UMP consent status. |
| getIabTcf() | -- | Promise<IabTcfInfo> | Read IAB TCF v2.0 values from local storage. |
| requestIDFA() | -- | Promise<{ status: number }> | Request IDFA tracking authorization (iOS 14+ only). |
| loadBanner(options) | BannerAdOptions | Promise<BannerLoadResult> | Load a banner ad with the given options. |
| showBanner() | -- | Promise<void> | Show a previously loaded banner ad. |
| hideBanner() | -- | Promise<void> | Hide the currently visible banner (keeps it loaded). |
| removeBanner() | -- | Promise<void> | Remove and destroy the current banner completely. |
| loadInterstitial(options) | FullScreenAdOptions | Promise<void> | Pre-load an interstitial ad. |
| showInterstitial() | -- | Promise<void> | Show a previously loaded interstitial ad. |
| loadRewarded(options) | FullScreenAdOptions | Promise<void> | Pre-load a rewarded ad. |
| showRewarded() | -- | Promise<void> | Show a previously loaded rewarded ad. |
| loadRewardedInterstitial(options) | FullScreenAdOptions | Promise<void> | Pre-load a rewarded interstitial ad. |
| showRewardedInterstitial() | -- | Promise<void> | Show a previously loaded rewarded interstitial ad. |
| loadAppOpen(options) | FullScreenAdOptions | Promise<void> | Pre-load an app-open ad. |
| showAppOpen() | -- | Promise<void> | Show a previously loaded app-open ad. |
| addListener(eventName, handler) | Event name, callback | Promise<PluginListenerHandle> | Register a listener for a plugin event. |
| resumeBanner() | -- | Promise<void> | Resume a previously hidden banner (alias for showBanner). |
| openAdInspector() | -- | Promise<void> | Open the Google Ad Inspector for debugging ad serving. |
| showBannerAd(options) | BannerAdOptions | Promise<BannerLoadResult> | Migration alias: loads banner with autoShow: true. |
| prepareInterstitial(options) | FullScreenAdOptions | Promise<void> | Migration alias for loadInterstitial(). |
| prepareRewardVideoAd(options) | FullScreenAdOptions | Promise<void> | Migration alias for loadRewarded(). |
| showRewardVideoAd() | -- | Promise<void> | Migration alias for showRewarded(). |
| removeAllListeners() | -- | Promise<void> | Remove all registered event listeners. |
Interfaces
InitializeOptions
| Property | Type | Default | Description |
| ------------------------- | ---------- | ------- | -------------------------------------------------------- |
| isUsingAdManagerRequest | boolean | false | Use Ad Manager (GAM) requests instead of standard AdMob. |
| isResponseInfo | boolean | false | Include response info in ad results (debugging). |
| isConsentDebug | boolean | false | Enable UMP consent debug mode. |
| testDeviceIds | string[] | [] | Test device IDs that should receive test ads. |
TargetingOptions
| Property | Type | Default | Description |
| ------------------------ | -------------------- | ------- | --------------------------------------------------- |
| childDirectedTreatment | boolean | -- | Tag the request for COPPA child-directed treatment. |
| underAgeOfConsent | boolean | -- | Tag the request for users under the age of consent. |
| contentRating | MaxAdContentRating | -- | Maximum ad content rating. |
GlobalSettingsOptions
| Property | Type | Default | Description |
| -------------- | --------- | ------- | ----------------------------------------------------- |
| setAppMuted | boolean | false | Mute video ads. |
| setAppVolume | number | 1.0 | App audio volume for video ads (0.0 -- 1.0). |
| pubIdEnabled | boolean | -- | Whether the publisher-provided identifier is enabled. |
BannerAdOptions
| Property | Type | Default | Description |
| --------------- | ------------------- | ------------------- | -------------------------------------------------------------- |
| adUnitId | string | (required) | The ad unit ID to load. |
| position | BannerPosition | BOTTOM_CENTER | Where on screen to position the banner. |
| size | AdMobBannerSize | ANCHORED_ADAPTIVE | The banner size to request. |
| collapsible | "top" \| "bottom" | -- | Enable collapsible banner; value specifies collapsed position. |
| autoShow | boolean | true | Automatically show the banner after it loads. |
| isOverlapping | boolean | true | Whether the banner overlaps app content instead of pushing it. |
| margin | number | 0 | Margin in pixels from the top or bottom screen edge. |
| npa | boolean | false | Set to true to request Non-Personalized Ads for this request. |
FullScreenAdOptions
| Property | Type | Default | Description |
| ---------- | --------- | -------------- | ----------------------------------------- |
| adUnitId | string | (required) | The ad unit ID to load. |
| autoShow | boolean | true | Automatically show the ad after it loads. |
| npa | boolean | false | Request Non-Personalized Ads for this request. |
| immersiveMode | boolean | false | Android only. Hide system navigation during fullscreen ad display. |
SdkInitResult
| Property | Type | Description |
| --------------- | -------- | --------------------------------------------------------- |
| version | string | The Google Mobile Ads SDK version string. |
| consentStatus | string | The consent status at the time of initialization. |
| adapters | any[] | Mediation adapter initialization statuses (if available). |
AdRevenueInfo
| Property | Type | Description |
| ----------- | -------- | --------------------------------------------------------------------------------- |
| micros | number | Revenue value in micros (e.g., 15000000 = $15). |
| currency | string | ISO 4217 currency code (e.g., "USD"). |
| precision | number | Precision type (0 = unknown, 1 = estimated, 2 = publisher-provided, 3 = precise). |
| adUnitId | string | The ad unit ID that generated the revenue. |
AdErrorInfo
| Property | Type | Description |
| --------- | --------- | -------------------------------------------------- |
| code | number | Numeric error code. |
| message | string | Human-readable error message. |
| domain | string | Error domain (e.g., "com.google.android.gms.ads"). |
| cause | string? | Optional underlying cause description. |
RewardInfo
| Property | Type | Description |
| -------- | -------- | ------------------------------------------------------------- |
| type | string | The type / label of the reward (configured in AdMob console). |
| amount | number | The amount of the reward. |
BannerLoadResult
| Property | Type | Description |
| -------- | -------- | -------------------------------------------------------------- |
| height | number | The height of the loaded banner in density-independent pixels. |
CollapsibleResult
| Property | Type | Description |
| --------------- | --------- | ------------------------------------------------- |
| isCollapsible | boolean | Whether the loaded banner is in collapsible mode. |
ConsentInfo
| Property | Type | Description |
| --------------- | --------------- | --------------------------------------------------------- |
| status | ConsentStatus | The user's consent status. |
| canRequestAds | boolean | Whether the app is allowed to request (personalized) ads. |
IabTcfInfo
| Property | Type | Description |
| ------------------------ | --------- | ---------------------------------- |
| IABTCF_CmpSdkID | number? | CMP SDK ID. |
| IABTCF_gdprApplies | string? | Whether GDPR applies ("0" or "1"). |
| IABTCF_PurposeConsents | string? | Purpose consents bitfield string. |
| IABTCF_TCString | string? | The full TC string. |
AdResponseInfo
| Property | Type | Description |
| --------------------------- | --------- | ------------------------------------------------------- |
| responseId | string? | Unique response identifier. |
| mediationAdapterClassName | string? | Class name of the mediation adapter that served the ad. |
| adapterResponses | any[]? | Array of individual adapter response details. |
Events Reference
Banner Events
| Event Name | Payload Type | When It Fires |
| --------------------- | ------------------- | ---------------------------------------- |
| onBannerLoaded | BannerLoadResult | Banner ad has loaded successfully. |
| onBannerFailed | AdErrorInfo | Banner ad failed to load. |
| onBannerClicked | -- | User tapped on the banner. |
| onBannerImpression | -- | Banner impression was recorded. |
| onBannerOpened | -- | Banner opened a full-screen overlay. |
| onBannerClosed | -- | Banner's full-screen overlay was closed. |
| onBannerCollapsible | CollapsibleResult | Collapsible banner state changed. |
Interstitial Events
| Event Name | Payload Type | When It Fires |
| ---------------------------- | ------------- | ------------------------------------------------ |
| onInterstitialLoaded | -- | Interstitial ad has loaded and is ready to show. |
| onInterstitialFailed | AdErrorInfo | Interstitial ad failed to load. |
| onInterstitialShowed | -- | Interstitial ad is now visible on screen. |
| onInterstitialDismissed | -- | User dismissed the interstitial ad. |
| onInterstitialClicked | -- | User tapped the interstitial ad. |
| onInterstitialImpression | -- | Interstitial impression was recorded. |
| onInterstitialFailedToShow | AdErrorInfo | Loaded interstitial failed to display. |
Rewarded Events
| Event Name | Payload Type | When It Fires |
| ------------------------ | ------------- | ------------------------------------------------- |
| onRewardedLoaded | -- | Rewarded ad has loaded and is ready to show. |
| onRewardedFailed | AdErrorInfo | Rewarded ad failed to load. |
| onRewardedShowed | -- | Rewarded ad is now visible on screen. |
| onRewardedDismissed | -- | User dismissed the rewarded ad. |
| onRewardedClicked | -- | User tapped the rewarded ad. |
| onRewardedImpression | -- | Rewarded impression was recorded. |
| onRewardedFailedToShow | AdErrorInfo | Loaded rewarded ad failed to display. |
| onRewardEarned | RewardInfo | User completed the ad and earned the reward. |
| onRewardedSkipped | -- | User dismissed the ad without earning the reward. |
Rewarded Interstitial Events
| Event Name | Payload Type | When It Fires |
| ------------------------------------ | ------------- | ----------------------------------------------- |
| onRewardedInterstitialLoaded | -- | Rewarded interstitial has loaded. |
| onRewardedInterstitialFailed | AdErrorInfo | Rewarded interstitial failed to load. |
| onRewardedInterstitialShowed | -- | Rewarded interstitial is now visible. |
| onRewardedInterstitialDismissed | -- | User dismissed the rewarded interstitial. |
| onRewardedInterstitialClicked | -- | User tapped the rewarded interstitial. |
| onRewardedInterstitialImpression | -- | Rewarded interstitial impression was recorded. |
| onRewardedInterstitialFailedToShow | AdErrorInfo | Loaded rewarded interstitial failed to display. |
| onRewardedInterstitialRewardEarned | RewardInfo | User earned the reward from the interstitial. |
| onRewardedInterstitialSkipped | -- | User dismissed without earning the reward. |
App Open Events
| Event Name | Payload Type | When It Fires |
| ----------------------- | ------------- | ------------------------------------- |
| onAppOpenLoaded | -- | App open ad has loaded. |
| onAppOpenFailed | AdErrorInfo | App open ad failed to load. |
| onAppOpenShowed | -- | App open ad is now visible. |
| onAppOpenDismissed | -- | User dismissed the app open ad. |
| onAppOpenFailedToShow | AdErrorInfo | Loaded app open ad failed to display. |
General / SDK Events
| Event Name | Payload Type | When It Fires |
| --------------------- | --------------- | -------------------------------------------------------------------- |
| onAdRevenue | AdRevenueInfo | Any ad generated impression-level revenue. Fires for all ad formats. |
| onSdkInitialized | SdkInitResult | Google Mobile Ads SDK has finished initializing. |
| onConsentInfoUpdate | ConsentInfo | UMP consent status has been updated. |
Event Usage Example
import {AdMobAdvanced} from "cap-admob-advanced";
// Register a listener
const handle = await AdMobAdvanced.addListener("onBannerLoaded", (result) => {
console.log("Banner height:", result.height);
});
// Remove a specific listener when no longer needed
await handle.remove();
// Remove all listeners (e.g., on page destroy)
await AdMobAdvanced.removeAllListeners();Enums Reference
AdMobBannerSize
| Value | Description | Pixel Dimensions |
| --------------------- | -------------------------------------- | ---------------- |
| BANNER | Standard banner | 320 x 50 |
| LARGE_BANNER | Large banner | 320 x 100 |
| MEDIUM_RECTANGLE | IAB medium rectangle | 300 x 250 |
| FULL_BANNER | IAB full-size banner | 468 x 60 |
| LEADERBOARD | IAB leaderboard | 728 x 90 |
| RESPONSIVE_ADAPTIVE | Full-width adaptive, height auto | Varies |
| ANCHORED_ADAPTIVE | Anchored adaptive, fixed to edge | Varies |
| INLINE_ADAPTIVE | Inline adaptive for scrollable content | Varies |
BannerPosition
| Value | Description |
| --------------- | ----------------------------------- |
| TOP_CENTER | Banner at the top of the screen. |
| BOTTOM_CENTER | Banner at the bottom of the screen. |
MaxAdContentRating
| Value | Description |
| ----- | ----------------------------------------------------------- |
| G | Content suitable for general audiences. |
| PG | Content suitable for most audiences with parental guidance. |
| T | Content suitable for teen and older audiences. |
| MA | Content suitable only for mature audiences. |
ConsentStatus
| Value | Description |
| -------------- | -------------------------------------------------- |
| UNKNOWN | Consent status is unknown / not yet requested. |
| REQUIRED | User consent is required but not yet obtained. |
| NOT_REQUIRED | User consent is not required (e.g., non-EEA user). |
| OBTAINED | User consent has been obtained. |
ConsentDebugGeography
| Value | Description |
| ---------- | ---------------------------------- |
| DISABLED | Disabled -- use real geography. |
| EEA | Simulate a device in the EEA. |
| NOT_EEA | Simulate a device outside the EEA. |
AdMobError
| Value | Description |
| ------------------------- | -------------------------------------------------- |
| AD_LOAD_INVALID_REQUEST | The ad request was invalid (e.g., bad ad unit ID). |
| AD_LOAD_NETWORK_ERROR | Network error during ad load. |
| AD_LOAD_NO_FILL | Ad server returned no fill. |
| AD_LOAD_INTERNAL_ERROR | Internal error during ad load. |
| AD_SHOW_NOT_READY | Attempted to show an ad that is not ready. |
| AD_SHOW_ALREADY_SHOWING | Ad was already showing. |
| AD_UNKNOWN_ERROR | Unknown or unclassified error. |
Event Name Enums
For type-safe event listener registration, import and use these enums instead of raw strings:
import {
BannerAdPluginEvents,
InterstitialAdPluginEvents,
RewardAdPluginEvents,
RewardedInterstitialAdPluginEvents,
AppOpenAdPluginEvents,
GeneralAdPluginEvents,
} from "cap-admob-advanced";
// Instead of raw strings:
AdMobAdvanced.addListener("onBannerLoaded", handler);
// Use type-safe enums:
AdMobAdvanced.addListener(BannerAdPluginEvents.Loaded, handler);
AdMobAdvanced.addListener(RewardAdPluginEvents.Rewarded, handler);
AdMobAdvanced.addListener(GeneralAdPluginEvents.AdRevenue, handler);BannerAdPluginEvents
| Key | Value |
| ------------- | ------------------- |
| Loaded | onBannerLoaded |
| Failed | onBannerFailed |
| Clicked | onBannerClicked |
| Impression | onBannerImpression|
| Opened | onBannerOpened |
| Closed | onBannerClosed |
| Collapsible | onBannerCollapsible|
| SizeChanged | onBannerLoaded |
InterstitialAdPluginEvents
| Key | Value |
| -------------- | ------------------------------ |
| Loaded | onInterstitialLoaded |
| Failed | onInterstitialFailed |
| Showed | onInterstitialShowed |
| Dismissed | onInterstitialDismissed |
| Clicked | onInterstitialClicked |
| Impression | onInterstitialImpression |
| FailedToShow | onInterstitialFailedToShow |
RewardAdPluginEvents
| Key | Value |
| -------------- | ------------------------ |
| Loaded | onRewardedLoaded |
| Failed | onRewardedFailed |
| Showed | onRewardedShowed |
| Dismissed | onRewardedDismissed |
| Clicked | onRewardedClicked |
| Impression | onRewardedImpression |
| FailedToShow | onRewardedFailedToShow |
| Rewarded | onRewardEarned |
| Skipped | onRewardedSkipped |
AppOpenAdPluginEvents
| Key | Value |
| -------------- | ----------------------- |
| Loaded | onAppOpenLoaded |
| Failed | onAppOpenFailed |
| Showed | onAppOpenShowed |
| Dismissed | onAppOpenDismissed |
| FailedToShow | onAppOpenFailedToShow |
GeneralAdPluginEvents
| Key | Value |
| ------------------ | --------------------- |
| AdRevenue | onAdRevenue |
| SdkInitialized | onSdkInitialized |
| ConsentInfoUpdate | onConsentInfoUpdate |
Mediation Setup
The Google Mobile Ads SDK handles mediation automatically. To add third-party mediation adapters, include the adapter dependencies in your native project configuration.
Android (build.gradle)
Add mediation adapter dependencies to your app-level android/app/build.gradle:
dependencies {
// Meta Audience Network
implementation 'com.google.ads.mediation:facebook:6.18.0.1'
// Unity Ads
implementation 'com.google.ads.mediation:unity:4.12.4.0'
// AppLovin
implementation 'com.google.ads.mediation:applovin:13.0.1.0'
// AdColony (now Digital Turbine Exchange)
implementation 'com.google.ads.mediation:adcolony:4.8.0.3'
// Vungle (now Liftoff Monetize)
implementation 'com.google.ads.mediation:vungle:7.4.2.0'
}iOS (Podfile)
Add mediation adapter pods to your ios/App/Podfile:
target 'App' do
# ... existing pods ...
# Meta Audience Network
pod 'GoogleMobileAdsMediationFacebook'
# Unity Ads
pod 'GoogleMobileAdsMediationUnity'
# AppLovin
pod 'GoogleMobileAdsMediationAppLovin'
# AdColony (Digital Turbine Exchange)
pod 'GoogleMobileAdsMediationAdColony'
# Vungle (Liftoff Monetize)
pod 'GoogleMobileAdsMediationVungle'
endAfter adding adapter dependencies, run:
# Android
npx cap sync android
# iOS
npx cap sync ios
# or
cd ios/App && pod installAlways check the AdMob Mediation documentation for the latest adapter versions and setup instructions.
Test Ad Unit IDs
Use these official Google test ad unit IDs during development. They return test ads and will not generate real revenue or policy violations.
| Ad 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 |
| Collapsible Banner | ca-app-pub-3940256099942544/2014213617 | ca-app-pub-3940256099942544/8388050270 |
Important: Never use test ad unit IDs in production builds. Replace them with your real ad unit IDs from the AdMob console before publishing.
Migration from @capacitor-community/admob
This plugin provides drop-in migration aliases for the official plugin's API names:
// These work identically -- use whichever you prefer:
AdMobAdvanced.showBannerAd(opts); // alias -> loadBanner({...opts, autoShow: true})
AdMobAdvanced.prepareInterstitial(opts); // alias -> loadInterstitial(opts)
AdMobAdvanced.prepareRewardVideoAd(opts); // alias -> loadRewarded(opts)
AdMobAdvanced.showRewardVideoAd(); // alias -> showRewarded()
AdMobAdvanced.resumeBanner(); // alias -> showBanner()Event enums are also compatible:
// Official plugin style (still works):
AdMobAdvanced.addListener(BannerAdPluginEvents.SizeChanged, handler);
AdMobAdvanced.addListener(RewardAdPluginEvents.Rewarded, handler);Troubleshooting
"App ID not set" / "Missing Application ID"
Cause: The AdMob App ID is not configured in your native project.
Android fix: Verify that your AndroidManifest.xml contains:
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-XXXXXXXXXXXXXXXX~YYYYYYYYYY" />iOS fix: Verify that your Info.plist contains:
<key>GADApplicationIdentifier</key>
<string>ca-app-pub-XXXXXXXXXXXXXXXX~YYYYYYYYYY</string>"No fill" errors
Cause: The ad network has no ads available for the current request.
Solutions:
- Use test ad unit IDs during development (they always fill).
- No fill is normal in production -- not every request will return an ad.
- Implement retry logic with exponential backoff.
- Add mediation adapters to increase fill rates.
- Check that your ad units are approved and active in the AdMob console.
Consent form not showing
Cause: The UMP SDK determined that consent is not required for the user's geography.
Solutions:
- Use
isConsentDebug: trueininitialize()to simulate EEA geography during testing. - Use
forceDisplayPrivacyForm()to force the form to display regardless of status. - Call
consentReset()to clear previous consent state and re-test.
Banner not visible
Cause: The banner may be loaded but hidden, or it may be positioned behind other UI elements.
Solutions:
- Ensure
autoShow: trueis set, or callshowBanner()after loading. - Check the
isOverlappingoption. Iffalse, the web view is resized to make room for the banner. Iftrue, the banner overlaps the content. - Verify that no other view is covering the banner position.
- Add bottom/top padding to your app content to account for the banner height.
Android: ProGuard / R8 issues
If you encounter issues with minified release builds, add these ProGuard rules to android/app/proguard-rules.pro:
-keep class com.google.android.gms.ads.** { *; }
-keep class com.google.ads.** { *; }
-keep class com.capacitor.admob.advanced.** { *; }iOS: Missing frameworks
If you see linker errors related to Google Mobile Ads:
- Ensure
pod installhas been run in theios/Appdirectory. - Verify that
Google-Mobile-Ads-SDKandGoogleUserMessagingPlatformappear in yourPodfile.lock. - Clean and rebuild:
cd ios/App && pod deintegrate && pod install. - In Xcode, ensure
Build Settings > Other Linker Flagsincludes-ObjC.
Android 15 (API 35) full-screen ad rendering issues
The plugin includes an automatic workaround for Android 15's edge-to-edge enforcement that can cause AdActivity to render behind system bars. This is handled automatically -- no configuration needed.
Contributing
Contributions are welcome. Please follow these guidelines:
Workflow
- Fork the repository.
- Create a feature branch from
main:git checkout -b feature/your-feature. - Make your changes.
- Ensure the plugin builds successfully:
npm run build - Test on both Android and iOS devices/emulators.
- Commit with clear, descriptive messages.
- Open a pull request against
main.
Code Style
- TypeScript: Follow the existing code style. Use strict types and avoid
anywhere possible. - Kotlin: Follow Kotlin coding conventions. Use
@PluginMethodannotation for bridge methods. - Swift: Follow Swift API Design Guidelines. Use
@objcannotation for bridge methods.
Testing Guidelines
- Test every ad format on both platforms.
- Test with both test ad unit IDs and real ad unit IDs (in a test AdMob account).
- Verify consent flow in EEA and non-EEA simulated geographies.
- Test on both physical devices and emulators/simulators.
- Test the web stub to ensure
ionic servedoes not crash.
Updating the Plugin
Updating the Google Mobile Ads SDK
Android
Edit android/build.gradle and update the version numbers:
dependencies {
implementation "com.google.android.gms:play-services-ads:24.9.0" // Update this
implementation "com.google.android.ump:user-messaging-platform:4.0.0" // Update this
implementation "com.google.ads.mediation:admob:24.9.0.0" // Update this
}iOS
Edit ios/AdMobAdvancedPlugin.podspec and update the version:
s.dependency 'Google-Mobile-Ads-SDK', '~> 12.14.0' # Update this
s.dependency 'GoogleUserMessagingPlatform', '~> 3.1.0' # Update thisThen run pod update in your ios/App directory.
Adding New Ad Formats
To add a new ad format in the future:
- TypeScript: Add method signatures to
src/definitions.ts, add event types, and implement the web stub insrc/web.ts. - Android: Create a new manager class (e.g.,
NewFormatAdManager.kt) and add@PluginMethodbridge methods inAdMobAdvancedPlugin.kt. - iOS: Create a new manager class (e.g.,
NewFormatAdManager.swift) and add@objcbridge methods inAdMobAdvancedPlugin.swift. Register new methods inpluginMethods. - Rebuild:
npm run build && npx cap sync.
Migration Notes
This plugin targets Capacitor 7.x and uses the CAPBridgedPlugin protocol on iOS (introduced in Capacitor 6). If migrating from an older Capacitor version:
- Ensure your app is on Capacitor 7.x (
@capacitor/core ^7.0.0). - On iOS, the plugin uses Swift 5.9 and requires a deployment target of 14.0.
- On Android, the plugin requires
minSdk 23,compileSdk 35, and Java 17.
License
MIT
Copyright (c) 2025
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
