> 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-expo-plugin/sdk-expo-plugin.md).

# SDK: Expo plugin

## Step 1: Install the packages

`@pushly/push-sdk-expo` applies the native configuration; `@pushly/push-sdk-react-native` provides the runtime SDK you import from. Install both.

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

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

{% endtab %}

{% tab title="NPM" %}

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

{% endtab %}
{% endtabs %}

## Step 2: Adding plugin to Expo config

### Step 2.1: Google Services

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

### Step 2.2: app.config.js

Add the plugin to your Expo config and provide the App Group ID, Android application ID (must match the package inside `google-services.json`), and the path to your `google-services.json` file:

{% tabs %}
{% tab title="app.config.js" %}

```javascript
export default {
  expo: {
    ...,
    plugins: [
      [
        '@pushly/push-sdk-expo',
        {
          ios: {
            nseTargetName: 'NotificationServiceExtension',
            nseBundleIdSuffix: '.NotificationServiceExtension',
            appGroupId: 'group.com.example.myapp.push',
            swiftVersion: '5.0',
          },
          android: {
            applicationId: 'com.example.myapp',
            googleServicesFile: './app/google-services.json',
            applyGoogleServicesPlugin: true,
          },
        },
      ],
    ],
  },
};
```

{% endtab %}
{% endtabs %}

<table><thead><tr><th>Property</th><th>Definition</th></tr></thead><tbody><tr><td><pre><code>ios.nseTargetName
</code></pre></td><td>User-defined name for NotificationServiceExtension.<br><code>default: NotificationServiceExtension</code></td></tr><tr><td><pre><code>ios.nseBundleIdSuffix
</code></pre></td><td>Bundle id suffix for NotificationServiceExtension. Value is appended to PRODUCT_BUNDLE_IDENTIFIER env var.<br><code>default: .NotificationServiceExtension</code></td></tr><tr><td><pre><code>ios.appGroupId
</code></pre></td><td>To ensure that the PushSDK can properly capture information the container should be named <code>group.{app-bundle-id}.push</code>.</td></tr><tr><td><pre><code>ios.swiftVersion
</code></pre></td><td>Used to setup NotificationServiceExtension target in pbxproj file.<br><code>default: 5.0</code></td></tr><tr><td><pre><code>android.applicationId
</code></pre></td><td>Application ID used by Android application. Defaults to <code>android.package</code> from your Expo config.</td></tr><tr><td><pre><code>android.googleServicesFile
</code></pre></td><td>Location of google-services.json file relative to the project root</td></tr><tr><td><pre><code>android.applyGoogleServicesPlugin
</code></pre></td><td>Should google services plugin be applied in gradle.<br><code>default: true</code></td></tr></tbody></table>

Run `expo prebuild --clean` (or use EAS Build/custom dev clients) to generate native projects with the Pushly setup applied.

## Step 3: iOS Setup

### Step 3.1: Install Pods

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

### Step 3.2: Notification Service Extension

A **Notification Service Extension** is required to unlock full rich media and analytics tracking functionality, which this plugin installs for you during prebuild.

{% hint style="warning" %}
Use `expo run:ios` or an EAS build to ensure automatic NSE installation. If your project has a checked-in `ios/` directory, `expo prebuild` will not regenerate it and EAS skips prebuild entirely. In that case, run `npx expo prebuild --platform ios --clean` so the extension is installed.
{% endhint %}

To verify the extension was installed in a build, inspect the IPA:

```bash
unzip -l YourApp.ipa | grep appex
```

This should list `PlugIns/NotificationServiceExtension.appex`. If it does not, the extension was never installed — confirm you are using a dev or EAS build and that prebuild ran.

## 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-expo-plugin/sdk-expo-plugin.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.
