For AI agents: a documentation index is available at /docs/llms.txt. Append .md to any page URL for markdown, or send Accept: text/markdown.
React Native SDK
The React Native SDK lets you send events to Amplitude.
React Native support
React-Native doesn't provide stable release versioning, which makes backward compatibility challenging. React-Native itself isn't backward compatible and can introduce breaking changes across versions. Check the React-Native compatibility list for more details. Amplitude supports only the latest version of React-Native.
Compatibility matrix
The following matrix lists Amplitude React Native SDK support for different versions of React Native and React Native CLI.
| @amplitude/analytics-react-native | react-native | Gradle | Android Gradle Plugin |
|---|---|---|---|
| >= 1.4.0 | >= 0.68 | 7.5.1+ | 7.2.1+ |
| >= 1.0.0, <= 1.3.6 | >= 0.61, <= 0.70 | 3.5.3+ | 3.5.3+ |
Learn more about the Android Gradle Plugin compatibility.
Install the SDK
To start using the Amplitude React Native SDK, install the package to your project with npm. The SDK uses @react-native-async-storage/async-storage by default to persist identity and the event queue across app launches, so install it alongside the SDK. If you'd rather use your own storage backend, refer to Opt out of AsyncStorage.
Web and Expo support
You can use this SDK for react-native apps built for web or built using Expo (Expo Go not yet supported).
npm install @amplitude/analytics-react-native
npm install @react-native-async-storage/async-storage
Install the native modules to run the SDK on iOS.
cd ios
pod install
Initialize the SDK
Initialize the SDK before any instrumentation. The API key for your Amplitude project is required. You can optionally pass a user ID and config object in this call. After you initialize the SDK, you can use it anywhere in your application.
import { init } from "@amplitude/analytics-react-native";
// Option 1, initialize with API_KEY only
init(API_KEY);
// Option 2, initialize including user ID if it's already known
init(API_KEY, "user@amplitude.com");
// Option 3, initialize including configuration
init(API_KEY, "user@amplitude.com", {
disableCookies: true, // Disables the use of browser cookies
});
Configure the SDK
Web vs. mobile
The SDK shares configuration across web and mobile platforms. Many of these options don't apply when you run the SDK on native platforms like iOS or Android. For example, on web, the SDK stores identity in the browser cookie by default. On native platforms, the SDK stores identity in async storage.
Configure batching behavior
To support high-performance environments, the SDK sends events in batches. The track method queues every event in memory. The SDK flushes events in batches in the background. You can customize batch behavior with flushQueueSize and flushIntervalMillis. By default, the serverUrl is https://api2.amplitude.com/2/httpapi. To send large batches of data at a time, set useBatch to true to set setServerUrl to the batch event upload API https://api2.amplitude.com/batch. Both the regular mode and the batch mode use the same events upload threshold and flush time intervals.
import * as amplitude from "@amplitude/analytics-react-native";
amplitude.init(API_KEY, OPTIONAL_USER_ID, {
// Events queued in memory will flush when number of events exceed upload threshold
// Default value is 30
flushQueueSize: 50,
// Events queue will flush every certain milliseconds based on setting
// Default value is 10000 milliseconds
flushIntervalMillis: 20000,
});
Offline mode
Beginning with version 1.6.0, the React Native SDK supports offline mode. The SDK detects when the device loses network connectivity and queues events instead of dropping them. While the device is offline, the SDK persists tracked events to storage and stops attempting uploads. When the device reconnects, the SDK flushes the queued events to Amplitude. Offline mode is on by default, so you don't need to configure it.
The SDK detects connectivity through a native module: NWPathMonitor on iOS and ConnectivityManager on Android. On web (react-native-web), the SDK uses the browser's navigator.onLine state and online and offline events.
The SDK persists events to storage while the device is offline, so the configured storageProvider bounds the size of the offline queue. Refer to Opt out of AsyncStorage to change where the SDK stores queued events.
Native module setup
Connectivity detection relies on the SDK's native modules:
- iOS: The native module links automatically when you run
pod install. Refer to Install the SDK. The minimum supported iOS deployment target is 13.0. - Android: The SDK declares the
ACCESS_NETWORK_STATEpermission in its manifest, which merges into your app's manifest automatically. You don't need to make any manual changes.
Disable offline mode
To turn off automatic connectivity detection, set offline to OfflineDisabled when you initialize the SDK.
import * as amplitude from "@amplitude/analytics-react-native";
amplitude.init(API_KEY, OPTIONAL_USER_ID, {
offline: amplitude.Types.OfflineDisabled,
});
When you disable offline mode, the SDK flushes events based on flushIntervalMillis and flushQueueSize only. To implement your own offline logic, disable offline mode as shown, then toggle config.offline based on your own network detection.
EU data residency
You can configure the server zone when you initialize the client to send data to Amplitude's EU servers. The SDK sends data based on the server zone if you set it.
For EU data residency, set up the project inside Amplitude EU. You must initialize the SDK with the API key from Amplitude EU.
amplitude.init(API_KEY, OPTIONAL_USER_ID, {
serverZone: "EU",
});
Debugging
You can control the level of logs printed to the developer console.
- 'None': Suppresses all log messages.
- 'Error': Shows error messages only.
- 'Warn': Shows error messages and warnings. This is the default value if you don't explicitly specify
logLevel. - 'Verbose': Shows informative messages.
- 'Debug': Shows error messages, warnings, and informative messages that may help with debugging, including the function context information for all SDK public method invocations. Use this logging mode only in development phases.
Set the log level by configuring the logLevel with the level you want.
amplitude.init(AMPLITUDE_API_KEY, OPTIONAL_USER_ID, {
logLevel: amplitude.Types.LogLevel.Warn,
});
The default logger outputs logs to the developer console. You can provide your own logger implementation based on the Logger interface for customization. For example, you can collect error messages from the SDK in a production environment.
Set the logger by configuring the loggerProvider with your own implementation.
amplitude.init(AMPLITUDE_API_KEY, OPTIONAL_USER_ID, {
loggerProvider: new MyLogger(),
});
Debug mode
Enable the debug mode by setting the logLevel to "Debug", for example:
amplitude.init(AMPLITUDE_API_KEY, OPTIONAL_USER_ID, {
logLevel: amplitude.Types.LogLevel.Debug,
});
The default logger outputs extra function context information to the developer console when you invoke any SDK public method, including:
- 'type': Category of this context, for example "invoke public method".
- 'name': Name of the invoked function, for example "track".
- 'args': Arguments of the invoked function.
- 'stacktrace': Stacktrace of the invoked function.
- 'time': Start and end timestamp of the function invocation.
- 'states': Useful internal states snapshot before and after the function invocation.
Autocapture
Available in @amplitude/analytics-react-native 1.6.8 and later. Autocapture lets you track sessions, application lifecycle events, screen views, element interactions, frustration interactions, and network requests with minimal instrumentation.
The React Native SDK autocaptures the following event types when you enable them:
- Sessions (
session_startandsession_end) - Application lifecycles (
[Amplitude] Application Openedand[Amplitude] Application Backgrounded) - Screen views (
[Amplitude] Screen Viewed), when you call the screen view helpers - Element interactions (
[Amplitude] Element Pressed), when you enable element interactions and wrap handlers (manually or with the Babel plugin) - Frustration interactions (
[Amplitude] Rage Clickand[Amplitude] Error Click), when you enable frustration interactions and wrap handlers (manually or with the Babel plugin) - Network requests (
[Amplitude] Network Request), when you enable network tracking
Enable Autocapture
Pass autocapture: true to enable sessions, app lifecycles, screen views, element interactions, frustration interactions, and network tracking together, or pass an options object to choose features.
import { init } from "@amplitude/analytics-react-native";
// Enable every Autocapture feature
init(API_KEY, OPTIONAL_USER_ID, {
autocapture: true,
});
// Or enable features individually
init(API_KEY, OPTIONAL_USER_ID, {
autocapture: {
sessions: true,
appLifecycles: true,
networkTracking: true,
},
});
To turn Autocapture off, omit autocapture or set it to false.
init(API_KEY, OPTIONAL_USER_ID, {
autocapture: false,
});
Track sessions
Set autocapture.sessions to true (or pass autocapture: true) to track session_start and session_end when the session ID changes. This matches trackingSessionEvents: true. Prefer the Autocapture option for new instrumentation.
init(API_KEY, OPTIONAL_USER_ID, {
autocapture: {
sessions: true,
},
});
trackingSessionEvents still works. Use autocapture.sessions when you adopt Autocapture.
Track application lifecycles
Set autocapture.appLifecycles to true to track application foreground and background events from React Native AppState.
init(API_KEY, OPTIONAL_USER_ID, {
autocapture: {
appLifecycles: true,
},
});
When you enable this setting, Amplitude tracks:
[Amplitude] Application Opened: fires on cold start when the app is already active at init, and again when the app returns to the foreground after a real background.[Amplitude] Application Backgrounded: fires whenAppStatechanges tobackground.
The SDK doesn't treat inactive → active (for example, Control Center) as a new open. It emits [Amplitude] Application Opened only after a prior background.
Track screen views
Screen view Autocapture isn't fully automatic. Call trackScreenView or trackScreenViewOnNavigationStateChange to send [Amplitude] Screen Viewed with [Amplitude] Screen Name. Set autocapture.screenViews to false only when you want to disable those helpers.
import {
init,
trackScreenView,
trackScreenViewOnNavigationStateChange,
} from "@amplitude/analytics-react-native";
import {
NavigationContainer,
useNavigationContainerRef,
} from "@react-navigation/native";
init(API_KEY, OPTIONAL_USER_ID, {
autocapture: {
sessions: true,
appLifecycles: true,
},
});
// Manual screen view
trackScreenView("Home");
// React Navigation: onStateChange doesn't fire for the initial route;
// call the helper from onReady for the cold-start screen.
function App() {
const navigationRef = useNavigationContainerRef();
return (
<NavigationContainer
ref={navigationRef}
onReady={() => {
trackScreenViewOnNavigationStateChange(navigationRef.getRootState());
}}
onStateChange={trackScreenViewOnNavigationStateChange}
>
{/* navigators */}
</NavigationContainer>
);
}
trackScreenViewOnNavigationStateChange resolves the focused leaf route in nested navigators and skips duplicate callbacks for the same screen name (for example, onReady plus onStateChange, or param-only updates). Re-init and reset clear the dedupe state.
Track element interactions
Set autocapture.elementInteractions to true so Amplitude tracks UI interactions on handlers wrapped with ampCapture. When a wrapped handler runs, the SDK sends [Amplitude] Element Pressed with properties such as [Amplitude] Target Test ID, [Amplitude] Target Accessibility Label, [Amplitude] Target Component, [Amplitude] Target Element, and [Amplitude] Action.
import { init } from "@amplitude/analytics-react-native";
init(API_KEY, OPTIONAL_USER_ID, {
autocapture: {
elementInteractions: true,
},
});
You can wrap handlers in source with ampCapture, or use the Babel plugin so Metro/Babel wraps them at compile time.
import { ampCapture } from "@amplitude/analytics-react-native";
<Button
testID="1234"
accessibilityLabel="Sign up"
onPress={ampCapture(
() => {
/* your handler */
},
{
testID: "1234",
accessibilityLabel: "Sign up",
action: "press",
},
)}
/>
Transpile source with the Babel plugin
Install @amplitude/babel-plugin-autocapture-transformer as a dev dependency. The plugin expects @amplitude/analytics-react-native in your app; it imports ampCapture automatically.
npm install --save-dev @amplitude/babel-plugin-autocapture-transformer
Add the plugin to your Babel config. For Expo or React Native, use babel.config.js:
module.exports = function (api) {
api.cache(true);
return {
presets: ["babel-preset-expo"], // or your existing presets
plugins: ["@amplitude/babel-plugin-autocapture-transformer"],
};
};
Or in .babelrc / babel.config.json:
{
"plugins": ["@amplitude/babel-plugin-autocapture-transformer"]
}
At compile time, the plugin rewrites known interactive JSX handlers. For example:
// Before transpile
<Button
accessibilityLabel="Online test label"
testID="12345"
title="Online test"
onPress={func}
/>
// After transpile
import { ampCapture } from "@amplitude/analytics-react-native";
<Button
accessibilityLabel="Online test label"
testID="12345"
title="Online test"
onPress={ampCapture(func, {
event: "Press",
accessibilityLabel: "Online test label",
testID: "12345",
element: "Button",
component: "HomeScreen",
})}
/>
When a file already imports from @amplitude/analytics-react-native, the plugin adds ampCapture to that import instead of inserting a second one.
The plugin only rewrites known interactive JSX elements that already have an expression handler (for example onPress={handler}). It leaves string handlers and elements without handlers unchanged.
| Category | Default elements | Attributes → event |
|---|---|---|
| Pressable | Button, TouchableOpacity, TouchableHighlight, TouchableWithoutFeedback, Pressable, Touchable, TouchableNativeFeedback, Link | onPress → Press, onLongPress → LongPress |
| Value change | Switch, Slider, Picker | onValueChange → ValueChange |
| Text change | TextInput | onChangeText → ChangeText, onSubmitEditing → SubmitEditing |
If the element has accessibilityLabel or testID, the plugin copies those values into the ampCapture properties object. It also adds:
element: the JSX tag name (for exampleButton).component: the enclosing React component or function name when the plugin can resolve it (for exampleHomeScreen).
To include custom components, pass extra element names in the plugin options:
module.exports = function (api) {
api.cache(true);
return {
presets: ["babel-preset-expo"],
plugins: [
[
"@amplitude/babel-plugin-autocapture-transformer",
{
pressableElements: ["CustomButton"],
valueChangeElements: ["Toggle"],
textChangeElements: ["SearchField"],
},
],
],
};
};
The plugin transforms only plain JSX identifiers such as <Button />. It ignores member expressions like <RN.Button /> unless you list the local identifier in the matching options array. The plugin doesn't inspect spread attributes (for example {...props}) for accessibilityLabel or testID. It omits component when the enclosing function is anonymous.
After you change Babel config, restart Metro so the new plugin loads.
Track frustration interactions
Available in @amplitude/analytics-react-native 1.11.0 and later. Error clicks require 1.12.0 or later.
Set autocapture.frustrationInteractions to true so Amplitude tracks rage clicks and error clicks on handlers wrapped with ampCapture. Use the Babel plugin to wrap handlers at compile time, or wrap them in source. These events use the same wrappers as element interactions.
import { init } from "@amplitude/analytics-react-native";
init(API_KEY, OPTIONAL_USER_ID, {
autocapture: {
frustrationInteractions: true,
},
});
Pass an options object to turn rage clicks or error clicks off individually. Both stay on when you enable frustration interactions and omit the field.
init(API_KEY, OPTIONAL_USER_ID, {
autocapture: {
frustrationInteractions: {
rageClick: true,
errorClick: false,
},
},
});
A rage click is four or more presses within 1 second that stay inside a 50-pixel region. Amplitude tracks [Amplitude] Rage Click for the burst and includes the element properties from the first press.
An error click is a press or long press followed by an unhandled React Native error within 2 seconds. Amplitude tracks [Amplitude] Error Click and includes the same element properties as a rage click.
Track network requests
Track when JavaScript fetch or XHR network requests fail. By default, Amplitude tracks network requests with a response code in the range 500-599, excluding requests made to any amplitude.com domain. Network tracking observes the JavaScript fetch and XHR layer. It doesn't capture HTTP traffic that native modules issue outside JavaScript.
Set config.autocapture.networkTracking to true to enable network request tracking.
init(API_KEY, OPTIONAL_USER_ID, {
autocapture: {
networkTracking: true,
},
});
When you enable this setting, Amplitude tracks the [Amplitude] Network Request event whenever the application makes a matching network request.
Advanced configuration for network tracking
Set config.autocapture.networkTracking to a NetworkTrackingOptions object to configure which network requests Amplitude tracks.
init(API_KEY, OPTIONAL_USER_ID, {
autocapture: {
networkTracking: {
captureRules: [
{
statusCodeRange: "400-599",
},
],
ignoreHosts: ["*.example.com"],
ignoreAmplitudeRequests: true,
},
},
});
This example tracks network requests with status codes from 400-599, ignores requests to *.example.com domains, and excludes Amplitude's own requests.
Safe headers
When you set requestHeaders: true or responseHeaders: true, Amplitude captures only safe headers and excludes sensitive ones that may contain authentication credentials or personally identifiable information.
Network body capture
If a network request or response body is in JSON, you can capture part of the response body by configuring responseBody.allowlist and responseBody.blocklist. You can capture part of the request body by configuring requestBody.allowlist and requestBody.blocklist.
The allowlist and blocklist are lists of JSON Pointer-like strings that capture specific fields. For example: ['foo/bar', 'hello/**']. allowlist tells the client which fields to capture. blocklist tells the client to exclude fields from capture. By default, the SDK captures nothing from the body.
Example request/response body
{
"a": "A",
"b": {
"c": "C",
"d": {
"e": "E",
"f": "F"
}
},
"g": "G"
}
| allowlist | Captured Result |
|---|---|
a | { "a": "A" } |
a/b/* | { "a": { "b": { "c": "C" } } } |
b/c | { "b": { "c": "C" } } |
b/** | { "b": { "c": "C", "d": { "e": "E", "f": "F" } } } |
b/d/* | { "b": { "d": { "e": "E", "f": "F" } } } |
* | { "a": "A", "g": "G" } |
Track events
This SDK uses the HTTP V2 API and follows the same constraints for events. Make sure that all events you log with the SDK have the event_type field and at least one of deviceId (included by default) or userId, and follow the HTTP API's constraints on each of those fields.
To prevent instrumentation issues, device IDs and user IDs must be strings with a length of 5 characters or more. If an event contains a device ID or user ID that's too short, the SDK removes the ID value from the event. If the event doesn't have a userId or deviceId value, Amplitude may reject the upload with a 400 status. Override the default minimum length of 5 characters by setting the minIdLength config option.
Events represent how users interact with your application. For example, "Button Clicked" may be an action you want to note.
import { track } from "@amplitude/analytics-react-native";
// Track a basic event
track("Button Clicked");
// Track events with optional properties
const eventProperties = {
buttonColor: "primary",
};
track("Button Clicked", eventProperties);
Track events to multiple projects
To log events to multiple Amplitude projects, create separate instances for each Amplitude project. Then, pass the instance variables to wherever you want to call Amplitude. Each instance allows for independent apiKeys, userIds, deviceIds, and settings.
import * as amplitude from "@amplitude/analytics-react-native";
const defaultInstance = amplitude.createInstance();
defaultInstance.init(API_KEY_DEFAULT);
const envInstance = amplitude.createInstance();
envInstance.init(API_KEY_ENV, {
instanceName: "env",
});
User properties
User properties help you understand your users at the time they performed some action within your app, such as their device details, their preferences, or language.
Use Identify to set the user properties of a particular user without sending any event. The SDK supports the operations set, setOnce, unset, add, append, prepend, preInsert, postInsert, remove, and clearAll on individual user properties. You declare the operations through a provided Identify interface. You can chain multiple operations together in a single Identify object. You then pass the Identify object to the Amplitude client to send to the server.
If you send the Identify call after the event, the results of operations appear immediately in the dashboard user's profile area, but they don't appear in the chart result until you send another event after the Identify call. The identify call only affects events going forward. More details in User properties and events.
Identify
The Identify object provides controls over setting user properties. First, instantiate an Identify object. Then, call Identify methods on it. Finally, the client makes a call with the Identify object.
import { identify, Identify } from "@amplitude/analytics-react-native";
const identifyObj = new Identify();
identify(identifyObj);
Identify.set
This method sets the value of a user property. For example, you can set a role property of a user.
import { Identify, identify } from "@amplitude/analytics-react-native";
const identifyObj = new Identify();
identifyObj.set("location", "LAX");
identify(identifyObj);
Identify.setOnce
This method sets the value of a user property only once. The SDK ignores subsequent calls using setOnce(). For example, you can set an initial login method for a user. Because the SDK only tracks the initial value, setOnce() ignores subsequent calls.
import { Identify, identify } from "@amplitude/analytics-react-native";
const identifyObj = new Identify();
identifyObj.setOnce("initial-location", "SFO");
identify(identifyObj);
Identify.add
This method increments a user property by some numerical value. If the user property doesn't have a value set yet, the SDK initializes it to 0 before incrementing. For example, you can track a user's travel count.
import { Identify, identify } from "@amplitude/analytics-react-native";
const identifyObj = new Identify();
identifyObj.add("travel-count", 1);
identify(identifyObj);
Arrays in user properties
You can use arrays as user properties. You can directly set arrays or use prepend, append, preInsert, and postInsert to generate an array.
Identify.prepend
This method prepends a value or values to a user property array. If the user property doesn't have a value set yet, the SDK initializes it to an empty list before prepending the new values.
import { Identify, identify } from "@amplitude/analytics-react-native";
const identifyObj = new Identify();
identifyObj.prepend("visited-locations", "LAX");
identify(identifyObj);
Identify.append
This method appends a value or values to a user property array. If the user property doesn't have a value set yet, the SDK initializes it to an empty list before appending the new values.
import { Identify, identify } from "@amplitude/analytics-react-native";
const identifyObj = new Identify();
identifyObj.append("visited-locations", "SFO");
identify(identifyObj);
Identify.preInsert
This method pre-inserts a value or values to a user property if the value doesn't exist in the user property yet. Pre-insert means inserting the value at the beginning of a given list. If the user property doesn't have a value set yet, the SDK initializes it to an empty list before pre-inserting the new values. If the user property has an existing value, the SDK performs no operation.
import { Identify, identify } from "@amplitude/analytics-react-native";
const identifyObj = new Identify();
identifyObj.preInsert("unique-locations", "LAX");
identify(identifyObj);
Identify.postInsert
This method post-inserts a value or values to a user property if the value doesn't exist in the user property yet. Post-insert means inserting the value at the end of a given list. If the user property doesn't have a value set yet, the SDK initializes it to an empty list before post-inserting the new values. If the user property has an existing value, the SDK performs no operation.
import { Identify, identify } from "@amplitude/analytics-react-native";
const identifyObj = new Identify();
identifyObj.postInsert("unique-locations", "SFO");
identify(identifyObj);
Identify.remove
This method removes a value or values from a user property if the value exists in the user property. Remove means remove the existing values from the given list. If the item doesn't exist in the user property, the SDK performs no operation.
import { Identify, identify } from "@amplitude/analytics-react-native";
const identifyObj = new Identify();
identifyObj.remove("unique-locations", "JFK");
identify(identifyObj);
Identify.clearAll
This method removes all user properties from a user. Use clearAll with care because the operation is irreversible.
import { Identify, identify } from "@amplitude/analytics-react-native";
const identifyObj = new Identify();
identifyObj.clearAll();
identify(identifyObj);
User groups
Amplitude supports assigning users to groups and performing queries, such as Count by Distinct, on those groups. If at least one member of the group has performed the specific event, then the count includes the group.
For example, you want to group your users based on what organization they're in by using an 'orgId'. Joe is in 'orgId' '10', and Sue is in 'orgId' '15'. Sue and Joe both perform a certain event. You can query their organizations in the Event Segmentation Chart.
When you set groups, define a groupType and groupName. In the previous example, 'orgId' is the groupType, and '10' and '15' are the values for groupName. Another example of a groupType could be 'sport' with groupName values like 'tennis' and 'baseball'.
Setting a group also sets the groupType:groupName as a user property, and overwrites any existing groupName value set for that user's groupType, and the corresponding user property value. groupType is a string, and groupName can be either a string or an array of strings to indicate that a user is in multiple groups.
If Joe is in 'orgId' '15', then the groupName would be '15'.
import { setGroup } from "@amplitude/analytics-react-native";
// set group with single group name
setGroup("orgId", "15");
If Joe is in 'sport' 'tennis' and 'soccer', then the groupName would be '["tennis", "soccer"]'.
import { setGroup } from "@amplitude/analytics-react-native";
// set group with multiple group names
setGroup("sport", ["soccer", "tennis"]);
You can also set event-level groups by passing an Event Object with groups to track. With event-level groups, the group designation applies only to the specific event you log, and doesn't persist on the user unless you explicitly set it with setGroup.
import { track } from "@amplitude/analytics-react-native";
track({
event_type: "event type",
event_properties: { eventPropertyKey: "event property value" },
groups: { orgId: "15" },
});
Group properties
Use the Group Identify API to set or update the properties of particular groups. These updates only affect events going forward.
The groupIdentify() method accepts a group type and group name string parameter, as well as an Identify object that the SDK applies to the group.
import { Identify, groupIdentify } from "@amplitude/analytics-react-native";
const groupType = "plan";
const groupName = "enterprise";
const event = new Identify();
event.set("key1", "value1");
groupIdentify(groupType, groupName, identify);
Track revenue
The preferred method of tracking revenue for a user is to use revenue() in conjunction with the provided Revenue interface. Revenue instances store each revenue transaction and let you define several special revenue properties (such as "revenueType", "productIdentifier", and so forth) that Amplitude uses in Event Segmentation and Revenue LTV charts. The SDK then passes these Revenue instance objects into revenue() to send as revenue events to Amplitude. This lets Amplitude automatically display data relevant to revenue in the platform. You can use this to track both in-app and non-in-app purchases.
To track revenue from a user, call revenue each time a user generates revenue. For example, a user purchases 3 units of a product at $3.99.
import { Revenue, revenue } from "@amplitude/analytics-react-native";
const event = new Revenue()
.setProductId("com.company.productId")
.setPrice(3.99)
.setQuantity(3);
revenue(event);
Revenue interface
| Name | Description |
|---|---|
product_id | Optional. String. An identifier for the product. Amplitude recommends something like the Google Play Store product ID. Defaults to null. |
quantity | Required. Int. The quantity of products purchased. revenue = quantity * price. Defaults to 1 |
price | Required. Double. The price of the products purchased, and this can be negative. revenue = quantity * price. Defaults to null. |
revenue_type | Optional, but required for revenue verification. String. The revenue type (for example tax, refund, income). Defaults to null. |
receipt | Optional. String. The receipt identifier of the revenue. Defaults to null |
receipt_sig | Optional, but required for revenue verification. String. The receipt signature of the revenue. Defaults to null. |
properties | Optional. JSONObject. An object of event properties to include in the revenue event. Defaults to null. |
Flush the event buffer
The flush method triggers the client to send buffered events.
import { flush } from "@amplitude/analytics-react-native";
flush();
By default, the SDK calls flush automatically in an interval. To flush the events altogether, you can control the async flow with the optional Promise interface, for example:
await init(AMPLITUDE_API_KEY).promise;
track("Button Clicked");
await flush().promise;
Custom user ID
If your app has its own login system that you want to track users with, you can call setUserId at any time.
TypeScript
import { setUserId } from "@amplitude/analytics-react-native";
setUserId("user@amplitude.com");
You can also assign the User ID as an argument to the init call.
import { init } from "@amplitude/analytics-react-native";
init(API_KEY, "user@amplitude.com");
Custom session ID
You can assign a new Session ID using setSessionId. When you set a custom session ID, make sure the value is in milliseconds since epoch (Unix Timestamp).
TypeScript
import { setSessionId } from "@amplitude/analytics-react-native";
setSessionId(Date.now());
Custom device ID
You can assign a new device ID using deviceId. When you set a custom device ID, make sure the value is sufficiently unique. Amplitude recommends a UUID.
import { setDeviceId } from "@amplitude/analytics-react-native";
const { uuid } = require("uuidv4");
setDeviceId(uuid());
Reset when a user logs out
reset is a shortcut to anonymize users after they log out, by:
- Setting
userIdtoundefined. - Setting
deviceIdto a new UUID value.
With an undefined userId and a completely new deviceId, the current user appears as a brand new user in the dashboard.
import { reset } from "@amplitude/analytics-react-native";
reset();
Opt users out of tracking
You can turn off logging for a given user by setting setOptOut to true.
import { setOptOut } from "@amplitude/analytics-react-native";
setOptOut(true);
The SDK doesn't save or send any events to the server while setOptOut is enabled, and the setting persists across page loads.
Re-enable logging by setting setOptOut to false.
import { setOptOut } from "@amplitude/analytics-react-native";
setOptOut(false);
Optional tracking
By default, the SDK tracks these properties automatically. You can override this behavior by passing a configuration called trackingOptions when you initialize the SDK, setting the appropriate options to false.
| Tracking Options | Default |
|---|---|
adid | true |
carrier | true |
deviceManufacturer | true |
deviceModel | true |
ipAddress | true |
language | true |
osName | true |
osVersion | true |
platform | true |
amplitude.init(API_KEY, OPTIONAL_USER_ID, {
trackingOptions: {
adid: false,
appSetId: false,
carrier: false,
deviceManufacturer: false,
deviceModel: false,
ipAddress: false,
idfv: false,
language: false,
osName: false,
osVersion: false,
platform: false,
},
});
Callback
All asynchronous APIs are optionally awaitable through a Promise interface. The Promise interface also serves as a callback interface.
import { track } from "@amplitude/analytics-react-native";
// Using async/await
const results = await track("Button Clicked").promise;
result.event; // {...} (The final event object sent to Amplitude)
result.code; // 200 (The HTTP response status code of the request.
result.message; // "Event tracked successfully" (The response message)
// Using promises
track("Button Clicked").promise.then((result) => {
result.event; // {...} (The final event object sent to Amplitude)
result.code; // 200 (The HTTP response status code of the request.
result.message; // "Event tracked successfully" (The response message)
});
Plugins
Plugins let you extend the Amplitude SDK's behavior by, for example, modifying event properties (enrichment type) or sending to third-party APIs (destination type). A plugin is an object with methods setup() and execute().
To integrate Experiment as a plugin, install @amplitude/plugin-experiment-react-native and use the experimentPlugin() function. Refer to Amplitude Analytics plugin in the Experiment React Native SDK documentation for setup details.
For Session Replay integration with Segment, refer to the Session Replay React Native Segment Integration guide.
add
The add method adds a plugin to Amplitude. Plugins can help process and send events.
import { add } from "@amplitude/analytics-react-native";
add(new Plugin());
remove
The remove method removes the given plugin name from the client instance if it exists.
import { remove } from "@amplitude/analytics-react-native";
remove(plugin.name);
Plugin setup
This method contains logic for preparing the plugin for use and has config as a parameter. The expected return value is undefined. A typical use for this method is to copy configuration from config or instantiate plugin dependencies. The SDK calls this method when you register the plugin to the client through client.add().
Plugin.execute
This method contains the logic for processing events and has event as a parameter. As an enrichment type plugin, the expected return value is the modified or enriched event. As a destination type plugin, the expected return value is a map with keys: event (BaseEvent), code (number), and message (string). The SDK calls this method for each event, including Identify, GroupIdentify, and Revenue events, that you instrument through the client interface.
Enrichment type plugin example
Here's an example of a plugin that modifies each instrumented event by adding an increment integer to the event_id property of an event starting from 100.
import { init, add } from "@amplitude/analytics-react-native";
import {
ReactNativeConfig,
EnrichmentPlugin,
Event,
PluginType,
} from "@amplitude/analytics-types";
export class AddEventIdPlugin implements EnrichmentPlugin {
name = "add-event-id";
type = PluginType.ENRICHMENT as const;
currentId = 100;
config?: ReactNativeConfig;
/**
* setup() is called on plugin installation
* example: client.add(new AddEventIdPlugin());
*/
async setup(config: ReactNativeConfig): Promise<undefined> {
this.config = config;
return;
}
/**
* execute() is called on each event instrumented
* example: client.track('New Event');
*/
async execute(event: Event): Promise<Event> {
event.event_id = this.currentId++;
return event;
}
}
init("API_KEY");
add(new AddEventIdPlugin());
Destination type plugin example
Here's an example of a plugin that sends each instrumented event to a target server URL using your preferred HTTP client.
import { init, add } from "@amplitude/analytics-react-native";
import {
ReactNativeConfig,
DestinationPlugin,
Event,
PluginType,
Result,
} from "@amplitude/analytics-types";
export class MyDestinationPlugin implements DestinationPlugin {
name = "my-destination-plugin";
type = PluginType.DESTINATION as const;
serverUrl: string;
config?: ReactNativeConfig;
constructor(serverUrl: string) {
this.serverUrl = serverUrl;
}
/**
* setup() is called on plugin installation
* example: client.add(new MyDestinationPlugin());
*/
async setup(config: ReactNativeConfig): Promise<undefined> {
this.config = config;
return;
}
/**
* execute() is called on each event instrumented
* example: client.track('New Event');
*/
async execute(event: Event): Promise<Result> {
const payload = { key: "secret", data: event };
const response = await fetch(this.serverUrl, {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "*/*",
},
body: JSON.stringify(payload),
});
return {
code: response.status,
event: event,
message: response.statusText,
};
}
}
init("API_KEY");
add(new MyDestinationPlugin("https://custom.domain.com"));
Advanced topics
Opt out of AsyncStorage
The React Native SDK uses @react-native-async-storage/async-storage to persist identity and the event queue across app launches. If you'd rather use your own storage backend (for example react-native-mmkv, an encrypted store, or SQLite), you can supply your own storage and exclude AsyncStorage from your native build.
The SDK uses two separate storage slots:
storageProviderfor the event queue (events waiting to flush to Amplitude).cookieStoragefor identity and session state (device ID, user ID, session ID).
Override both to fully opt out. If you only override storageProvider, the SDK still tries to read and write identity through the default chain, which falls back to AsyncStorage on native. If you've also removed AsyncStorage, identity degrades to in-memory and resets on every app launch.
Override both storage slots at init
Implement the Storage interface and pass both slots. init's signature is (apiKey, userId, options) — pass undefined or the desired user ID for userId so the overrides land in the options slot.
import { init } from "@amplitude/analytics-react-native";
init(API_KEY, undefined, {
storageProvider: myEventQueueStorage,
cookieStorage: myIdentityStorage,
});
Exclude AsyncStorage from native autolinking
Add the package to react-native.config.js with both native platforms set to null.
module.exports = {
dependencies: {
"@react-native-async-storage/async-storage": {
platforms: { ios: null, android: null },
},
},
};
AsyncStorage no longer links into your iOS or Android binaries. The JS package stays in node_modules so require() still resolves, but because you've overridden both storage slots, the SDK never invokes any AsyncStorage methods.
React Native Web
These steps cover iOS and Android only. React Native Web requires additional bundler configuration to strip AsyncStorage from the web bundle, which isn't yet documented here.
Custom HTTP client
You can provide an implementation of the Transport interface to the transportProvider configuration option for customization. For example, you can send requests to your proxy server with customized HTTP request headers.
import { Transport } from "@amplitude/analytics-types";
class MyTransport implements Transport {
async send(serverUrl: string, payload: Payload): Promise<Response | null> {
// check example: https://github.com/amplitude/Amplitude-TypeScript/blob/main/packages/analytics-client-common/src/transports/fetch.ts
}
}
amplitude.init(API_KEY, OPTIONAL_USER_ID, {
transportProvider: new MyTransport(),
});
Location
The Amplitude ingestion servers resolve event location in the following order:
- User-provided
city,country,region. - Resolved from
location_latandlocation_lng. - Resolved from
ip.
By default, the server determines location from the ip. To provide more granular location, you can set city, country, and region individually, or set location_lat and location_lng, which the server then resolves to city, country, and region. Amplitude doesn't set precise location in the SDK to avoid extra permissions that not all customers need.
To set fine-grain location, you can use an enrichment Plugin. Here is an example of how to set location_lat and location_lng.
Disabling IP tracking with ipAddress: false in TrackingOptions prevents the backend from resolving location. In this case, you may want to create a Plugin like the previous example to set any relevant location information yourself.
Carrier
Carrier support works on Android, but Apple stopped supporting it in iOS 16. In earlier versions of iOS, the SDK fetches carrier info using CTCarrier and serviceSubscriberCellularProviders, which are deprecated with no replacement.
Advertising identifiers
Different platforms have different advertising identifiers. Because of user privacy concerns, Amplitude doesn't automatically collect these identifiers. You can enable them using the following instructions. The platform providers no longer recommend some identifiers for use. Read the notes that follow before you decide to enable them.
| Platform | Advertising Identifier | Recommended | Notes |
|---|---|---|---|
| Android | AppSetId | Yes | AppSetId is a unique identifier for the app instance. The system resets it when the user reinstalls the app. |
| Android | ADID | No | ADID is a unique identifier for the device. The system resets it when the user opts out of personalized ads. |
| iOS | IDFV | Yes | IDFV is a unique identifier for the app instance. The system resets it when the user reinstalls the app. |
| iOS | IDFA | No | IDFA is a unique identifier for the device. The system resets it when the user opts out of personalized ads. |
Android
App set ID
App set ID is a unique identifier for each app install on a device. The user resets app set ID manually when they uninstall the app, or after 13 months of not opening the app. Google designed this as a privacy-friendly alternative to Ad ID for users who want to opt out of stronger analytics.
To use App Set ID, follow these steps.
Add
play-services-appsetas a dependency to the Android project of your app.bashdependencies { implementation 'com.google.android.gms:play-services-appset:16.0.2' }Enable
trackingOptions.appSetId.tsamplitude.init(API_KEY, OPTIONAL_USER_ID, { trackingOptions: { appSetId: true, }, });
Android Ad ID
Android Ad ID is a unique identifier for each device. The user resets Android Ad ID manually when they opt out of personalized ads.
To use Android Ad ID, follow these steps.
Add
play-services-ads-identifieras a dependency to the Android project of your app. The latest Android SDK docs describe the more detailed setup.bashdependencies { implementation 'com.google.android.gms:play-services-ads-identifier:18.0.1' }
Android Ad ID is enabled by default. To disable it, set trackingOptions.adId to false.
amplitude.init(API_KEY, OPTIONAL_USER_ID, {
trackingOptions: {
adId: false,
},
});
iOS
IDFV
IDFV is a unique identifier for the app instance. The system resets IDFV when the user reinstalls the app.
To enable IDFV on iOS devices, set trackingOptions.idfv to true.
amplitude.init(API_KEY, OPTIONAL_USER_ID, {
trackingOptions: {
idfv: true,
},
});
IDFA
Amplitude no longer recommends IDFA. Consider using IDFV instead when possible.
IDFA is a unique identifier for the device. The system resets IDFA when the user opts out of personalized ads.
The React Native SDK doesn't directly access the IDFA because it requires adding the AdSupport.framework to your app. Instead, you can use an Enrichment Plugin to set the IDFA yourself.
Here is an example Plugin that sets the IDFA using a third-party library.
Over the air updates (OTA)
If you use a platform like Expo that supports OTA updates, note that the SDK has both native and JS code. With OTA updates, you also need to make sure the native code updates. Refer to Expo's documentation on publishing and runtime versions for more details.
The following table lists versions of the SDK with the native code changes:
Was this helpful?