npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

capacitor-levelplay-ads

v0.1.15

Published

Unity LevelPlay mediation SDK for Capacitor with banner, interstitial and rewarded ads supported.

Downloads

1,175

Readme

capacitor-levelplay-ads

Android iOS LevelPlay NPM version Downloads License

Unity LevelPlay mediation for Capacitor.

This plugin integrates the Unity LevelPlay mediation SDK (formerly ironSource) into Capacitor.

Banner, interstitial and rewarded ads are supported.

Ads can be served across every mediated demand source from a single, modular API with zero mandatory native configuration.


📦 SDK Versions

| Component | Platform | Version | | :--- | :--- | :--- | | LevelPlay Mediation SDK | Android | com.unity3d.ads-mediation:mediation-sdk:9.4.0 | | IronSource SDK | iOS | IronSourceSDK (CocoaPods) |


✨ Key Features

  • Mediation-first: One LevelPlay app key fans out to every network you enable — AdMob, AppLovin, Unity Ads, Vungle, Meta, Mintegral, Pangle.
  • IAB TCF v2.2 consent (default): Bundles the InMobi Choice CMP for GDPR-compliant consent — collects a TCF string and writes the standard IABTCF_* keys every mediation adapter reads. Swappable for a built-in non-TCF modal when shipping outside the EU.
  • CCPA & COPPA: First-class setCCPAConsent() and setChildDirected().
  • App Tracking Transparency: requestTrackingAuthorization() prompts ATT on iOS and is a safe no-op on Android.
  • Impression-level revenue (ILRD): Subscribe to onAdRevenue for per-impression revenue across all networks.
  • Android 15 edge-to-edge ready: Automated lifecycle workaround so fullscreen ad close buttons are never hidden behind the system bars.
  • Anti-spam rate limiting: Built-in per-ad load throttling protects your account from invalid-traffic penalties.
  • Opt-in network injection: Mediation adapter pods/gradle deps are injected at sync time from a single levelplay.networks key — no manual XML edits.

📦 Installation

npm install capacitor-levelplay-ads
npx cap sync

⚙️ Configuration (Mediation Networks)

Mediation network adapters are opt-in. The plugin bundles only the core LevelPlay SDK; each demand source you want is wired in by a Capacitor CLI hook.

  1. Add a levelplay block to your app's root package.json:
{
  "name": "your-app-name",
  "levelplay": {
    "networks": ["admob", "applovin", "unityads"],
    "userTrackingDescription": "This identifier is used to deliver personalized ads to you.",
    "consentProvider": "inmobi",
    "inmobi": {
      "pCode": "YOUR_PCODE_HERE"
    }
  }
}

Supported network keys: admob, applovin, unityads, vungle, meta, mintegral, pangle.

Consent provider

The consentProvider key picks how the plugin collects GDPR consent:

| Value | What it does | When to use | |---|---|---| | inmobi (default) | Bundles InMobi Choice CMP. IAB TCF v2.2 compliant. Auto-shows the CMP on first launch and writes the standard IABTCF_* keys to SharedPreferences (Android) / NSUserDefaults (iOS). | Apps shipped in the EU/EEA. Required for GDPR audit compliance. | | custom | Built-in alert dialog. Writes a permissive gdprApplies=0 stub. Not TCF compliant. | Apps that ship outside the EU only, or where you already integrate a different CMP. |

When consentProvider: "inmobi", set levelplay.inmobi.pCode to the pCode from your InMobi Choice workspace (strip the leading p-). Optionally set levelplay.inmobi.packageId to override the property package id; defaults to the app's applicationId/bundle id.

Once configured, the plugin auto-initializes the CMP at process start (Android: via a ContentProvider that runs in Application.onCreate; iOS: from AppDelegate.didFinishLaunching via plugin load). You still call LevelPlayAds.requestConsentInfo() from JS — under inmobi that call resolves as soon as the user has interacted with the CMP UI.

  1. Register the hook in the scripts section of your package.json:
{
  "scripts": {
    "capacitor:sync:after": "node node_modules/capacitor-levelplay-ads/scripts/levelplay-manifest.js"
  }
}

On every npx cap sync the hook injects, for each selected network:

  • Android adapter implementation lines into android/app/build.gradle
  • iOS adapter pods into ios/App/Podfile
  • NSUserTrackingUsageDescription + per-network SKAdNetwork IDs into Info.plist

Transparency note: the injection script is strictly OPT-IN and only runs if you explicitly declare the hook above.

Manual alternative

If you'd rather not run the hook, do the equivalent edits yourself:

Android — add the adapters you need to android/app/build.gradle:

dependencies {
    implementation 'com.unity3d.ads-mediation:admob-adapter:4.3.46'
    implementation 'com.unity3d.ads-mediation:applovin-adapter:4.3.39'
    implementation 'com.unity3d.ads-mediation:unityads-adapter:4.3.44'
    // …one per network from the supported list above
}

iOS — add the matching pods to ios/App/Podfile inside the App target:

pod 'IronSourceAdMobAdapter'
pod 'IronSourceAppLovinAdapter'
pod 'IronSourceUnityAdsAdapter'

iOS — ios/App/App/Info.plist (required for ATT prompt + attribution):

<key>NSUserTrackingUsageDescription</key>
<string>This identifier will be used to deliver personalized ads to you.</string>
<key>SKAdNetworkItems</key>
<array>
    <dict><key>SKAdNetworkIdentifier</key><string>su67r6k2v3.skadnetwork</string></dict> <!-- IronSource -->
    <dict><key>SKAdNetworkIdentifier</key><string>cstr6suwn9.skadnetwork</string></dict> <!-- AdMob -->
    <dict><key>SKAdNetworkIdentifier</key><string>ludvb6z3bs.skadnetwork</string></dict> <!-- AppLovin -->
    <dict><key>SKAdNetworkIdentifier</key><string>4dzt52r2t5.skadnetwork</string></dict> <!-- UnityAds -->
    <!-- Vungle: gta9lk7p23.skadnetwork -->
    <!-- Meta: v9wttpbfk9.skadnetwork, n38lu8286q.skadnetwork -->
    <!-- Mintegral: kbd757ywx3.skadnetwork -->
    <!-- Pangle: 238da6jt44.skadnetwork, 22mmun2rn5.skadnetwork -->
</array>

Without NSUserTrackingUsageDescription Apple will reject the build (the IronSource SDK calls ATTrackingManager). Without the matching SKAdNetwork IDs install attribution silently fails and mediation revenue reports go dark.

Adapter versions are pinned in scripts/levelplay-manifest.js — check that file for the current set if you're maintaining the edits by hand.


Install

To use npm:

npm install capacitor-levelplay-ads

To use yarn:

yarn add capacitor-levelplay-ads

Sync native files:

npx cap sync

🚀 Quick Setup

A minimal flow: initialize the SDK, ask for consent, then load and show an interstitial.

import { LevelPlayAds } from 'capacitor-levelplay-ads';

async function bootstrapAds() {
  // 1. Initialize the LevelPlay SDK with your app key.
  await LevelPlayAds.initialize({
    appKey: 'YOUR_LEVELPLAY_APP_KEY',
    isTesting: true, // remove or set to false in production
  });

  // 2. Request a GDPR / consent decision. The plugin shows a custom modal
  //    on first run and reuses the stored decision afterwards.
  const consent = await LevelPlayAds.requestConsentInfo({
    privacyPolicyUrl: 'https://example.com/privacy',
    networks: ['admob', 'meta'], // optional — must match your levelplay.networks
  });

  if (!consent.canRequestAds) {
    console.log('User declined personalised ads.');
  }

  // 3. (iOS only) Ask for App Tracking Transparency. Resolves with
  //    "NOT_APPLICABLE" on Android, so the same call works cross-platform.
  await LevelPlayAds.requestTrackingAuthorization();

  // 4. Pre-load an interstitial. Use AdEvent constants instead of raw
  //    event-name strings so typos surface at compile time.
  LevelPlayAds.addListener(AdEvent.InterstitialLoaded, () => {
    console.log('Interstitial ready.');
  });
  LevelPlayAds.addListener(AdEvent.InterstitialClosed, () => {
    console.log('Interstitial closed — next ad is auto-reloading.');
  });

  // `autoShow: true` chains show() automatically once the ad loads —
  // the same promise resolves on display or rejects on display failure.
  await LevelPlayAds.loadInterstitial({
    adUnitId: 'YOUR_INTERSTITIAL_AD_UNIT',
    autoShow: false,
  });
}

async function showInterstitial() {
  const { isReady } = await LevelPlayAds.isInterstitialReady();
  if (isReady) {
    await LevelPlayAds.showInterstitial();
  }
}

// Optional: a sticky bottom-right banner that flips to bottom-left on rotation.
async function bannerWithRotation() {
  await LevelPlayAds.createBanner({
    adUnitId: 'YOUR_BANNER_AD_UNIT',
    adSize: 'ADAPTIVE',
    position: 'BOTTOM_RIGHT',
    isOverlap: false, // Android only — pushes the WebView up by banner height
  });

  LevelPlayAds.addListener(AdEvent.OrientationChanged, ({ orientation }) => {
    LevelPlayAds.updateBannerStyle({
      position: orientation === 'LANDSCAPE' ? 'BOTTOM_LEFT' : 'BOTTOM_RIGHT',
    });
  });
}

Import AdEvent alongside LevelPlayAds:

import { LevelPlayAds, AdEvent } from 'capacitor-levelplay-ads';

Position and size strings are case- and separator-insensitive at the JS layer — 'top-left', 'topLeft' and 'TOP_LEFT' all canonicalize to TOP_LEFT before reaching the native side.

⚠️ initialize and requestConsentInfo must complete before any loadInterstitial / loadRewarded / createBanner call — ad loads are rejected otherwise.


⚠️ Important Notices

1. iOS integration paths

CocoaPods is the primary, supported iOS integration path — it pulls the IronSource SDK via the podspec. Swift Package Manager is secondary; see Package.swift for details. Without the SDK the plugin still builds: all native SDK code is guarded and degrades to no-ops.

API

Capacitor LevelPlay Ads Plugin

Unity LevelPlay (formerly ironSource) mediation SDK for Capacitor.

CRITICAL: Proper Execution Order

To stay compliant with GDPR / CCPA / COPPA, follow this exact order at app start:

  1. Request Consent: await LevelPlayAds.requestConsentInfo(...) Shows the custom consent modal if the user has not decided yet.
  2. Initialize SDK: await LevelPlayAds.initialize(...) The SDK boots up using the consent decision gathered in step 1.
  3. Load Ads: e.g. await LevelPlayAds.loadInterstitial(...)
  4. Show Ads: e.g. await LevelPlayAds.showInterstitial()

Ad loading is gated: initialize() must have run and a consent decision must exist, otherwise load calls reject.

initialize(...)

initialize(options: InitializeOptions) => Promise<InitializeResult>

Initializes the LevelPlay mediation SDK. Call after requestConsentInfo().

| Param | Type | | ------------- | --------------------------------------------------------------- | | options | InitializeOptions |

Returns: Promise<InitializeResult>


launchTestSuite()

launchTestSuite() => Promise<void>

Launches the LevelPlay Test Suite for verifying mediation integration. Debug builds only.


requestConsentInfo(...)

requestConsentInfo(options?: ConsentOptions | undefined) => Promise<ConsentData>

Requests the current consent decision. If none exists, shows the custom consent modal. Must be called before loading ads.

| Param | Type | | ------------- | --------------------------------------------------------- | | options | ConsentOptions |

Returns: Promise<ConsentData>


showPrivacyOptions(...)

showPrivacyOptions(options?: ConsentOptions | undefined) => Promise<ConsentData>

Re-presents the consent modal so the user can change a prior decision. Wire this to a button in your app's settings/privacy screen.

| Param | Type | | ------------- | --------------------------------------------------------- | | options | ConsentOptions |

Returns: Promise<ConsentData>


getConsentData()

getConsentData() => Promise<ConsentData>

Returns the persisted consent decision without showing any UI.

Returns: Promise<ConsentData>


resetConsent()

resetConsent() => Promise<ConsentData>

Clears the stored consent decision so the next requestConsentInfo() re-shows the modal. Useful for QA flows and a "reset privacy choice" button in your settings screen.

Returns: Promise<ConsentData>


setCCPAConsent(...)

setCCPAConsent(options: { doNotSell: boolean; }) => Promise<void>

Sets the CCPA "do not sell my personal information" flag.

| Param | Type | | ------------- | ------------------------------------ | | options | { doNotSell: boolean; } |


setChildDirected(...)

setChildDirected(options: { isChildDirected: boolean; }) => Promise<void>

Sets the COPPA child-directed treatment flag.

| Param | Type | | ------------- | ------------------------------------------ | | options | { isChildDirected: boolean; } |


requestTrackingAuthorization()

requestTrackingAuthorization() => Promise<TrackingAuthorizationResult>

iOS only. Prompts the App Tracking Transparency (ATT) dialog. No-op on Android (resolves with status NOT_APPLICABLE).

Returns: Promise<TrackingAuthorizationResult>


getAdvertisingId()

getAdvertisingId() => Promise<AdvertisingIdResult>

Returns the platform advertising identifier:

  • Android — Google Advertising ID (GAID), via Play Services. limited is the LimitAdTracking flag.
  • iOS — IDFA, via ASIdentifierManager. The OS returns an all-zero UUID until the user grants App Tracking Transparency authorization, in which case limited is true and id is "00000000-0000-0000-0000-000000000000".

Call requestTrackingAuthorization() first on iOS to get a real value.

Returns: Promise<AdvertisingIdResult>


setDynamicUserId(...)

setDynamicUserId(options: { userId: string; }) => Promise<void>

Sets the dynamic user ID forwarded in server-to-server (S2S) reward callbacks. Call before showRewarded() to tag each reward with a verifiable token (e.g. a transaction ID or session nonce).

Can be changed between ad shows — the value active at show time is the one included in the S2S callback.

| Param | Type | | ------------- | -------------------------------- | | options | { userId: string; } |


createBanner(...)

createBanner(options: BannerOptions) => Promise<void>

Creates and loads a banner ad.

| Param | Type | | ------------- | ------------------------------------------------------- | | options | BannerOptions |


showBanner()

showBanner() => Promise<void>

Shows a previously created (and hidden) banner.


hideBanner()

hideBanner() => Promise<void>

Temporarily hides the banner without destroying it.


destroyBanner()

destroyBanner() => Promise<void>

Destroys the banner and removes it from the view hierarchy.


updateBannerStyle(...)

updateBannerStyle(options: BannerStyleOptions) => Promise<void>

Reposition or restyle the active banner without destroying it. Only the provided fields change; omitted fields keep their current value. isOverlap only affects Android — iOS always overlays the WebView.

| Param | Type | | ------------- | ----------------------------------------------------------------- | | options | BannerStyleOptions |


loadInterstitial(...)

loadInterstitial(options: AdLoadOptions) => Promise<void>

Loads an interstitial ad.

| Param | Type | | ------------- | ------------------------------------------------------- | | options | AdLoadOptions |


isInterstitialReady()

isInterstitialReady() => Promise<AdReadyResult>

Synchronously checks whether an interstitial ad is loaded and ready.

Returns: Promise<AdReadyResult>


showInterstitial()

showInterstitial() => Promise<void>

Shows the loaded interstitial ad.


loadRewarded(...)

loadRewarded(options: AdLoadOptions) => Promise<void>

Loads a rewarded ad.

| Param | Type | | ------------- | ------------------------------------------------------- | | options | AdLoadOptions |


isRewardedReady()

isRewardedReady() => Promise<AdReadyResult>

Synchronously checks whether a rewarded ad is loaded and ready.

Returns: Promise<AdReadyResult>


showRewarded()

showRewarded() => Promise<void>

Shows the loaded rewarded ad.


addListener(string, ...)

addListener(eventName: AdEventName | string, listenerFunc: (info: any) => void) => Promise<PluginListenerHandle>

Listens for native ad events.

Interstitial events

  • onInterstitialAdLoadedAdInfo
  • onInterstitialAdLoadFailedAdErrorInfo
  • onInterstitialAdDisplayedAdInfo
  • onInterstitialAdDisplayFailedAdErrorInfo
  • onInterstitialAdClickedAdInfo
  • onInterstitialAdClosedAdInfo
  • onInterstitialAdInfoChangedAdInfo

Rewarded events

  • onRewardedAdLoadedAdInfo
  • onRewardedAdLoadFailedAdErrorInfo
  • onRewardedAdDisplayedAdInfo
  • onRewardedAdDisplayFailedAdErrorInfo
  • onRewardedAdClickedAdInfo
  • onRewardedAdClosedAdInfo
  • onRewardedAdInfoChangedAdInfo
  • onRewardedAdRewardedAdRewardEvent

Banner events

  • onBannerAdLoadedAdInfo
  • onBannerAdLoadFailedAdErrorInfo
  • onBannerAdDisplayedAdInfo
  • onBannerAdDisplayFailedAdErrorInfo
  • onBannerAdClickedAdInfo
  • onBannerAdExpandedAdInfo
  • onBannerAdCollapsedAdInfo
  • onBannerAdLeftApplicationAdInfo

Revenue

  • onAdRevenueAdRevenueEvent (impression-level ad revenue / ILRD)

Consent

  • onConsentStatusChangedConsentData

Orientation

  • onOrientationChangedOrientationChangedEvent

Prefer the typed AdEvent constants (e.g. AdEvent.InterstitialLoaded) over raw strings for compile-time safety.

| Param | Type | | ------------------ | ----------------------------------- | | eventName | string | | listenerFunc | (info: any) => void |

Returns: Promise<PluginListenerHandle>


Interfaces

InitializeResult

| Prop | Type | Description | | ------------ | ------------------- | -------------------------------------- | | status | string | INITIALIZED_SUCCESSFULLY on success. |

InitializeOptions

| Prop | Type | Description | | --------------- | -------------------- | -------------------------------------------------------------------------------------------------------- | | appKey | string | LevelPlay app key from the Unity LevelPlay dashboard. Required. | | userId | string | Optional publisher-defined user identifier (used for server-to-server rewarded callbacks and reporting). | | isTesting | boolean | Enables LevelPlay test/integration mode. Set false before publishing. Default: false |

ConsentData

| Prop | Type | Description | | ------------------- | ----------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | status | 'UNKNOWN' | 'GRANTED' | 'DENIED' | The recorded consent decision. - UNKNOWN — no decision yet (fresh install). - GRANTED — user granted consent. - DENIED — user denied consent. | | granted | boolean | Simplified boolean: true when status === 'GRANTED'. | | canRequestAds | boolean | True when ads may be requested (a decision exists, granted or denied). | | provider | ConsentProvider | Which provider produced this decision: inmobi or custom. Useful for deciding whether to trust the tcString field. | | tcString | string | IAB TCF v2.2 consent string. Populated only when the inmobi provider is active and the user has interacted with the CMP. Undefined under custom (which doesn't produce a real TCF payload). |

ConsentOptions

| Prop | Type | Description | | ----------------------- | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | privacyPolicyUrl | string | URL opened when the user taps the privacy policy link in the modal. Only used by the custom consent provider — ignored under InMobi (which renders its own privacy policy link inside the CMP UI). | | title | string | Custom modal title. custom provider only. | | message | string | Custom modal body text. custom provider only. | | acceptButtonText | string | Label for the accept/grant button. custom provider only. | | declineButtonText | string | Label for the decline/deny button. custom provider only. | | networks | string[] | Mediation network keys the consent decision should be applied to. When omitted, consent is applied globally. |

TrackingAuthorizationResult

| Prop | Type | Description | | ------------ | ------------------- | ------------------------------------------------------------------------------------------------------ | | status | string | iOS ATT status: AUTHORIZED, DENIED, RESTRICTED, NOT_DETERMINED, or NOT_APPLICABLE (Android). |

AdvertisingIdResult

| Prop | Type | Description | | ------------- | -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | | id | string | The advertising identifier. Empty string when unavailable; on iOS the all-zeros UUID "00000000-0000-0000-0000-000000000000" when ATT is not authorized. | | limited | boolean | True when the user has limited / opted out of ad tracking. Android: LimitAdTracking flag. iOS: true when ATT is not authorized. |

BannerOptions

| Prop | Type | Description | | ------------------- | ------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | | adUnitId | string | LevelPlay banner ad unit ID. Required. | | adSize | 'BANNER' | 'LARGE' | 'MEDIUM_RECTANGLE' | 'LEADERBOARD' | 'ADAPTIVE' | Banner size. Default: ADAPTIVE. | | position | BannerPosition | Banner position on screen. Default: BOTTOM. | | isAutoShow | boolean | Show the banner automatically once loaded. Default: true. | | isOverlap | boolean | If true the banner overlaps the webview; if false it pushes the webview. Android only — iOS always overlays the WebView. Default: true. | | retryInterval | number | Minimum delay between consecutive load() calls, in milliseconds. Throttles invalid traffic. Default: 5000 (5 seconds). |

BannerStyleOptions

| Prop | Type | Description | | --------------- | --------------------------------------------------------- | -------------------------------------------- | | position | BannerPosition | New banner position. | | isOverlap | boolean | Android-only overlap flag. iOS ignores this. |

AdLoadOptions

| Prop | Type | Description | | ------------------- | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | adUnitId | string | LevelPlay ad unit ID. Required. | | autoShow | boolean | If true, the ad is shown immediately after a successful load. The returned promise then resolves on display (or rejects with "Auto-show failed: …"). Default: false. | | retryInterval | number | Minimum delay between consecutive load() calls, in milliseconds. Throttles invalid traffic. Default: 5000 (5 seconds). |

AdReadyResult

| Prop | Type | Description | | ------------- | -------------------- | -------------------------------------------- | | isReady | boolean | True when the ad is loaded and can be shown. |

PluginListenerHandle

| Prop | Type | | ------------ | ----------------------------------------- | | remove | () => Promise<void> |

Type Aliases

ConsentProvider

Which consent UI the plugin shows. Configured at install time via levelplay.consentProvider in the host app's package.json — not via JS.

  • inmobi (default): IAB TCF v2.2 compliant. Bundles InMobi Choice CMP. Requires levelplay.inmobi.pCode from https://choice.inmobi.com/.
  • custom: built-in alert dialog. Not TCF compliant; do not ship to EU.

'inmobi' | 'custom'

BannerPosition

Banner placement on screen. TOP_LEFT / TOP_RIGHT / BOTTOM_LEFT / BOTTOM_RIGHT anchor the banner to the corresponding screen corner; CENTER places it in the middle.

'TOP' | 'BOTTOM' | 'TOP_LEFT' | 'TOP_RIGHT' | 'BOTTOM_LEFT' | 'BOTTOM_RIGHT' | 'CENTER'

AdEventName

(typeof AdEvent)[keyof typeof AdEvent]