# Set up push notifications

 There's a new version available!

These pages cover version 1 of our SDK, but a newer version is available. In general, we suggest that you update to the latest version to take advantage of new features and fixes.

*   Are you new to our SDKs? [Check out the latest docs.](/integrations/sdk/expo/getting-started)
*   Otherwise, [learn about updating to the latest version](/integrations/sdk/expo/whats-new/)

The Expo plugin supports push notifications over APN for iOS and FCM for Android. Use this page to get started with push notification services.

This page is part of a setup flow for the SDK. Before you continue, make sure you've implemented previous features—i.e. you can't receive push notifications before you identify people!

## Before you begin[](#before-you-begin)

This page explains how to receive push notifications using our SDK. However, before you can send push notifications to your audience, you need to enable Customer.io to send push notifications through your preferred service: [Apple Push Notification Service (APNs)](/journeys/push-getting-started/#for-ios) and/or [Firebase Cloud Messaging (FCM)](/journeys/push-getting-started/#for-android).

This process lets you receive both basic push notifications in your app—a title and a message body—and rich push notifications with images and deep links.

 We do not support Expo’s Push Service

You can’t use push tokens obtained through [Expo’s Push Service](https://docs.expo.dev/push-notifications/sending-notifications/) to send push notifications through Customer.io. If your app previously used Expo’s push service, you’ll have to obtain new FCM or APN tokens to send push notifications through Customer.io.

Luckily, you won’t need to do anything to support your app’s users as you implement our SDK! If your app is able to obtain Expo push tokens, it should also be set up to receive APN or FCM device tokens. You’ll simply configure your app to [obtain an APN or FCM push token](/integrations/sdk/react-native/push/#integrate-push-notifications-in-your-app) and send that token to Customer.io using `CustomerIO.registerDeviceToken("<apn or fcm token here>")`.

### How it works[](#how-it-works)

When you use our Expo plugin, you’re already set up to support push.

Before a device can receive a push notification, you must:

1.  [Identify a person](/integrations/sdk/expo/identify/). This associates a token with the person; you can’t send push notifications to a device until you identify the recipient.
2.  (Optional) Set up your app to report push metrics back to Customer.io.

## Set up push on iOS[](#register-push)

For the most part, we’ll set up push notifications for you when you run `expo prebuild`. But before you do, you’ll need to add some additional code to support push notifications for iOS.

### Add push capabilities in Xcode[](#add-push-capabilities-in-xcode)

Before you can work with push notifications, you need to add Push Notification capabilities to your project in XCode.

1.  In your React Native project, go to the `ios` subfolder and open `<yourAppName>.xcworkspace`.
2.  Select your project, and then under *Targets*, select your main app.
3.  Click the **Signing & Capabilities** tab
4.  Click **Capability**.
5.  Add **Push Notifications** to your app.
    
    [![add push notification capabilities to your app](https://docs.customer.io/images/react-native-xcode-push.png)](#b837646bba75943a4f08d0fee059210c-lightbox)
    

When you’re done, you’ll see **Push Notifications** added to your app’s capabilities. Now you’re ready to run the `expo prebuild`.

[![this is what it looks like when you've successfully added push notifications to your app](https://docs.customer.io/images/react-native-xcode-push-added.png)](#8a72141293cedd80f2bd0345069d4f43-lightbox)

### Update iOS dependencies[](#update-ios-dependencies)

In some cases, we may make fixes in our iOS push packages that fix downstream issues in the Expo plugin. The command to update these packages depends on whether your Expo project uses a managed or bare workflow. For managed workflows, you can simply re-run the prebuild.

 Managed workflow

#### Managed workflow[](#Managed workflow)

```shell
expo prebuild --clean
# the --clean option is optional
```

 Bare workflow

#### Bare workflow[](#Bare workflow)

```shell
pod update --repo-update --project-directory=ios
```

### Rich push payloads[](#rich-push-payloads)

When you send a push notification, your app will expect the payload below; you can use the Custom Payload option in the push editor to . In the editor, you’ll select the type of device you want to send your message to: you can have separate payloads for Android and iOS.

[![The custom payload editor for a push notification](https://docs.customer.io/images/push-custom-ios.png)](#0c9b0c5b97db4dbadfe8437d8b8fe49c-lightbox)

The top level of the payload changes slightly depending on your push provider, APNS or FCM. Otherwise, your JSON is split into two major objects:

*   an `aps` object, which contains the standard aspects of a push—the `alert.title` and `alert.body` of your message—and [Apple’s push options](https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/PayloadKeyReference.html).
*   a `CIO` object containing the rich aspects of your message that the SDK will interpret. At present, it contains `link` and `image` strings.

 iOS APNs

#### iOS APNs[](#iOS APNs)

```json
{
    "aps": {
        // basic iOS message and options go here
        "mutable-content": 1,
        "alert": {
            "title": "string", //(optional) The title of the notification.
            "body": "string" //(optional) The message you want to send.
        }
    },
    "CIO": {
        "push": {
            "link": "string", //generally a deep link, i.e. my-app:://...
            "image": "string" //HTTPS URL of your image, including file extension
        }
    }
}
```

*   CIO object
    
    Contains options supported by the Customer.io SDK.
    
    *   push object
        
        Required Describes push notification options supported by the CIO SDK.
        

 iOS FCM

#### iOS FCM[](#iOS FCM)

```json
{
  "message": {
    "apns": {
      "payload": {
        "aps": {
          // basic iOS message and options go here
          "mutable-content": 1,
          "alert": {
            "title": "string", //(optional) The title of the notification.
            "body": "string" //(optional) The message you want to send.
           }
        },
        "CIO": {
          "push": {
            "link": "string", //generally a deep link, i.e. my-app://... or https://yourwebsite.com/...
            "image": "string" //HTTPS URL of your image, including file extension
          }
        }
      },
      "headers": {
        // (optional) headers to send to the Apple Push Notification Service.
        "apns-priority": 10
      }
    }
  }
}
```

*   message object
    
    Required The base object for all FCM payloads.
    
    *   apns object
        
        Required Defines a payload for iOS devices sent through Firebase Cloud Messaging (FCM).
        
        *   headers object
            
            Headers defined by [Apple’s payload reference](https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/sending_notification_requests_to_apns) that you want to pass through FCM.
            
        *   payload object
            
            Required Contains a push payload.
            
            *   CIO object
                
                Contains properties interpreted by the Customer.io iOS SDK.
                
                *   push object
                    
                    Required A push payload for the iOS SDK.
                    
            *   *Custom key-value pairs\** any type
                
                Additional properties that you've set up your app to interpret outside of the Customer.io SDK.
                

### Sound in push notifications (iOS Only)[](#sound-in-push-notifications)

When you send a push notification to iOS devices that uses our SDK, you can opt to send the *Default* system sound or no sound at all. If your audience’s phone is set to vibrate, or they’ve disabled sound permissions for your app, the *Default* setting will cause the device to vibrate rather than playing a sound.

In most cases, you should use the *Default* sound setting to make sure your audience hears (or feels) your message. But, before you send sound, you should understand:

1.  Your app needs permission from your users to play sounds. This is done by your app, not our SDKs. [Here’s an example from our iOS sample app](https://github.com/customerio/customerio-ios/blob/main/Apps/APN-UIKit/APN%20UIKit/Util/NotificationUtil.swift#L12-L13) showing how to request sound permissions.
2.  iOS users can go into *System Settings* and disable sound permissions for your app. Enabling the *Default* setting doesn’t guarantee that your audience hears a sound when your message is delivered!

 We don’t support custom sounds yet

If you want to send a custom sound, you’ll need to handle it on your own, outside the SDK and use a custom payload when you set up your push notifications.

## Prompt users to opt-into push notifications[](#prompt-users-to-opt-into-push-notifications)

Your audience has to opt into push notifications. To display the native iOS and Android push notification permission prompt, you’ll use the `CustomerIO.showPromptForPushNotifications` method (available only in `customerio-reactnative` version `>=2.2.0`).

You can configure push notifications to request authorization for sounds and badges as well (only on iOS). If a user opts into push notifications, the `CustomerIO.showPromptForPushNotifications` method will return `Granted`, otherwise it returns `Denied` as a `string`. If the user already responded to the push authorization prompt, the current authorization status is returned as a string.

```javascript
var options = {"ios" : {"sound" : true, "badge" : true}}
CustomerIO.showPromptForPushNotifications(options).then(status => {
  switch(status) {
    case "Granted":
     // Push permission is granted, your app can now receive push notifications
      break;
    case "Denied":
      // App is not authorized to receive push notifications
      // You might need to explain users why your app needs permission to receive push notifications
      break;
    case "NotDetermined":
      // Push permission status is not determined (Only for iOS)
      break;
  }
}).catch(error => {
  // Failed to show push permission prompt
  console.log(error)
})
```

### Get a user’s permission status[](#get-a-users-permission-status)

To get a user’s current permission status, call the `CustomerIO.getPushPermissionStatus()` method. This returns a promise with the current status as a string.

```javascript
CustomerIO.getPushPermissionStatus().then(status => {
  console.log("Push permission status is - " + status)
})
```

## Test your implementation[](#test-rich-push)

Before you release your app, you should test your implementation. Use the payloads below to send a push in the Customer.io web app with a [Custom Payload](/journeys/push-custom-payloads/#getting-started-with-custom-payloads).

In both of the test payloads below, you should:

*   Set the `link` to the deep link URL that you want to open when your tester taps your notification.
*   Set the `image` to the URL of an image you want to show in your notification. It’s important that the image URL starts with `https://` and *not* `http://` or the image might not show up.

 APNs test payload

#### APNs test payload[](#APNs test payload)

```json
{
    "CIO": {
        "push": {
            "link": "remote-habits://deep?message=hello&message2=world",
            "image": "https://thumbs.dreamstime.com/b/bee-flower-27533578.jpg"
        }
    },
    "aps": {
        "mutable-content": 1,
        "alert": {
            "title": "Title of your push goes here!",
            "body": "Body of your push goes here!"
        }
    }
}
```

 FCM test payload

#### FCM test payload[](#FCM test payload)

```json
{
    "message": {
        "apns": {
            "payload": {
                "CIO": {
                    "push": {
                        "link": "remote-habits://deep?message=hello&message2=world",
                        "image": "https://thumbs.dreamstime.com/b/bee-flower-27533578.jpg"
                    }
                },
                "aps": {
                    "mutable-content": 1,
                    "alert": {
                        "title": "Title of your push goes here!",
                        "body": "Body of your push goes here!"
                    }
                }
            }
        }
    }
}
```