# Mobile App Monitoring for React Native 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. ## Prerequisites | 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. | ## Install the package The package is hosted on a CDN registry. Install it with the ***--registry*** flag: ```bash npm install react-native-memobileapminsight-rn --registry=https://static.zohocdn.com/memobileapminsight-reactnativesdk --legacy-peer-deps ``` Autolinking links the native module automatically. No manual linking step is required. ## Platform setup ### Android Add the ManageEngine Maven repository to ***android/build.gradle***: ```groovy 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. ### iOS Open the Podfile at ***/ios/Podfile*** and add the following line inside your application target: ```ruby pod 'react-native-memobileapminsight-rn', :path => '../node_modules/react-native-memobileapminsight-rn' ``` For example: ```ruby target 'YourAppName' do # ... other pods pod 'react-native-memobileapminsight-rn', :path => '../node_modules/react-native-memobileapminsight-rn' end ``` Navigate to the ***ios*** folder and run: ```bash pod install ``` After ***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: ```xml NSAppTransportSecurity NSExceptionDomains [collectordomain].com NSExceptionAllowsInsecureHTTPLoads ``` Replace ***[collectordomain].com*** with your DEM collector domain. ## Initialize monitoring Import the module once in the application entry point, such as ***App.js*** or ***App.tsx***, before making other SDK calls: ```javascript 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: ```javascript mobileapm.startMonitoring(['SplashScreen']); // optional screens to ignore ``` Call ***startMonitoring*** exactly once. Other tracking calls are no-ops until monitoring starts. To enable verbose SDK logs during integration, disable them in production builds: ```javascript mobileapm.setDebugLoggingEnabled(__DEV__); ``` ***__DEV__*** is React Native's built-in Boolean global. It is ***true*** in debug builds and ***false*** in release builds. ## Enable network monitoring Pass an array of URL substrings to exclude from tracking, such as development-server or internal endpoints. Call this immediately after ***startMonitoring***: ```javascript mobileapm.initializeNetworkMonitoring(['/symbolicate', '/ping']); ``` ## Enable error and crash monitoring Configure the JavaScript, native, console, and unhandled-rejection error sources you want to track: ```javascript 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. ### Manual exception capture Wrap risky code and report caught exceptions explicitly: ```javascript try { riskyOperation(); } catch (err) { mobileapm.captureException(err); } ``` ### Error boundary for render errors Wrap a subtree so render and lifecycle errors are reported with a fallback user interface. The ***fallback*** value must be a function component: ```jsx const FallbackComponent = () => ( Something went wrong ); ``` ### ANR reporting Enable ANR reporting with the default threshold, or provide a custom threshold in seconds: ```javascript mobileapm.enableANRReporting(); // or with a custom threshold in seconds mobileapm.enableANRReportingWithThreshold(5); // disable later if needed mobileapm.disableANRReporting(); ``` ### Test crashes Use these methods only to verify crash and ANR reporting during integration. Do not expose them through production code paths: ```javascript mobileapm.crashApplication(); // throws a JS error mobileapm.crashNative(); // triggers a native crash mobileapm.triggerANRForTesting(6); // simulates an ANR ``` ## Screen tracking Screen data supports session tracking, crash context, and performance analysis. Choose one of the following approaches and use it consistently: - Option A: Use ***enableReactNavigation(ref)*** with React Navigation or Expo Router. - Option B: Replace ***NavigationContainer*** with ***MEAPMNavigationContainer***. - Option C: Use ***enableReactNativeNavigation(Navigation)*** with Wix React Native Navigation. - Option D: Use ***beginScreen*** and ***endScreen*** for custom navigation or explicit per-screen control. Options A, B, and C capture frame rate, screen duration, and total, slow, and frozen frame counts without per-screen code. ### Option A - Automatic: enableReactNavigation(ref) 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: ```jsx 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 ( { /* your navigator */ } ); } ``` Every screen in every navigator, including nested stacks inside tabs and drawers, is tracked automatically. ### Option B - Automatic: MEAPMNavigationContainer This drop-in replacement for React Navigation's ***NavigationContainer*** tracks route changes automatically and forwards the container props: ```jsx import { MEAPMNavigationContainer } from 'react-native-memobileapminsight-rn'; export default function App() { return ( { /* your navigator */ } ); } ``` Every screen in every navigator is tracked automatically. ### Option C - Automatic: enableReactNativeNavigation(Navigation) Use this option with Wix React Native Navigation. It subscribes to ***componentDidAppear*** and ***componentDidDisappear*** events and calls ***beginScreen*** and ***endScreen*** for each transition: ```javascript 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***: ```javascript mobileapm.enableReactNativeNavigation(Navigation, { ignoredComponents: ['LoadingOverlay', 'ToastNotification'] }); ``` ### Option D - Manual: beginScreen and endScreen Use this option for custom navigation or explicit per-screen control. With React Navigation, use ***useFocusEffect*** instead of ***useEffect*** so back navigation is tracked: ```jsx 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 ...; } ``` For custom or no navigation, use ***useEffect*** with an empty dependency array: ```jsx function HomeScreen() { const mountedAt = useRef(Date.now()); useEffect(() => { mobileapm.beginScreen('Home', Date.now() - mountedAt.current); return () => mobileapm.endScreen('Home'); }, []); return ...; } ``` For class components, call ***beginScreen*** in ***componentDidMount*** and ***endScreen*** in ***componentWillUnmount***. To exclude native screens such as a splash screen from automatic tracking, use: ```javascript mobileapm.excludeNativeScreens(['SplashScreen']); ``` ## User and environment tagging Set the user identifier and environment as soon as they are known, such as after login or at application startup: ```javascript mobileapm.setUserId('user@example.com'); // omit to use an auto-generated GUID mobileapm.setEnvironment('production'); // e.g. production | staging | qa ``` Use an opaque identifier instead of raw personally identifiable information when your application requires a user identifier. ## Custom transactions and components Use transactions to time a logical unit of work and components to break it down further: ```javascript 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: - ***txnName*** and ***componentName*** must be non-empty strings. - Every ***startTransaction*** call must have a matching ***stopTransaction*** call. - Start and stop components within the same transaction name. ## Breadcrumbs Add manual breadcrumbs to provide context leading up to an error: ```javascript mobileapm.addBreadCrumb('Info', 'download completed'); ``` ## Flushing data Data uploads automatically according to ***uploadInterval***. To force an immediate upload, for example before application termination, use: ```javascript mobileapm.flush(); ``` ## Stop monitoring Use this method sparingly, such as in a user opt-out flow: ```javascript mobileapm.stopMonitoring(); ``` ## Recommended integration order Call the SDK methods from the application entry point in the following order: 1. Import ***mobileapm*** and enable debug logging only for development builds. 2. Start monitoring with the configuration downloaded from Applications Manager. 3. Initialize network monitoring with the URL substrings to ignore. 4. Initialize error monitoring with the required error flags. 5. Set the user identifier and environment when they become available. 6. Wrap the root component with ***mobileapm.ErrorBoundary*** when render-error reporting is required. 7. Configure screen tracking for the navigation library used by the application. ```javascript 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'); ``` ## Verification checklist - Confirm that the application builds and runs on Android and iOS after the Maven and Podfile changes. - Confirm that ***setDebugLoggingEnabled(true)*** shows SDK logs during a debug session. Remove or guard this setting for release builds. - Navigate between screens and confirm that screen-tracking calls appear in the logs or dashboard. - Make a test network call and confirm that it appears in the network monitoring dashboard. - Use ***crashApplication()*** temporarily from a development-only control to produce a crash report. - Call ***mobileapm.flush()*** and confirm that buffered data appears on the dashboard. ## Full API reference The following tables summarize the React Native SDK methods and their parameters. ### Monitoring and configuration | 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. | ### Screen and error handling | Method | Parameter types | Description | |---|---|---| | `enableReactNavigation(navigationRef)` | `navigationRef: NavigationContainerRef` | Auto-track every route change via a React Navigation container ref (Option A). | | `MEAPMNavigationContainer`
`import { 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. | ### Transactions and data controls | 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. | ## Troubleshooting - **Tracking calls such as *addScreen*, *startTransaction*, or *setUserId* have no effect:** These APIs may have been called before ***startMonitoring*** or before the initialization calls completed. Start monitoring first and initialize the remaining modules afterward. - ***ErrorBoundary*** **does not display the fallback user interface:** Ensure that the ***fallback*** property is a function component. Do not pass a class component or a hook-based component directly as the fallback. - **The native build fails or the native module is unavailable at runtime:** Verify that the Maven repository entry for Android or the Podfile entry for iOS is present, then repeat the platform setup steps. - **Users unexpectedly experience crashes or ANRs in production:** Remove test methods such as ***crashApplication()***, ***crashNative()***, and ***triggerANRForTesting()*** from production code paths. Disable debug logging in release builds.