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

# React Native SDK

> Get started with our SDK built for iOS and Android apps using React Native

<Info>
  We are preparing a new v4 release of the React Native SDK. The documentation below covers the current shipping version — once v4 lands, this page will be updated.
</Info>

<Card title="React Native Demo Project" icon="github" href="https://github.com/kontextso/sdk-react-native-demo">
  See how easy it is to integrate high-performance ads into your React Native app using our lightweight SDK.
</Card>

## Requirements

* **React Native**: 0.73.2 or later

## Getting started

### 1. Installation

<Note>
  To get started, you will need to set up a [publisher account](/publishers#getting-started-is-easy) to get a `publisherToken` and `code`.
</Note>

```bash theme={null}
# Install the SDK
npm install @kontextso/sdk-react-native

# Install required peer dependencies
npm install react-native-device-info react-native-webview @react-native-community/netinfo
```

### 2. Initialize AdsProvider

The `AdsProvider` handles all data-fetching logic and must have access to the chat messages. Place it high enough in your component tree so it can contain all ad placements.

```tsx theme={null}
import * as React from 'react'
import { useState } from 'react'
import { View } from 'react-native'
import { AdsProvider } from '@kontextso/sdk-react-native'

interface Message {
  id: string
  role: 'user' | 'assistant'
  content: string
  createdAt: Date
}

function App() {
  const [messages, setMessages] = useState<Message[]>([])

  return (
    <AdsProvider
      publisherToken="<publisher-token>"
      messages={messages}
      userId='user-1234'
      conversationId='conv-5678'
      enabledPlacementCodes={['inlineAd']}
      character={{
        id: 'character-1234',
        name: 'John Doe',
        avatarUrl: 'https://example.com/avatar.png',
        greeting: 'Hello, how can I help you today?'
      }}
      regulatory={{
        coppa: 0,
        // ... other regulatory properties
      }}
      onEvent={({ name, code, payload }) => {
        // process events
      }}
    >
      <TheRestOfYourApplication />
    </AdsProvider>
  )
}
```

### 3. Set up IFA (Identifier for Advertisers)

* **iOS:** add `NSUserTrackingUsageDescription` to `ios/<YourApp>/Info.plist`. The SDK auto-prompts for ATT and reads IDFA from there.
* **Android:** the SDK adds the `com.google.android.gms.permission.AD_ID` permission via manifest merger automatically — no changes to your `AndroidManifest.xml` required.

See [IFA & ATT](/guides/ifa) for the full setup — required keys, prompt-timing gotchas, and how to manage the prompt yourself.

### 4. Set up SKAdNetwork (iOS only)

Add the SKAdNetwork identifiers we provide during onboarding to `ios/<YourApp>/Info.plist`. The SDK reads them and forwards them on every `/init` so DSPs can measure conversions.

See [SKAdNetwork](/guides/skadnetwork) for the full guide.

### 5. Show your first ad

An ad slot is a designated area in your UI where an ad can be rendered. In most cases, it appears below a chat message. During onboarding, you’ll receive a unique `code` for each ad slot you plan to use.

Copy the markup `<InlineAd />` and place it in your application where it should be rendered. Don't forget to assign `messageId` as a unique identifier. For example, if you have a `MessageList` component, you can show an ad after each message like this (every message will have a unique ad displayed because of `messageId`).

```tsx theme={null}
function MessageList({ messages }: { messages: Message[] }) {
  return (
    <View>
      {messages.map((m) => (
        <View key={m.id}>
          <Message message={m} />
          <InlineAd code="<your-code>" messageId={m.id} />
        </View>
      ))}
    </View>
  )
}
```

## API documentation

### `AdsProvider` properties

<ParamField path="publisherToken" type="string" required>
  Your unique publisher token.
</ParamField>

<ParamField path="messages" type="array" required>
  List of messages between the assistant and the user.

  <Expandable title="Properties">
    <ParamField path="id" type="string" required>
      Unique ID of the message.
    </ParamField>

    <ParamField path="role" type="string" required>
      Role of the message (`user` or `assistant`).
    </ParamField>

    <ParamField path="content" type="string" required>
      Message text.
    </ParamField>

    <ParamField path="createdAt" type="Date" required>
      Timestamp when the message was created.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField path="userId" type="string" required>
  Unique identifier that remains the same for the user’s lifetime (used for retargeting and rewarded ads).
</ParamField>

<ParamField path="userEmail" type="string">
  Email of the user.
</ParamField>

<ParamField path="conversationId" type="string" required>
  Unique ID of the conversation.
</ParamField>

<ParamField path="enabledPlacementCodes" type="array" required>
  Placement codes enabled for the conversation. Example: `['inlineAd']`.
</ParamField>

<ParamField path="character" type="object" optional>
  Character object used in this conversation.

  <Expandable title="Properties">
    <ParamField path="id" type="string" required>
      Unique ID of the character.
    </ParamField>

    <ParamField path="name" type="string" required>
      Name of the character.
    </ParamField>

    <ParamField path="avatarUrl" type="string" required>
      URL of the character’s avatar.
    </ParamField>

    <ParamField path="isNsfw" type="boolean" optional>
      Indicates whether the character is NSFW.
    </ParamField>

    <ParamField path="greeting" type="string" optional>
      The character’s greeting.
    </ParamField>

    <ParamField path="persona" type="string" optional>
      Description of the character’s personality.
    </ParamField>

    <ParamField path="tags" type="array" optional>
      Tags describing the character.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField path="regulatory" type="object" optional>
  Regulatory compliance information.

  **TCF (Transparency and Consent Framework)** signals — `gdpr` and `gdprConsent` — are handled automatically by the SDK if you have a TCF-compliant CMP (Consent Management Platform) integrated in your app. You do not need to set these manually.

  <Expandable title="Properties">
    <ParamField path="gdpr" type="integer" optional>
      Indicates whether the request is subject to GDPR regulations. (0 = No, 1 = Yes, null = Unknown)
    </ParamField>

    <ParamField path="gdprConsent" type="string" optional>
      The IAB Transparency and Consent Framework (TCF) consent string.
    </ParamField>

    <ParamField path="coppa" type="integer" optional>
      Indicates whether the request is subject to COPPA. (0 = No, 1 = Yes, null = Unknown)
    </ParamField>

    <ParamField path="gpp" type="string" optional>
      Global Privacy Platform (GPP) consent string.
    </ParamField>

    <ParamField path="gppSid" type="array" optional>
      IDs of the GPP sections that apply to this transaction.
    </ParamField>

    <ParamField path="usPrivacy" type="string" optional>
      Signals regarding consumer privacy under US privacy regulations (e.g., CCPA, LSPA).
    </ParamField>
  </Expandable>
</ParamField>

<ParamField path="variantId" type="string" optional>
  Publisher-provided identifier for the user cohort (for A/B testing).
</ParamField>

<ParamField path="onEvent" type="function" optional>
  Callback triggered when an event occurs. See [Supported events](#supported-events) for more details.
</ParamField>

<ParamField path="isDisabled" type="boolean" optional>
  Flag indicating if the ads are disabled.

  Note: This does not disable the display of old ads; that behavior is controlled by `staleAdsHandling`.
</ParamField>

<ParamField path="staleAdsHandling" type="string" optional>
  Determines how stale ads (ads not linked to the latest message) are handled.

  * `preserve` - keep displaying the last anchored ad until it's replaced by a new ad
  * `hide` (default) - hide the ad when it becomes stale
</ParamField>

### `InlineAd` properties

<ParamField path="code" type="string" required>
  Placement code provided during onboarding.
</ParamField>

<ParamField path="messageId" type="string" required>
  Unique ID of the message.
</ParamField>

<ParamField path="theme" type="string" optional>
  Theme of the ad, e.g. `light` or `dark`.
</ParamField>

<ParamField path="wrapper" type="function" optional>
  Wrapper function to wrap the ad content.
</ParamField>

### Supported Events

#### `ad.clicked`

The user has clicked the ad.

<Expandable title="Payload">
  <ParamField path="id" type="string">
    Ad ID.
  </ParamField>

  <ParamField path="content" type="string">
    Generated ad content.
  </ParamField>

  <ParamField path="messageId" type="string">
    Message ID.
  </ParamField>

  <ParamField path="url" type="string">
    Click URL.
  </ParamField>

  <ParamField path="format" type="string">
    Ad format.
  </ParamField>
</Expandable>

#### `ad.viewed`

The user has viewed the ad.

<Expandable title="Payload">
  <ParamField path="id" type="string">
    Ad ID.
  </ParamField>

  <ParamField path="content" type="string">
    Generated ad content.
  </ParamField>

  <ParamField path="messageId" type="string">
    Message ID.
  </ParamField>

  <ParamField path="format" type="string">
    Ad format.
  </ParamField>

  <ParamField path="revenue" type="number" optional>
    The revenue of the ad (eCPM in USD).
  </ParamField>
</Expandable>

#### `ad.filled`

Ad is available.

<Expandable title="Payload">
  <ParamField path="revenue" type="number" optional>
    The revenue of the ad (eCPM in USD).
  </ParamField>
</Expandable>

#### `ad.no-fill`

Ad is not available.

<Expandable title="Payload">
  <ParamField path="skipCode" type="string">
    The code indicating the reason why the ad was skipped.
  </ParamField>
</Expandable>

#### `ad.render-started`

Triggered before the first token is received.

<Expandable title="Payload">
  <ParamField path="id" type="string">
    Ad ID.
  </ParamField>
</Expandable>

#### `ad.render-completed`

Triggered after the last token is received.

<Expandable title="Payload">
  <ParamField path="id" type="string">
    Ad ID.
  </ParamField>
</Expandable>

#### `ad.error`

Triggered when an error occurs.

<Expandable title="Payload">
  <ParamField path="message" type="string">
    Error message.
  </ParamField>

  <ParamField path="errCode" type="string">
    Error code.
  </ParamField>
</Expandable>

#### `reward.granted`

Triggered when the user receives a reward.

<Expandable title="Payload">
  <ParamField path="id" type="string">
    Ad ID.
  </ParamField>
</Expandable>

#### `video.started`

Triggered when the video playback starts.

<Expandable title="Payload">
  <ParamField path="id" type="string">
    Ad ID.
  </ParamField>
</Expandable>

#### `video.completed`

Triggered when the video playback finishes.

<Expandable title="Payload">
  <ParamField path="id" type="string">
    Ad ID.
  </ParamField>
</Expandable>

## Guides

### Handling no-fill events

You can notify when the ad is not available by using the `onEvent` callback.

```tsx theme={null}
<AdsProvider
  // ...
  onEvent={({ name, payload }) => {
    if (name === 'ad.no-fill') {
      console.log('Ad is not available');
    }
  }}
/>
```

## Links

* [NPM Package](https://www.npmjs.com/package/@kontextso/sdk-react-native)
* [React Native Demo Project](https://github.com/kontextso/sdk-react-native-demo)
