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/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/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 afa40a0..d0643ef 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 CNG supported - 🔒 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..f597501 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" ], @@ -85,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/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 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