The Mapp Engage React Native plugin supports Expo through a config plugin. Expo apps get the plugin's native setup — permissions, services, capabilities — applied automatically on every prebuild, without manual native code changes.
Warning
Expo Go does not support this plugin, or any SDK with native code. You need a development build (
expo-dev-client) or EAS Build. This is the most common source of confusion when setting up Expo, so it is worth confirming before anything else.
Why a config plugin
Expo regenerates the native android and ios folders on every clean prebuild, which wipes any manual native setup. The config plugin reapplies the Mapp Engage native setup automatically each time you prebuild, so your configuration survives rebuilds — both local and via EAS Build.
Install
npx expo install react-native-mapp-plugin expo-dev-clientConfigure app.json
Add the plugin to the plugins array with the options for your project:
{
"expo": {
"name": "Mapp app",
"slug": "mapp-app",
"newArchEnabled": true,
"ios": {
"bundleIdentifier": "com.example.mappapp"
},
"android": {
"package": "com.example.mappapp",
"googleServicesFile": "./google-services.json"
},
"plugins": [
[
"react-native-mapp-plugin",
{
"android": {
"enableGeofencing": false,
"pushHandling": "mapp"
},
"ios": {
"appId": "MAPP_APP_ID",
"dmcSystemId": 123,
"sdkKey": "MAPP_SDK_KEY",
"isEu": true,
"inAppServerUrl": "MAPP_INAPP_SERVER_URL",
"openLandingPageInsideApp": false,
"customFields": ["customString", "customNumber", "customDate"],
"mediaTimeout": 5,
"enableGeofencing": false
}
}
]
]
}
}Android options
Option | Description |
|---|---|
| Adds fine and background location permissions when |
|
|
iOS options
Option | Description |
|---|---|
| Mapp Engage application ID. |
| Mapp DMC system ID. |
| Mapp SDK key. |
| Whether the application uses Mapp's EU environment. |
| In-app message server URL. |
| Opens push landing pages inside the app instead of the system browser. |
| Custom attribute keys the native SDK should expose, by type. |
| Rich Push media download timeout, in seconds. |
| Adds location usage descriptions and capabilities when |
The Android package must match the Firebase Android application in google-services.json. For iOS, configure an APNs-enabled App ID, a matching bundle identifier, and Apple/EAS signing credentials.
Note
Values in
app.jsonand native resources are public application configuration. Do not put service-account keys or signing secrets there.
The Firebase file is your own configuration. Point Expo's built-in expo.android.googleServicesFile field at it — this plugin does not copy, generate, or modify google-services.json.
Build and run
npx expo prebuild --clean
npx expo run:android
npx expo run:ios
# Cloud builds, after configuring EAS
eas build --profile development --platform all
eas build --profile preview --platform all
eas build --profile production --platform allChanging plugin options or native dependencies requires a new binary. JavaScript-only changes can use EAS Update.
Initialization
Register event listeners at application startup, then initialize Mapp. Since 2.0.0, engage() returns a promise — await it before calling APIs that depend on the native Mapp singleton. On iOS, the generated AppoxeeConfig.plist is the credential source of truth; the engage arguments remain relevant to Android.
import { Mapp, MappEventEmitter } from 'react-native-mapp-plugin';
const events = new MappEventEmitter();
const subscription = events.addListener('com.mapp.deep_link_received', event => {
// Route the deep link.
});
await Mapp.engage('ANDROID_SDK_KEY', 'FCM_PROJECT_ID', 'EMC', 'APP_ID', 'TENANT_ID');Android push ownership
pushHandling: "mapp" is the default. It requires expo.android.googleServicesFile and keeps com.reactlibrary.MessageService as the sole Mapp FCM callback owner. The config plugin removes the Mapp SDK v7 service from the merged app manifest.
Use pushHandling: "custom" when another integration — such as your own FirebaseMessagingService — owns callbacks. The plugin then removes both its own service and the Mapp SDK service, so your service owns callbacks. From native Android code, forward through MappPushHelper:
@Override public void onMessageReceived(RemoteMessage message) {
if (!MappPushHelper.handleMessage(getApplication(), message)) {
// Handle non-Mapp messages here.
}
}
@Override public void onNewToken(String token) {
MappPushHelper.handleNewToken(getApplication(), token);
}See the MappPushHelper reference for the full method list.
Note
Mapp.setRemoteMessage(...)remains available when JavaScript is guaranteed to be alive, but the native helper is required for reliable background and terminated delivery. If you also useexpo-notifications, use custom ownership with explicit native forwarding — a successful manifest merge alone does not forward payloads.
Geofencing
Set enableGeofencing on each platform that needs it. Android then adds fine and background location permissions, and Mapp.requestGeofenceLocationPermission() requests foreground permission before background permission. On iOS, also supply non-empty locationWhenInUsePermission and locationAlwaysPermission messages.
Note
Only request location access when your user-facing feature and store policy justify it.
iOS Rich Push
The config plugin creates a MappNotificationService Notification Service Extension with the bundle identifier <expo.ios.bundleIdentifier>.mappnotificationservice. The extension reads the public Mapp ios_apx_media payload key, downloads the media, and attaches it to the notification. It requires no additional CocoaPod or React Native code.
Warning
The extension must use the same iOS deployment target as your main app, or it loses connection to it. It is set to iOS 15+ by default. If you raise your app's deployment target, verify the extension target matches.
Note
The extension shares an App Group with the main app to connect the two for Rich Push. This is required — a project without a shared App Group cannot deliver Rich Push media.
The extension is also declared in Expo's experimental EAS app-extension metadata, so EAS can prepare its signing credentials. Regenerate the iOS project after changing the application bundle identifier.
Tested compatibility
Component | Tested baseline |
|---|---|
Expo SDK | 57 |
React Native | 0.86 (Expo SDK 57) |
New Architecture | Enabled |
Android min / compile / target SDK | 24 / 36 / 36 |
Android Gradle Plugin / Kotlin / JDK | 8.12 / 2.1.20 / 21 |
iOS deployment target | 16.4 (library minimum: 15.1) |
Mapp Android SDK | 7.1.2 |
Mapp iOS SDKs | Vendored xcframeworks in this package |
Mapp Engage Android 7.1.2 currently publishes Android dependencies newer than the Expo SDK 57 toolchain can consume. This release exports bounded compatibility constraints for AndroidX Core, WorkManager, Lifecycle, Play Services Location, and Kotlin stdlib — see Breaking Changes in 2.0.0 for the exact versions.
React Native CLI
Not using Expo? Install the plugin directly; autolinking discovers the Android package and CocoaPod automatically.
npm install react-native-mapp-plugin
cd ios && pod installDo not run react-native link, edit settings.gradle, or add the pod manually. See Get Started for the full setup.