> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pnlight.app/llms.txt
> Use this file to discover all available pages before exploring further.

# React Native SDK

> Install @pnlight/sdk-react-native, link the native iOS module, and initialize the PNLight SDK in a React Native app to track installs, send attribution, and render Remote UI.

Use `@pnlight/sdk-react-native` for React Native apps that need PNLight on iOS.

## Install

```bash theme={null}
npm install @pnlight/sdk-react-native
```

Package page: [@pnlight/sdk-react-native on npm](https://www.npmjs.com/package/@pnlight/sdk-react-native).

[![React Native SDK version](https://img.shields.io/npm/v/%40pnlight%2Fsdk-react-native?label=React%20Native)](https://www.npmjs.com/package/@pnlight/sdk-react-native)

## Initialize the SDK

Call `initialize` once during app startup.

```tsx theme={null}
import { initialize } from "@pnlight/sdk-react-native";

await initialize("pnlight_sdk_token");
```

## Common calls

```tsx theme={null}
import {
  addAttribution,
  getUserId,
  logEvent,
} from "@pnlight/sdk-react-native";

const userId = await getUserId();

await addAttribution(
  "appsFlyer",
  { af_status: "Non-organic" },
  "appsFlyerCustomerId"
);

await logEvent("paywall_viewed", {
  placement: "paywall",
});
```

`logEvent` sends optional in-app events to PNLight. You can review them in **Analytics → App Events**, on the **Events** page, and in customer timelines.

## IDFA after ATT

If PNLight initializes before the App Tracking Transparency prompt completes, call `updateIdfa()` after authorization so PNLight receives the granted IDFA.

```tsx theme={null}
import { updateIdfa } from "@pnlight/sdk-react-native";
import { requestTrackingPermission } from "react-native-tracking-transparency";

await requestTrackingPermission();
await updateIdfa();
```

## Remote UI component

Use `RemoteUiView` to fetch and render a placement. Add an `onAction` handler so your app can respond to actions from the returned UI.

```tsx theme={null}
import { RemoteUiView } from "@pnlight/sdk-react-native";

export function PaywallScreen() {
  return (
    <RemoteUiView
      placement="paywall"
      cardId="paywall_card"
      style={{ flex: 1 }}
      onAction={(event) => {
        if (event.logId === "purchase_button") {
          startPurchase(event.params.id).then(() => {
            navigation.navigate("Main");
          });
        }
      }}
    />
  );
}
```

### Remote UI props

| Prop                  | Type       | Description                                                                                |
| --------------------- | ---------- | ------------------------------------------------------------------------------------------ |
| `placement`           | `string`   | Placement ID configured in PNLight.                                                        |
| `cardId`              | `string`   | Optional card ID. Defaults to a placement-based value.                                     |
| `secure`              | `boolean`  | Deprecated. Secure rendering is controlled by the dashboard placement.                     |
| `preventRecording`    | `boolean`  | Deprecated. Capture blocking is controlled by the dashboard placement.                     |
| `attributionRequired` | `boolean`  | Waits for attribution before returning a config when enabled. Defaults to `true`.          |
| `ignoreCache`         | `boolean`  | Waits for a fresh server response instead of serving a cached config. Defaults to `false`. |
| `onAction`            | `function` | Handles custom actions from the rendered UI.                                               |
| `onError`             | `function` | Handles config loading errors.                                                             |

Use [Remote UI](/sdk/remote-ui) to learn how placements and actions work.
