From 2ce0fd3f7031dc621f4c32237918896ece77155f Mon Sep 17 00:00:00 2001 From: exzos Date: Fri, 4 Sep 2026 15:28:51 +0200 Subject: [PATCH 1/2] feat(ump): add Expo config plugin for the AdMob App ID MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The UMP SDK requires a Google-issued AdMob App ID (com.google.android.gms.ads.APPLICATION_ID / GADApplicationIdentifier) to run at all. Under Expo/CNG that can't just be hand-edited into android/ios — expo prebuild regenerates those directories from scratch. Add an app.plugin.js (androidAppId/iosAppId config, same createRunOncePlugin pattern as pangle/levelplay) that injects it on every prebuild. Also reword the "Works with Expo out of the box" Features bullet on unity/liftoff to "Expo CNG supported" — the previous phrasing read oddly next to the other packages' plugin-specific bullets. --- packages/liftoff/README.md | 2 +- packages/ump/README.md | 55 ++++++++++++++++++++++++------------- packages/ump/app.plugin.js | 56 ++++++++++++++++++++++++++++++++++++++ packages/ump/package.json | 3 ++ packages/unity/README.md | 2 +- 5 files changed, 97 insertions(+), 21 deletions(-) create mode 100644 packages/ump/app.plugin.js diff --git a/packages/liftoff/README.md b/packages/liftoff/README.md index 87eec53..b0def9e 100644 --- a/packages/liftoff/README.md +++ b/packages/liftoff/README.md @@ -11,7 +11,7 @@ Native. - 🎯 Liftoff Monetize (Vungle) — interstitial and rewarded video - ⚡️ [Nitro Modules](https://nitro.margelo.com/) — direct JSI bindings, no bridge overhead - 📱 iOS & Android -- 🧩 Works with Expo out of the box — no config plugin needed +- 🧩 Expo CNG supported - 🔒 Fully typed API ## Installation diff --git a/packages/ump/README.md b/packages/ump/README.md index afa40a0..f4ddfb0 100644 --- a/packages/ump/README.md +++ b/packages/ump/README.md @@ -10,11 +10,18 @@ Google User Messaging Platform (UMP) — GDPR/CCPA consent for React Native. - 🔐 Google UMP — GDPR/CCPA consent gathering and the privacy options form - ⚡️ [Nitro Modules](https://nitro.margelo.com/) — direct JSI bindings, no bridge overhead - 📱 iOS & Android -- 🧩 Works with Expo out of the box — no config plugin needed +- 🧩 Expo config plugin included — wires up your AdMob App ID automatically - 🔒 Fully typed API ## Installation +The UMP SDK refuses to run without a Google-issued AdMob App ID, even if you +don't use AdMob/Google Mobile Ads — omitting it throws +`The UMP SDK requires a valid application ID`. Don't have an AdMob app? +Create one for free in the [AdMob console](https://apps.admob.com/), or use +Google's public test IDs while developing — see the [`example`](example) +app for both platforms' values. + ### React Native ```sh @@ -22,19 +29,6 @@ npm install @react-native-ads/ump react-native-nitro-modules cd ios && pod install ``` -### Expo - -```sh -npx expo install @react-native-ads/ump react-native-nitro-modules -npx expo prebuild -``` - -### Required native setup - -The UMP SDK refuses to run without a Google-issued AdMob App ID, even if you -don't use AdMob/Google Mobile Ads — omitting this throws -`The UMP SDK requires a valid application ID`. - Android — add to `android/app/src/main/AndroidManifest.xml`: ```xml @@ -50,11 +44,34 @@ iOS — add to `Info.plist`: YOUR_ADMOB_APP_ID ``` -Don't have an AdMob app? Create one for free in the -[AdMob console](https://apps.admob.com/) to get an App ID, or use Google's -public test IDs while developing (`ca-app-pub-3940256099942544~3347511713` -on Android, `ca-app-pub-3940256099942544~1458002511` on iOS — see the -[`example`](example) app). +### Expo + +```sh +npx expo install @react-native-ads/ump react-native-nitro-modules +``` + +Enable the bundled config plugin — it wires up the App ID on both platforms +for you: + +```json +{ + "expo": { + "plugins": [ + [ + "@react-native-ads/ump", + { + "androidAppId": "YOUR_ADMOB_APP_ID", + "iosAppId": "YOUR_ADMOB_APP_ID" + } + ] + ] + } +} +``` + +```sh +npx expo prebuild +``` ## API diff --git a/packages/ump/app.plugin.js b/packages/ump/app.plugin.js new file mode 100644 index 0000000..ac7c0e8 --- /dev/null +++ b/packages/ump/app.plugin.js @@ -0,0 +1,56 @@ +const { + AndroidConfig, + createRunOncePlugin, + withAndroidManifest, + withInfoPlist, +} = require('expo/config-plugins'); +const packageJson = require('./package.json'); + +// The UMP SDK refuses to run without a Google-issued AdMob App ID, even if +// the app doesn't use AdMob/Google Mobile Ads — see the package README. + +function withUMPAndroidAppId(config, androidAppId) { + return withAndroidManifest(config, (modConfig) => { + const mainApplication = AndroidConfig.Manifest.getMainApplicationOrThrow( + modConfig.modResults + ); + AndroidConfig.Manifest.addMetaDataItemToMainApplication( + mainApplication, + 'com.google.android.gms.ads.APPLICATION_ID', + androidAppId + ); + return modConfig; + }); +} + +function withUMPIosAppId(config, iosAppId) { + return withInfoPlist(config, (modConfig) => { + modConfig.modResults.GADApplicationIdentifier = iosAppId; + return modConfig; + }); +} + +function withUMPAds(config, { androidAppId, iosAppId } = {}) { + if (!androidAppId || !iosAppId) { + throw new Error( + "@react-native-ads/ump config plugin requires both 'androidAppId' and " + + "'iosAppId' — the UMP SDK requires a Google-issued AdMob App ID to " + + 'run. Pass them in app.json/app.config, e.g.:\n' + + '["@react-native-ads/ump", { "androidAppId": "ca-app-pub-XXXXXXXXXXXXXXXX~XXXXXXXXXX", "iosAppId": "ca-app-pub-XXXXXXXXXXXXXXXX~XXXXXXXXXX" }]' + ); + } + + config = withUMPAndroidAppId(config, androidAppId); + config = withUMPIosAppId(config, iosAppId); + return config; +} + +const plugin = createRunOncePlugin( + withUMPAds, + packageJson.name, + packageJson.version +); + +module.exports = plugin; +module.exports.default = plugin; +module.exports.withUMPAds = withUMPAds; diff --git a/packages/ump/package.json b/packages/ump/package.json index fb29ba2..b0b10d1 100644 --- a/packages/ump/package.json +++ b/packages/ump/package.json @@ -10,6 +10,7 @@ "types": "./lib/typescript/src/index.d.ts", "default": "./lib/module/index.js" }, + "./app.plugin.js": "./app.plugin.js", "./package.json": "./package.json" }, "files": [ @@ -22,6 +23,7 @@ "nitro.json", "*.podspec", "react-native.config.js", + "app.plugin.js", "!ios/build", "!android/build", "!android/gradle", @@ -58,6 +60,7 @@ "user-messaging-platform", "admob", "google-mobile-ads", + "expo", "ios", "android" ], diff --git a/packages/unity/README.md b/packages/unity/README.md index 5b80527..77a3efd 100644 --- a/packages/unity/README.md +++ b/packages/unity/README.md @@ -10,7 +10,7 @@ Unity Ads — interstitial and rewarded video ads for React Native. - 🎮 Unity Ads — interstitial and rewarded video - ⚡️ [Nitro Modules](https://nitro.margelo.com/) — direct JSI bindings, no bridge overhead - 📱 iOS & Android -- 🧩 Works with Expo out of the box — no config plugin needed +- 🧩 Expo CNG supported - 🔒 Fully typed API ## Installation From c0a19eb0fb30377a63e4814d317293c4bafaa468 Mon Sep 17 00:00:00 2001 From: exzos Date: Fri, 4 Sep 2026 15:30:55 +0200 Subject: [PATCH 2/2] chore(ump): declare optional expo peer dep; unify Expo README bullet MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ump's app.plugin.js imports from expo/config-plugins but package.json never declared expo as a (peer) dependency, unlike pangle's plugin — levelplay had the same gap. Add expo as an optional peerDependency + devDependency, matching pangle's existing pattern. Also collapse all five packages' Features bullet about Expo down to the same "Expo CNG supported" line instead of each spelling out what its plugin does (or doesn't) do. --- packages/levelplay/README.md | 2 +- packages/pangle/README.md | 2 +- packages/ump/README.md | 2 +- packages/ump/package.json | 7 +++++++ yarn.lock | 5 +++++ 5 files changed, 15 insertions(+), 3 deletions(-) diff --git a/packages/levelplay/README.md b/packages/levelplay/README.md index 871268b..5275a05 100644 --- a/packages/levelplay/README.md +++ b/packages/levelplay/README.md @@ -11,7 +11,7 @@ for React Native. - 🎯 LevelPlay (ironSource) mediation — interstitial and rewarded video - ⚡️ [Nitro Modules](https://nitro.margelo.com/) — direct JSI bindings, no bridge overhead - 📱 iOS & Android -- 🧩 Expo config plugin included — adds LevelPlay's Maven repo automatically +- 🧩 Expo CNG supported - 🔒 Fully typed API ## Installation diff --git a/packages/pangle/README.md b/packages/pangle/README.md index c2c9fb8..9b01f80 100644 --- a/packages/pangle/README.md +++ b/packages/pangle/README.md @@ -10,7 +10,7 @@ Pangle — interstitial and rewarded video ads for React Native. - 🎯 Pangle — interstitial and rewarded video - ⚡️ [Nitro Modules](https://nitro.margelo.com/) — direct JSI bindings, no bridge overhead - 📱 iOS & Android -- 🧩 Expo config plugin included — adds Pangle's Maven repo automatically +- 🧩 Expo CNG supported - 🔒 Fully typed API ## Installation diff --git a/packages/ump/README.md b/packages/ump/README.md index f4ddfb0..d0643ef 100644 --- a/packages/ump/README.md +++ b/packages/ump/README.md @@ -10,7 +10,7 @@ Google User Messaging Platform (UMP) — GDPR/CCPA consent for React Native. - 🔐 Google UMP — GDPR/CCPA consent gathering and the privacy options form - ⚡️ [Nitro Modules](https://nitro.margelo.com/) — direct JSI bindings, no bridge overhead - 📱 iOS & Android -- 🧩 Expo config plugin included — wires up your AdMob App ID automatically +- 🧩 Expo CNG supported - 🔒 Fully typed API ## Installation diff --git a/packages/ump/package.json b/packages/ump/package.json index b0b10d1..f597501 100644 --- a/packages/ump/package.json +++ b/packages/ump/package.json @@ -88,16 +88,23 @@ "@babel/preset-typescript": "^7.27.1", "@types/react": "^19.2.0", "babel-jest": "^29.7.0", + "expo": "*", "nitrogen": "0.29.6", "react": "19.2.3", "react-native": "0.85.0", "react-native-nitro-modules": "^0.29.6" }, "peerDependencies": { + "expo": "*", "react": "*", "react-native": "*", "react-native-nitro-modules": "^0.29.6" }, + "peerDependenciesMeta": { + "expo": { + "optional": true + } + }, "workspaces": [ "example" ], diff --git a/yarn.lock b/yarn.lock index b7851ab..4b89875 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3391,14 +3391,19 @@ __metadata: "@iabtcf/core": "npm:^1.5.6" "@types/react": "npm:^19.2.0" babel-jest: "npm:^29.7.0" + expo: "npm:*" nitrogen: "npm:0.29.6" react: "npm:19.2.3" react-native: "npm:0.85.0" react-native-nitro-modules: "npm:^0.29.6" peerDependencies: + expo: "*" react: "*" react-native: "*" react-native-nitro-modules: ^0.29.6 + peerDependenciesMeta: + expo: + optional: true languageName: unknown linkType: soft