# Expo SDK Basic integration guide

This section contains information on how to integrate the Pushwoosh Expo SDK into your application.

## Prerequisites

To integrate the Pushwoosh Expo SDK into your app, you will need the following:

<Aside type="note" title="Requirements">
 - A [Pushwoosh account](https://sso.pushwoosh.com/login).
 - A [Pushwoosh project](/product/first-steps/start-with-your-project/create-your-project) set up in your account.
 - **For iOS integration:**
    - An iOS platform configured to send push notifications. We recommend using the [Token-Based Authentication configuration](/developer/first-steps/connect-messaging-services/ios-configuration/ios-token-based-configuration/) as the simplest approach.
    - Set the Gateway to `Sandbox` to send pushes to a simulator.
 - **For Android integration:**
    - A [configured Android platform](/developer/first-steps/connect-messaging-services/android-configuration/android-firebase-configuration)
    - The `google-services.json` file and `package name` from your Firebase project.
    - A Firebase project connected to your Android application. Follow the [Firebase setup guide](https://firebase.google.com/docs/android/setup#manually_add_firebase) if needed.
 - Your `Pushwoosh Application Code` and [Pushwoosh Device API Token](/developer/api-reference/api-access-token/#device-api-token) from the Pushwoosh Control Panel for your application.
</Aside>

## Integration steps

### 1. Install the plugin

Install the Pushwoosh Expo plugin using the Expo CLI

```bash
expo install pushwoosh-expo-plugin
```

Install Pushwoosh React Native SDK

```bash
npm install pushwoosh-react-native-plugin --save
```

### 2. Set the plugin properties

Add the plugin to the front of the plugin array with the necessary properties:

```json title="app.json/app.config.js"
{
  "expo": {
    "plugins": [
      [
        "pushwoosh-expo-plugin",
        {
          "mode": "development",
          "ios": {
            "PW_API_TOKEN": "__YOUR_DEVICE_API_TOKEN__"
          },
          "android": {
            "apiToken": "__YOUR_DEVICE_API_TOKEN__"
          }
        }
      ]
    ]
  }
}
```
Where:

- `mode` is used to configure the APNs environment entitlement. “Development” or “production” values are available.
- `PW_API_TOKEN`, `apiToken` is your [Pushwoosh Device API Token.](/developer/api-reference/api-access-token/#device-api-token)

### 3. Initialize Pushwoosh

In the root component of your application:
- Import the `pushwoosh-react-native-plugin` plugin.
- Initialize the Pushwoosh SDK.
- Call `register()` in your initialization logic to register for push notifications.

```javascript title="index.tsx"
import Pushwoosh from 'pushwoosh-react-native-plugin';

Pushwoosh.init({
    "pw_appid": "__YOUR_APP_ID__"
});

Pushwoosh.register();
```
Where:
- `__YOUR_APP_ID__` is the application code from the Pushwoosh Control Panel.

### 4. Android Native Setup

Add Firebase configuration file:

1. Copy your `google-services.json` file to the root directory of the project.
2. Set the `googleServicesFile` property to the path of your `google-services.json` and specify the `package` property:

```json title="app.json/app.config.js"
  "expo": {
    "name": "sample",
  "android": {
    "package": "com.pushwoosh.sample",
    "googleServicesFile": "./google-services.json"
  },
  "plugins": [
    [
      "pushwoosh-expo-plugin",
      {
        "mode": "development",
        "ios": {
          "PW_API_TOKEN": "__YOUR_DEVICE_API_TOKEN__"
        },
        "android": {
          "apiToken": "__YOUR_DEVICE_API_TOKEN__"
        }
      }
    ]
  ]
}
```

### 5. iOS Native Setup

Set `bundleIdentifier` property to the `ios` object:

```json title="app.json/app.config.js"
  "expo": {
    "name": "sample",
    "ios": {
      "bundleIdentifier": "com.pushwoosh.sample"
    },
    "plugins": [
    [
      "pushwoosh-expo-plugin",
      {
        "mode": "development",
        "ios": {
          "PW_API_TOKEN": "__YOUR_DEVICE_API_TOKEN__"
        },
        "android": {
          "apiToken": "__YOUR_DEVICE_API_TOKEN__"
        }
      }
    ]
  ]
}
```

### 6. Prebuild the app
Generate native code and configure the dependencies for each platform by running prebuild:
```bash
npx expo prebuild
```

### 7. Run the project

1. Build and run the project:
<Tabs>
<TabItem label="Android">
```bash
npx expo run:android
```
</TabItem>

<TabItem label="iOS">
```bash
npx expo run:ios
```
</TabItem>
</Tabs>

2. Go to the Pushwoosh Control Panel and [send a push notification](/product/messaging-channels/push-notifications/send-push-notifications/one-time-push).
3. You should see the notification in the app.

## Extended integration

At this stage, you have already integrated the SDK and can send and receive push notifications. Now, let’s explore the core functionality

### Push notification event listeners

In the Pushwoosh SDK there are two event listeners, designed for handling push notifications:

- `onPushReceived` event is triggered, when a push notification is received
- `onPushAccepted` event is triggered, when a user opens a notification

You should set up these event listeners right after initialization of the SDK at the application start up:

```typescript 
import { DeviceEventEmitter } from 'react-native';
import Pushwoosh from 'pushwoosh-react-native-plugin';

class PushwooshNotificationHandler {
  setupPushListeners(): void {

    DeviceEventEmitter.addListener("pushReceived", (e) => {
      console.warn("Push received: " + JSON.stringify(e));
    });

    DeviceEventEmitter.addListener("pushOpened", (e) => {
      console.warn("Push opened:" + JSON.stringify(e));
    });

  }
}
```

### User configuration

By focusing on individual user behavior and preferences, you can deliver personalized content, leading to increased user satisfaction and loyalty

```typescript
import Pushwoosh from 'pushwoosh-react-native-plugin';

class Registration {
  afterUserLogin(user: User): void {
    
    // Set user ID
    Pushwoosh.setUserId(user.getId());

    // Set user email
    Pushwoosh.setEmails(user.getEmailList());

    // Setting additional user information as tags for Pushwoosh
    Pushwoosh.setTags({
      "age": user.getAge(),
      "name": user.getName(),
      "last_login": user.getLastLoginDate()
    });
  }
}
```

### Tags

Tags are key-value pairs assigned to users or devices, allowing segmentation based on attributes like preferences or behavior, enabling targeted messaging.

```typescript
import Pushwoosh from 'pushwoosh-react-native-plugin';

class UpdateUser {
  afterUserUpdateProfile(user: User): void {

    // Set list of favorite categories
    Pushwoosh.setTags({
      "favorite_categories": user.getFavoriteCategoriesList()
    });

    // Set payment information
    Pushwoosh.setTags({
      "is_subscribed": user.isSubscribed(),
      "payment_status": user.getPaymentStatus(),
      "billing_address": user.getBillingAddress()
    });
  }
}
```

### Events

Events are specific user actions or occurrences within the app that can be tracked to analyze behavior and trigger corresponding messages or actions

```typescript
import Pushwoosh from 'pushwoosh-react-native-plugin';

class Registration {

  // Track login event
  afterUserLogin(user: User): void {
    Pushwoosh.postEvent("login", {
      "name": user.getName(),
      "last_login": user.getLastLoginDate()
    });
  }

  // Track purchase event
  afterUserPurchase(product: Product): void {
    Pushwoosh.postEvent("purchase", {
      "product_id": product.getId(),
      "product_name": product.getName(),
      "price": product.getPrice(),
      "quantity": product.getQuantity()
    });
  }
}
```

### Message delivery tracking for iOS

You must add a Notification Service Extension target to your project. This is essential for accurate delivery tracking and features like Rich Media on iOS. 

Follow the [native guide’s steps](/developer/pushwoosh-sdk/ios-sdk/setting-up-pushwoosh-ios-sdk/basic-integration-guide/#4-message-delivery-tracking) to add the extension target and the necessary Pushwoosh code within it.

### Additional plugin properties

| Property <div style="width:180px"></div> | Default <div style="width:100px"></div> | Description |
|-----------------|---------|-------------|
| **iOS properties** | | |
| `Pushwoosh_LOG_LEVEL` | `INFO` | Log level for iOS. Possible values: `NONE`, `ERROR`, `WARN`, `INFO`, `DEBUG`, `NOISE` |
| **Android properties** | | |
| `logLevel` | `INFO` | Log level for Android. One of: `NONE`, `ERROR`, `WARN`, `INFO`, `DEBUG`, `NOISE` |
| `multiNotificationMode`| `true` | Can be changed to false in case you want to display only the last notification for the user |
| `icon` | - | Path to a custom notification icon for Android |

## Troubleshooting

If you encounter any issues during the integration process, please refer to the [support and community](/developer/pushwoosh-sdk/support-and-community) section.

###### FCM registration error: Failed to retrieve token. Is firebase configured correctly?

Make sure your Firebase `googleServicesFile` property is set up in the Expo configuration file and the `google-services.json` file is added to the root directory of your project:
```json title="app.json/app.config.js"
"expo": {
  "name": "sample",
  "android": {
    "package": "com.pushwoosh.sample",
    "googleServicesFile": "./google-services.json"
  },
  "plugins": [
    [
      "pushwoosh-expo-plugin",
      {
        "mode": "development",
        "ios": {
          "PW_API_TOKEN": "__YOUR_DEVICE_API_TOKEN__"
        },
        "android": {
          "apiToken": "__YOUR_DEVICE_API_TOKEN__"
        }
      }
    ]
  ]
}
```

###### TypeError: Cannot read property 'init' of null

You might encounter the error, when attempting to run the app on a device.\
To resolve the issue, make sure you've completed the prebuild step. It generates the native code and configures the dependencies for each platform.

```bash
npx expo prebuild
```