---
title: "React Native SDK"
source: https://docs.myappaffiliate.com/sdk-react-native
docs: "MyAppAffiliate — Developer Documentation"
index: https://docs.myappaffiliate.com/llms.txt
---
# React Native SDK

One integration for iOS + Android. Pure JS/TS over `fetch` — no native modules to link.

**Prompt for an AI coding agent**

```text
Integrate MyAppAffiliate into my project.

Documentation (read these first, they are the source of truth):
- Page: https://docs.myappaffiliate.com/sdk-react-native.md
- Full docs index: https://docs.myappaffiliate.com/llms.txt

Task: Add the MyAppAffiliate React Native SDK to my app: install the package, start it once at app startup passing AsyncStorage and Linking, and identify the user with the same id my billing provider reports. Tell me what changes if I'm on Expo.

Rules:
- Follow the documented API exactly — no invented method names, endpoints, parameters or field names.
- Match the conventions already used in my codebase.
- Ask me for my SDK key instead of guessing, and never hard-code it — read it from config/environment.
- Do NOT set an API base URL anywhere. Every SDK compiles the production host in; a staging or self-hosted host belongs in a build setting, not in code.
- Tell me afterwards which steps I still have to do by hand (dashboard settings, capabilities, webhook configuration).
```

## Install

```bash
npm i @myappaffiliate/sdk-react-native @react-native-async-storage/async-storage
```

## 1. Start it

```ts
import AsyncStorage from "@react-native-async-storage/async-storage";
import { Linking } from "react-native";
import { myAppAffiliate } from "@myappaffiliate/sdk-react-native";

await myAppAffiliate.start({
  apiKey: "pk_live_…",
  storage: AsyncStorage,  // so attribution survives an app restart
  linking: Linking,       // hands us your deep links — cold start included
});
```

You never pass an API URL — the host is compiled in.

`storage` and `linking` are the two things the SDK cannot get on its own, because this
package deliberately imports neither `react-native` nor AsyncStorage (that is what
makes it work identically in bare RN, Expo, and Expo Go). Pass them and everything
else is automatic: with `linking`, the SDK subscribes to deep links itself, so you
write no `getInitialURL` / `addEventListener` glue.

## 2. Identify the user

Call this once you know who the user is. The id must be the **same string your
billing provider reports back to us** — RevenueCat's `logIn(...)` id, Adapty's
customer user id, Superwall's app user id, or your Stripe/Paddle metadata value. See
[Billing & Webhooks](https://docs.myappaffiliate.com/webhooks).

```ts
await myAppAffiliate.identify(user.id);
```

That's the whole integration. There is no third step — in particular, you do **not**
need to set an `affiliate_id` subscriber attribute anywhere; attribution joins on the
user id.

## Optional

**Creator codes** — a "Got a code?" field. Works with no deep-link setup at all:

```ts
await myAppAffiliate.applyCode("LUMI");
```

**Handle links yourself** instead of passing `linking`:

```ts
await myAppAffiliate.attribute(url);  // claim_token | ct | via | ref | code
```

**Read the attribution** for your own UI or analytics:

```ts
const affiliateId = await myAppAffiliate.attributedAffiliateId();  // string | null
```

**Staging or self-hosted API**, and debug logging:

```ts
await myAppAffiliate.start({
  apiKey: "pk_live_…",
  storage: AsyncStorage,
  apiBaseUrl: "https://staging.example.com",
  debug: true,
});
```

**On logout or a data-erasure request:** `await myAppAffiliate.reset();`

## What `start` does for you

- Generates and persists a device id.
- Claims the deep link the app was launched with, and every one that arrives later.
- Retries a referral an earlier launch captured but failed to send.

All calls resolve to `false`/`null` on failure — never a thrown error in your render
path.

## Expo

Works in the **managed workflow** — the SDK is pure JS, and AsyncStorage has an Expo
build (`npx expo install @react-native-async-storage/async-storage`). For deep links,
pass `expo-linking` as `linking`; it exposes the same `getInitialURL` and
`addEventListener("url", …)` shape.

Universal/App Links need a dev build or EAS (associated domains can't be tested in
Expo Go); the creator-code path works everywhere, Expo Go included.

## API

| Call | Purpose |
|---|---|
| `myAppAffiliate.start({ apiKey, storage, linking })` | Start once at startup |
| `myAppAffiliate.identify(userId)` | Bind your user id to the attribution |
| `myAppAffiliate.attribute(url)` | Claim a referral from a link |
| `myAppAffiliate.applyCode(code)` | Creator-code entry |
| `myAppAffiliate.attributedAffiliateId()` | The attributed affiliate id (or `null`) |
| `myAppAffiliate.reset()` | Clear all persisted SDK state |

Every function is also a named export (`import { start, identify } from …`) if you
prefer that to the namespace.
