> For the complete documentation index, see [llms.txt](https://docs.amply.tools/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.amply.tools/developer-guide/react-native-integration.md).

# React Native integration

In plain English: this page is a collection of how-tos for the Amply React Native SDK beyond "just get it running." It covers peer dependencies, the iOS pod install step, Android autolinking, using the `useAmplySystemEvents` hook, cleaning up listeners so you don't leak memory, and handling re-initialization when the JS bundle reloads. A PM can skim the headings; an engineer copies the TypeScript snippets.

**Use this when** the React Native SDK is installed and you need to wire a specific flow. **Don't use this when** you haven't finished the Quickstart yet — start there.

## Before you start

* React Native 0.79+, Expo SDK 54+ (or bare RN 0.79+) — see [Installation](/developer-guide/installation.md) for the full requirements matrix.
* New Architecture enabled (the SDK uses the new native module system).
* Node 18+.

## Peer dependencies and install

The SDK requires `react >=18.2.0`, `react-native >=0.79.0`, and `expo >=54.0.0` as peer dependencies — make sure your app has them, then install:

```bash
npm install @amplytools/react-native-amply-sdk
```

## iOS: run pod install

After installing the npm package, refresh the iOS native project. This links the native iOS SDK into your app.

```bash
cd ios
pod install
cd ..
```

Run this every time you change the installed npm version of the SDK.

## Android: autolinking is automatic

On Android there is no manual Gradle edit. The SDK ships a `react-native.config.js` entry that React Native's autolinking picks up on the next build. Just rebuild:

```bash
npx react-native run-android
```

If you use Expo with `expo prebuild`, the SDK's config plugin registers the native package for you during prebuild.

## Initialize once, early

Call `initialize` once, as close to app start as possible. The function returns a Promise that resolves when the native SDK is ready.

**Signature:**

```ts
Amply.initialize(config: AmplyInitializationConfig): Promise<void>

type AmplyInitializationConfig = {
  appId: string;
  apiKeyPublic: string;
  apiKeySecret?: string | null;
  endpoint?: string | null;
  defaultConfig?: string | null;
  debug?: boolean | null;
  logLevel?: LogLevel | null;
};
```

```tsx
// App.tsx
import {useEffect} from 'react';
import Amply from '@amplytools/react-native-amply-sdk';

export default function App() {
  useEffect(() => {
    Amply.initialize({
      appId: 'com.example.app',
      apiKeyPublic: 'pk_...',
      apiKeySecret: 'sk_...',
      logLevel: 'warn',
    }).catch(err => console.warn('[Amply] init failed', err));
  }, []);

  return <RootNavigator />;
}
```

`Amply.isInitialized()` returns `true` synchronously once `initialize` has resolved.

### Custom property value types

RN custom properties accept `string | number | boolean` only. The iOS and Android native SDKs accept more types — stick to primitives on React Native.

## Re-init on Fast Refresh / JS reload

Pressing R in Metro re-runs your JS bundle but the native side stays alive. The native SDK remains initialized across JS reloads. Guarding your init is optional but keeps logs clean:

```ts
if (!Amply.isInitialized()) await Amply.initialize(config);
```

On a cold launch, both JS and native start fresh — always call `initialize` on mount.

## Listening to system events

System events are SDK lifecycle signals: config loaded, session started, campaign evaluated. Two APIs are available.

### Option 1: the hook (good for debug UI)

**Signature:**

```ts
useAmplySystemEvents(options?: {
  maxEntries?: number;       // default 50
  dedupe?: boolean;          // default true
  onEvent?: (event: EventRecord) => void;
}): {events: EventRecord[]; reset: () => void};
```

```tsx
import {useAmplySystemEvents} from '@amplytools/react-native-amply-sdk';

function DebugPanel() {
  const {events, reset} = useAmplySystemEvents({maxEntries: 20});
  return (
    <View>
      {events.map(e => <Text key={e.id}>{e.name} @ {e.timestamp}</Text>)}
      <Button title="Clear" onPress={reset} />
    </View>
  );
}
```

### Option 2: the raw listener (good for production)

Returns a Promise that resolves to an unsubscribe function.

**Signature:**

```ts
Amply.addSystemEventListener(
  listener: (event: EventRecord) => void
): Promise<() => void>;
// Alias: Amply.systemEvents.addListener(listener)
```

```tsx
useEffect(() => {
  let unsubscribe: (() => void) | undefined;
  let cancelled = false;

  Amply.systemEvents.addListener(event => {
    console.log('[Amply]', event.name, event.properties);
  }).then(unsub => {
    if (cancelled) unsub();           // component unmounted before subscribe landed
    else unsubscribe = unsub;
  });

  return () => {
    cancelled = true;
    unsubscribe?.();                  // always call the unsubscribe
  };
}, []);
```

{% hint style="warning" %}
Always call the returned unsubscribe in cleanup. Subscriptions that outlive the component that created them will keep the listener running on stale state and can leak memory across navigations.
{% endhint %}

## Receiving campaign deeplinks

Same Promise-returns-unsubscribe shape.

**Signature:**

```ts
Amply.addDeepLinkListener(
  listener: (event: DeepLinkEvent) => void
): Promise<() => void>;

type DeepLinkEvent = {url: string; info: JsonMap; consumed: boolean};
```

```tsx
useEffect(() => {
  let unsubscribe: (() => void) | undefined;
  let cancelled = false;
  Amply.addDeepLinkListener(event => {
    navigation.navigate('Route', {url: event.url});
  }).then(unsub => { if (cancelled) unsub(); else unsubscribe = unsub; });
  return () => { cancelled = true; unsubscribe?.(); };
}, [navigation]);
```

Declare your URL scheme in `Info.plist` and `AndroidManifest.xml` — see [iOS integration](/developer-guide/ios-integration.md#registering-your-deeplink-scheme) and [Android integration](/developer-guide/android-integration.md#registering-deeplink-intent-filters).

## Tracking events and identifying the user

```ts
Amply.track({name: 'ScreenViewed', properties: {screen: 'Home'}});

Amply.setUserId('user_42');
Amply.setCustomProperties({plan: 'premium', seats: 3, trial: false});
await Amply.getCustomProperty('plan');   // 'premium'
Amply.setUserId(null);                   // clear
```

See [Tracking events](/developer-guide/tracking-events.md) and [User attributes](/developer-guide/user-attributes.md) for payload rules.

## Tearing down all listeners

For hard resets (user logs out, tests):

```ts
Amply.removeAllListeners();
```

This clears every deeplink subscription the SDK is currently tracking. It does not uninitialize the SDK.

## Log level

```ts
Amply.setLogLevel('debug');   // 'none' | 'error' | 'warn' | 'info' | 'debug'
Amply.getLogLevel();
```

Debug logging is forwarded to `console` automatically when the level is not `'none'`.

## Related

* [React Native quickstart](/developer-guide/quickstart-react-native.md) — initial setup, not covered here.
* [Tracking events](/developer-guide/tracking-events.md) — payload shapes and common patterns.
* [Handling deeplinks](/developer-guide/handling-deeplinks.md) — cross-platform deeplink routing patterns.
* [iOS integration](/developer-guide/ios-integration.md) — platform-specific flows that still apply under RN.
* [Android integration](/developer-guide/android-integration.md) — platform-specific flows that still apply under RN.
* [SDK reference: React Native](/reference/sdk-react-native.md) — full method list.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.amply.tools/developer-guide/react-native-integration.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
