> For the complete documentation index, see [llms.txt](https://documentation.pushly.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://documentation.pushly.com/integration/implementation-steps/react-native/sdk-react-native.md).

# SDK: React Native

## Step 1: Import the PushSDK Library

Install the PushSDK using either your preferred package manager.

{% tabs %}
{% tab title="Yarn" %}

```sh
yarn add @pushly/push-sdk-react-native
```

{% endtab %}

{% tab title="NPM" %}

```sh
npm install --save @pushly/push-sdk-react-native
```

{% endtab %}
{% endtabs %}

[<mark style="color:blue;">Autolinking is provided automatically</mark>](https://reactnative.dev/blog/2019/07/03/version-60#native-modules-are-now-autolinked) if you are using React Native version **0.60** or greater.

## Step 2: Android Setup

### Step 2.1: Gradle

Update your gradle scripts with the required dependencies:

{% tabs %}
{% tab title="android/build.gradle" %}

```gradle
buildscript {
    ...
    dependencies {
        ...
        classpath 'com.google.gms:google-services:4.3.13'
    }
}
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="android/app/build.gradle" %}

```gradle
android {
    compileSdk 36
    ...

    defaultConfig {
        ...
        minSdk 24
        targetSdk 34
    }
}

apply plugin: 'com.google.gms.google-services'
```

{% endtab %}
{% endtabs %}

### Step 2.2: Google Services

Add your `google-services.json` file to `android/app` directory.

## Step 3: iOS Setup

### Step 3.1: Install Pods

Within your `<project_root>/ios` directory run: `pod install`

### Step 3.2: Add Notification Service Extension

The Notification Service Extension is required to enable rich notifications that support images and custom actions.

Open XCode using your app's **xcworkspace.** Next, select `File > New > Target` and then select `Notification Service Extension` inside the iOS templates tab and click `Next`.

<figure><img src="https://810756845-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Lry9Z27iWOZyQEGAgY7%2Fuploads%2FIKOtBgXyBx78VJBxuNs9%2Fimage.png?alt=media&#x26;token=b0055514-7e75-4ce8-a0b3-bbba8f2543c6" alt=""><figcaption></figcaption></figure>

Enter "NotificationServiceExtension" for the `Product Name` and any other configuration details for your app extension and then click `Finish` but **do not click activate** on the subsequent dialog.

<figure><img src="https://810756845-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Lry9Z27iWOZyQEGAgY7%2Fuploads%2F96yVKAthjykdmnXGXlem%2Fimage.png?alt=media&#x26;token=b8ed3424-44e0-4259-b97b-bb1457411164" alt=""><figcaption></figcaption></figure>

Click `Cancel` on the dialoging prompting you to activate the service extension so that you can set the deployment target once the modal is closed.

<img src="https://810756845-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Lry9Z27iWOZyQEGAgY7%2Fuploads%2FcGXECnSyGjGGEUBg5KDM%2Fimage.png?alt=media&#x26;token=bc91b955-baa5-490f-a32b-dd7367657f9f" alt="" data-size="original">

Set the extension's `Deployment Target` to the **same value as your primary application target**.

### Step 3.3: Add the Pushly Dependency to the Service Extension

In your `<project_root>/ios/Podfile`, add the **NotificationServiceExtension** at the same level as your main target:

{% tabs %}
{% tab title="Podfile" %}

```ruby
target 'NotificationServiceExtension' do
  pod 'Pushly', '>= 1.0', '< 2.0'
end
```

{% endtab %}

{% tab title="Example Podfile" %}

```ruby
require_relative '../node_modules/react-native/scripts/react_native_pods'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'

platform :ios, min_ios_version_supported
prepare_react_native_project!

linkage = ENV['USE_FRAMEWORKS']
if linkage != nil
  Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green
  use_frameworks! :linkage => linkage.to_sym
end

target 'PushlyDevApp' do
  config = use_native_modules!

  use_react_native!(
    :path => config[:reactNativePath],
    # An absolute path to your application root.
    :app_path => "#{Pod::Config.instance.installation_root}/.."
  )

  target 'PushlyDevAppTests' do
    inherit! :complete
    # Pods for testing
  end

  post_install do |installer|
    react_native_post_install(
      installer,
      config[:reactNativePath],
      # Set `mac_catalyst_enabled` to `true` in order to apply patches
      # necessary for Mac Catalyst builds
      :mac_catalyst_enabled => false
    )
  end
end

target 'NotificationServiceExtension' do
  pod 'Pushly', '>= 1.0', '< 2.0'
end
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
This version range is deliberately wide, and you do not need to narrow it when you upgrade. The React Native SDK's podspec already declares the exact `Pushly` version its bridge needs, and CocoaPods installs the single version that satisfies both requirements.
{% endhint %}

Now that the service extension dependency has been added to the Podfile you will need to re-run installation. Within the `<project_root>/ios` directory, run: `pod install`.

### Step 3.4: Update the Service Extension

Now, open the newly created Notification Service Extension and replace the code with the following:

{% tabs %}
{% tab title="Swift" %}

```swift
import Pushly

class NotificationService: PNNotificationServiceExtension {
}
```

{% endtab %}

{% tab title="Objective-C" %}

```objectivec
// Make sure to keep the header file import
#import "NotificationService.h"

@import Pushly;

@interface NotificationService ()

@property (nonatomic, strong) void (^contentHandler)(UNNotificationContent *contentToDeliver);
@property (nonatomic, strong) UNMutableNotificationContent *bestAttemptContent;

@end

@implementation NotificationService

- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
    self.contentHandler = contentHandler;
    self.bestAttemptContent = [request.content mutableCopy];
    
    [PNNotificationServiceExtensionHandler didReceiveExtensionRequest:request content:self.bestAttemptContent withContentHandler:contentHandler];
}

- (void)serviceExtensionTimeWillExpire {
    // Called just before the extension will be terminated by the system.
    // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
    [PNNotificationServiceExtensionHandler didRecieveExtensionTimeWillExpire:self.bestAttemptContent withContentHandler:self.contentHandler];

    self.contentHandler(self.bestAttemptContent);
}

@end
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
If Xcode warns that it cannot find Pushly, make sure you have a physical device or the "Any iOS Device" option selected as your build destination.
{% endhint %}

### Step 3.4: Add Capabilities to Primary Application Target

{% hint style="warning" %}
The Push Notifications capability should only be added to the **primary application target**.
{% endhint %}

Select the root project and then your primary application target > `Signing & Capabilities`

<figure><img src="https://810756845-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Lry9Z27iWOZyQEGAgY7%2Fuploads%2FPEKQiayxyjIphpjeqxB1%2Fimage.png?alt=media&#x26;token=84e69c08-d120-4a48-a193-a272b9e4f109" alt=""><figcaption></figcaption></figure>

Click the `+ Capability` and add `Push Notifications`.

Click the `+ Capability` and add `Background Modes`.

After adding the `Background Modes` capability ensure that `Remote Notifications` are enabled.

<figure><img src="https://810756845-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Lry9Z27iWOZyQEGAgY7%2Fuploads%2FMAfJ7lisFKGMxQvjpIaB%2Fimage.png?alt=media&#x26;token=7b5b4afb-0a24-4b0a-8ef6-594f763231ea" alt=""><figcaption></figcaption></figure>

Click the `+ Capability` and add `App Groups`.

Click the `+` symbol located inside the `App Groups` section to add a new named container. To ensure that the PushSDK can properly capture information the container should be named `group.{app-bundle-id}.push`.

<figure><img src="https://810756845-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Lry9Z27iWOZyQEGAgY7%2Fuploads%2FOR42sYi1kH4o1227pQpY%2Fimage.png?alt=media&#x26;token=c504305e-c703-4e7e-afff-834d9de68aac" alt=""><figcaption></figcaption></figure>

Check the box next to the newly created App Group in the primary application target.

### Step 3.5: Add Capabilities to The Notification Service Extension

Now in your **NotificationServiceExtension** target select the `Signing & Capabilities` tab.

Click the `+ Capability` and add `App Groups`.

Finally, check the box next to the newly created App Group.

## Step 4: SDK Initialization

In your `index.tsx` or `app.tsx` file initialize the PushSDK using the example implementation code below.

Replace the `REPLACE_WITH_SDK_KEY` in the `setConfiguration` method with the SDK Key from the platform settings page.

{% tabs %}
{% tab title="index.tsx" %}

```tsx
...
import { PushSDK, LogLevel } from '@pushly/push-sdk-react-native';

export const App = () => {
    ...

    // We recommend initializing the PushSDK in a useEffect block
    // to prevent the application from attempting to invoke
    // PushSDK.setConfiguration() on each rerender
    React.useEffect(() => {
        PushSDK.setLogLevel(LogLevel.INFO);
        PushSDK.setConfiguration({ appKey: 'REPLACE_WITH_SDK_KEY' });

        PushSDK.showNativeNotificationPermissionPrompt().then(({ granted }) => {
            console.log(`Permissions granted: ${granted}`);
        });
    }, []);
    
    // The rest of the your app
    ...
};
```

{% endtab %}
{% endtabs %}

Run your application on either an Android device or emulator (ensure the emulator has `Google Play Store Services` installed) or on an iOS device, if building for iOS, to make sure it builds correctly.

The code you added in the previous step will show the push permission dialog upon app open. This can be customized by using [SDK methods](/integration/implementation-steps/react-native/sdk-react-native/sdk-methods.md) to control when the dialog shows.

After accepting the dialog log into the platform and navigate to `Notifications > Create Notification` and send your first notification, targeting the appropriate **Native: iOS** or **Native: Android** channel, to your device.

## Next Steps

Once you have confirmed the SDK is working properly you may continue to add additional optional functionality like:

* [<mark style="color:blue;">Handling notification opens / app links / deep linking</mark>](/integration/implementation-steps/react-native/sdk-react-native/deep-linking.md)
* [<mark style="color:blue;">Attaching attributes to a subscriber's profile</mark>](/integration/implementation-steps/react-native/sdk-react-native/sdk-methods.md)
* [<mark style="color:blue;">Sending information about what content a subscriber interacts with</mark>](/integration/implementation-steps/react-native/sdk-react-native/activity-tracking.md)


---

# 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, and the optional `goal` query parameter:

```
GET https://documentation.pushly.com/integration/implementation-steps/react-native/sdk-react-native.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
