Applications Manager Mobile App Monitor for React Native lets you measure the performance and stability of React Native applications on end-user devices. The React Native SDK captures screen, network, transaction, error, crash, and application-not-responding (ANR) data for analysis in Applications Manager.
This page explains how to install the react-native-memobileapminsight-rn package, configure the native Android and iOS projects, initialize monitoring, and instrument common application workflows.
Browse through the following topics to learn more about configuring Mobile App Monitor for React Native:
| Requirement | Version or requirement |
|---|---|
| react | 18.2.0 or later |
| react-native | 0.71.0 or later and earlier than 1.0.0 |
| iOS | Deployment target 15.0 or later |
| Android | Compile SDK API 21 or later, Java 1.8 or later, and AndroidX enabled with android.useAndroidX=true in gradle.properties. |
| apm_config.json | Download from a Mobile App Monitor created in Applications Manager and place it in the Android project. |
| apm_config.plist | Download from a Mobile App Monitor created in Applications Manager and add it to the iOS project. |
The package is hosted on a CDN registry. Install it with the --registry flag:
npm install react-native-memobileapminsight-rn --registry=https://static.zohocdn.com/memobileapminsight-reactnativesdk --legacy-peer-depsAutolinking links the native module automatically. No manual linking step is required.
Add the ManageEngine Maven repository to android/build.gradle:
buildscript {
repositories {
maven { url 'https://maven.zohodl.com' }
}
}
allprojects {
repositories {
maven { url 'https://maven.zohodl.com' }
}
}Sync Gradle from Android Studio, or run ./gradlew build once, to confirm that the package resolves.
Download apm_config.json from the Mobile App Monitor installation and place it at android/app/src/main/res/raw/apm_config.json. The file is prefilled with the appKey, collectorURL, uploadInterval, and payloadSize values.
Note: If the collector endpoint uses a self-signed certificate in a debug or evaluation environment, add the apm_cert.cer file (from the DEM Collector installation directory /conf/sslcerts) alongside apm_config.json in android/app/src/main/res/raw/. Self-signed certificates are not recommended for production.
Open the Podfile at <your-project>/ios/Podfile and add the following line inside your application target:
pod 'react-native-memobileapminsight-rn', :path => '../node_modules/react-native-memobileapminsight-rn'For example:
target 'YourAppName' do
# ... other pods
pod 'react-native-memobileapminsight-rn', :path => '../node_modules/react-native-memobileapminsight-rn'
endNavigate to the ios folder and run:
pod installAfter pod install completes, open the .xcworkspace file, not the .xcodeproj file.
Drag apm_config.plist into the root of the Xcode project. In the dialog that appears, set Action to Copy files to destination, select the required application target, and click Finish.
Note: If the collector endpoint uses a self-signed certificate in a debug or evaluation environment, add the apm_cert.cer file (from the DEM Collector installation directory /conf/sslcerts) to the Xcode project alongside apm_config.plist, using the same Copy files to destination option. Self-signed certificates are not recommended for production.
When using a self-signed certificate, you must allow an exception in Info.plist for the DEM collector domain. Open Info.plist and add the following configuration:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>[collectordomain].com</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>Replace [collectordomain].com with your DEM collector domain.
Import the module once in the application entry point, such as App.js or App.tsx, before making other SDK calls:
import { mobileapm } from 'react-native-memobileapminsight-rn';Start monitoring as early as possible in the application lifecycle. You can pass native screen names to exclude from automatic tracking:
mobileapm.startMonitoring(['SplashScreen']); // optional screens to ignoreCall startMonitoring exactly once. Other tracking calls are no-ops until monitoring starts.
To enable verbose SDK logs during integration, disable them in production builds:
mobileapm.setDebugLoggingEnabled(__DEV__);__DEV__ is React Native's built-in Boolean global. It is true in debug builds and false in release builds.
Pass an array of URL substrings to exclude from tracking, such as development-server or internal endpoints. Call this immediately after startMonitoring:
mobileapm.initializeNetworkMonitoring(['/symbolicate', '/ping']);Configure the JavaScript, native, console, and unhandled-rejection error sources you want to track:
mobileapm.initializeErrorMonitoring({
trackUnhandledErrors: true,
trackConsoleErrors: false,
trackUnhandledRejections: true,
trackNativeErrors: false
});Call this once after monitoring has started and before rendering the rest of the application.
Wrap risky code and report caught exceptions explicitly:
try {
riskyOperation();
} catch (err) {
mobileapm.captureException(err);
}Wrap a subtree so render and lifecycle errors are reported with a fallback user interface. The fallback value must be a function component:
const FallbackComponent = () => (
<View>
<Text>Something went wrong</Text>
</View>
);
<mobileapm.ErrorBoundary fallback={FallbackComponent}>
<YourScreenComponent />
</mobileapm.ErrorBoundary>Enable ANR reporting with the default threshold, or provide a custom threshold in seconds:
mobileapm.enableANRReporting();
// or with a custom threshold in seconds
mobileapm.enableANRReportingWithThreshold(5);
// disable later if needed
mobileapm.disableANRReporting();Use these methods only to verify crash and ANR reporting during integration. Do not expose them through production code paths:
mobileapm.crashApplication(); // throws a JS error
mobileapm.crashNative(); // triggers a native crash
mobileapm.triggerANRForTesting(6); // simulates an ANRScreen data supports session tracking, crash context, and performance analysis. Choose one of the following approaches and use it consistently:
Options A, B, and C capture frame rate, screen duration, and total, slow, and frozen frame counts without per-screen code.
This option is recommended for apps using @react-navigation/native or Expo Router. It attaches listeners to a navigation container reference without changing the NavigationContainer component:
import { NavigationContainer, useNavigationContainerRef } from '@react-navigation/native';
import { mobileapm } from 'react-native-memobileapminsight-rn';
import { useEffect } from 'react';
export default function App() {
const navigationRef = useNavigationContainerRef();
useEffect(() => {
// Returns unsubscribe - React cleans it up automatically.
return mobileapm.enableReactNavigation(navigationRef);
}, []);
return (
<NavigationContainer ref={navigationRef}>
{ /* your navigator */ }
</NavigationContainer>
);
}Every screen in every navigator, including nested stacks inside tabs and drawers, is tracked automatically.
This drop-in replacement for React Navigation's NavigationContainer tracks route changes automatically and forwards the container props:
import { MEAPMNavigationContainer } from 'react-native-memobileapminsight-rn';
export default function App() {
return (
<MEAPMNavigationContainer>
{ /* your navigator */ }
</MEAPMNavigationContainer>
);
}Every screen in every navigator is tracked automatically.
Use this option with Wix React Native Navigation. It subscribes to componentDidAppear and componentDidDisappear events and calls beginScreen and endScreen for each transition:
import { Navigation } from 'react-native-navigation';
import { mobileapm } from 'react-native-memobileapminsight-rn';
mobileapm.startMonitoring();
mobileapm.enableReactNativeNavigation(Navigation);
Navigation.registerComponent('Home', () => HomeScreen);
Navigation.registerComponent('Profile', () => ProfileScreen);
Navigation.events().registerAppLaunchedListener(() => {
Navigation.setRoot({ root: { bottomTabs: { children: [
{ component: { name: 'Home' } },
{ component: { name: 'Profile' } }
] } } });
});To exclude overlays or modals, pass their registered component names in ignoredComponents:
mobileapm.enableReactNativeNavigation(Navigation, {
ignoredComponents: ['LoadingOverlay', 'ToastNotification']
});Use this option for custom navigation or explicit per-screen control. With React Navigation, use useFocusEffect instead of useEffect so back navigation is tracked:
import { useFocusEffect } from '@react-navigation/native';
import { useCallback, useRef } from 'react';
function HomeScreen() {
const mountedAt = useRef(Date.now());
useFocusEffect(
useCallback(() => {
mobileapm.beginScreen('Home', Date.now() - mountedAt.current);
return () => {
mobileapm.endScreen('Home');
mountedAt.current = Date.now(); // reset for next focus
};
}, [])
);
return <View>...</View>;
}For custom or no navigation, use useEffect with an empty dependency array:
function HomeScreen() {
const mountedAt = useRef(Date.now());
useEffect(() => {
mobileapm.beginScreen('Home', Date.now() - mountedAt.current);
return () => mobileapm.endScreen('Home');
}, []);
return <View>...</View>;
}For class components, call beginScreen in componentDidMount and endScreen in componentWillUnmount. To exclude native screens such as a splash screen from automatic tracking, use:
mobileapm.excludeNativeScreens(['SplashScreen']);Set the user identifier and environment as soon as they are known, such as after login or at application startup:
mobileapm.setUserId('user@example.com'); // omit to use an auto-generated GUID
mobileapm.setEnvironment('production'); // e.g. production | staging | qaUse an opaque identifier instead of raw personally identifiable information when your application requires a user identifier.
Use transactions to time a logical unit of work and components to break it down further:
mobileapm.startTransaction('listing_blogs');
mobileapm.startComponent('listing_blogs', 'http_request');
await fetchBlogs();
mobileapm.stopComponent('listing_blogs', 'http_request');
mobileapm.startComponent('listing_blogs', 'view_data_onto_screen');
renderBlogs();
mobileapm.stopComponent('listing_blogs', 'view_data_onto_screen');
mobileapm.stopTransaction('listing_blogs');Follow these rules:
Add manual breadcrumbs to provide context leading up to an error:
mobileapm.addBreadCrumb('Info', 'download completed');Data uploads automatically according to uploadInterval. To force an immediate upload, for example before application termination, use:
mobileapm.flush();Use this method sparingly, such as in a user opt-out flow:
mobileapm.stopMonitoring();Call the SDK methods from the application entry point in the following order:
import { mobileapm } from 'react-native-memobileapminsight-rn';
mobileapm.setDebugLoggingEnabled(__DEV__);
mobileapm.startMonitoring();
mobileapm.initializeNetworkMonitoring(['/symbolicate']);
mobileapm.initializeErrorMonitoring({
trackUnhandledErrors: true,
trackUnhandledRejections: true
});
mobileapm.setEnvironment(__DEV__ ? 'staging' : 'production');The following tables summarize the React Native SDK methods and their parameters.
| Method | Parameter types | Description |
|---|---|---|
setDebugLoggingEnabled(enabled) | enabled: boolean | Toggle verbose SDK logging. |
startMonitoring(ignoredScreens?) | ignoredScreens?: string[] | Start monitoring using the native configuration. |
stopMonitoring() | - | Stop monitoring. |
initializeNetworkMonitoring(ignoredHttpCalls?) | ignoredHttpCalls?: string[] | Enable HTTP call tracking and optionally ignore URL substrings. |
initializeErrorMonitoring(config) | config: ErrorMonitoringConfig | Enable JavaScript and native error tracking. |
setUserId(userId) | userId: string | Associate telemetry with a user. |
setEnvironment(env) | env: string | Tag telemetry with an environment name. |
| Method | Parameter types | Description |
|---|---|---|
enableReactNavigation(navigationRef) | navigationRef: NavigationContainerRef | Auto-track every route change via a React Navigation container ref (Option A). |
MEAPMNavigationContainerimport { MEAPMNavigationContainer } from 'react-native-memobileapminsight-rn'; | Accepts and forwards every NavigationContainer prop, including ref | Drop-in replacement for NavigationContainer that auto-tracks every route change (Option B). |
enableReactNativeNavigation(Navigation, options?) | Navigation: Navigation, options?: { ignoredComponents?: string[] } | Auto-track Wix React Native Navigation screen transitions (Option C). |
beginScreen(screenName, loadTime) | screenName: string, loadTime: number | Start tracking a screen. Must be paired with endScreen (Option D). |
endScreen(screenName) | screenName: string | End tracking and send the screen's metrics. The name must match the beginScreen call (Option D). |
addScreen(screenName, loadTime) | screenName: string, loadTime: number | Report a screen view and load time. |
excludeNativeScreens(screenNames) | screenNames: string[] | Exclude native screens from tracking. |
ErrorBoundary | fallback: React.ComponentType | Wrap a React subtree with a fallback component for render errors. |
captureException(err) | err: Error | Manually report a caught exception. |
addBreadCrumb(event, message) | event: string, message: string | Add a manual breadcrumb. |
enableANRReporting() / enableANRReportingWithThreshold(seconds) / disableANRReporting() | seconds: number for threshold | Control ANR reporting. |
| Method | Parameter types | Description |
|---|---|---|
startTransaction(txnName) / stopTransaction(txnName) | txnName: string | Track a custom transaction. |
startComponent(txnName, componentName) / stopComponent(txnName, componentName) | txnName: string, componentName: string | Group work within a transaction. |
flush() | - | Force an immediate upload. |
crashApplication() / crashNative() / triggerANRForTesting(seconds) | seconds: number for ANR testing | Trigger test crashes or an ANR during integration testing only. |
It allows us to track crucial metrics such as response times, resource utilization, error rates, and transaction performance. The real-time monitoring alerts promptly notify us of any issues or anomalies, enabling us to take immediate action.
Reviewer Role: Research and Development