# Set up push notifications

 There's a new version available!

These pages cover version 4 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/react-native/getting-started)
*   Otherwise, [learn about updating to the latest version](/integrations/sdk/react-native/whats-new/)

Our React Native SDK supports push notifications over APN or FCM—including rich push messages with links and images. Use this page to add support for your push provider and set your app up to receive push notifications.

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

Under the hood, our React Native SDK takes advantage of our native Android and iOS SDKs. This helps us keep the React Native SDK up to date. But, for now, it also means you’ll need to add a *bit* of code to support your iOS users. For Android, you’re ready to go if you followed our [getting started instructions](/integrations/sdk/react-native/getting-started/#install).

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

1.  (iOS) [Add push notification capabilities in XCode](#add-push-capabilities-in-xcode).
2.  (iOS) [Integrate push notifications](#register-push): code samples on this page help you do that.
3.  [Identify a person](/integrations/sdk/react-native/identify/). This associates a token with the person; you can’t send push notifications to a device until you identify the recipient.
4.  [Request, or check for, push notification permissions](#prompt-users-for-to-opt-into-push-notifications). If your app’s user doesn’t grant permission, notifications will not appear in the system tray.

While push providers support a number of features in their payloads, **our React Native package only supports deep links and images right now**. If you want to include action buttons or other rich push features, you need to add your own custom code. When writing your own custom code, we recommend that you use our SDK as it is much easier to extend than writing your own code from scratch.

 Did you already set up your push providers?

To send, test, and receive push notifications, you’ll need to set up your push notification service(s) in Customer.io. If you haven’t already, set up [Apple Push Notification Service (APNs)](/journeys/push-getting-started/#for-ios) and/or [Firebase Cloud Messaging (FCM)](/push-getting-started/#for-android).

## Set up push on Android[](#register-push-android)

If you followed our [Getting Started instructions](/integrations/sdk/react-native/quick-start-guide/#install), you’re already set up to send standard push notifications to Android devices.

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

You’ll need to add some additional code to support push notifications for iOS. You’ll need to add push capabilities in XCode and integrate push capabilities in your app.

### 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. When you’re done, you’ll see **Push Notifications** added to your app’s capabilities, but there are still a few more steps to finish setting things up.
    
    [![add push notification capabilities to your app](https://docs.customer.io/images/react-native-xcode-push.png)](#b837646bba75943a4f08d0fee059210c-lightbox)
    
6.  Go to **File** > **New** > **Target**.
    
    [![xcode-servicenotification1.png](https://docs.customer.io/images/xcode-servicenotification1.png)](#64d64173bde7b46bad5fc1f14cc8f36a-lightbox)
    
7.  Select **Notification Service Extension** and click **Next**.
    
    [![xcode-servicenotification2.png](https://docs.customer.io/images/xcode-servicenotification2.png)](#6413f7694da0358105aca5a02cf835dc-lightbox)
    
8.  Enter a product name, like *NotificationServiceExtension* (which we use in our examples on this page) and **set the *Language* to *Swift* or *Objective C* based on the language you use for native iOS files.** Click **Finish**.
    
    [![xcode-servicenotification3.png](https://docs.customer.io/images/xcode-servicenotification3.png)](#97f7eea0f5f268a29a24b1bdea3c767c-lightbox)
    
9.  When presented with the dialog below, click **Cancel**. This helps Xcode continue debugging your app and not just the extension you just added.
    
    [![xcode-servicenotification4.png](https://docs.customer.io/images/xcode-servicenotification4.png)](#7a87192ad7f0dc9047625d6dfc407e77-lightbox)
    

Now you have another target in your project navigator named `NotificationServiceExtension`. We’ll configure this extension when we [Integrate Push Notifications](#integrate-push-capabilities-in-your-app) in the following section.

### Integrate push capabilities in your app[](#integrate-push-capabilities-in-your-app)

Pick your push provider (*APN* or *FCM*) and the language your native files are written in to get started (*Objective C* or *Swift*).

#### APN/Objective-C[](#APN/Objective-C)

1.  Open your `ios/Podfile` and add the Customer.io push dependency, highlighted here, to both your main target and `NotificationServiceExtension` target.
    
    ```ruby
    target 'SampleApp' do # Look for the main app target. 
      # Make all file modifications after this line:
      config = use_native_modules!
    
      # Add the following line to add the Customer.io native dependency: 
      pod 'customerio-reactnative/apn', :path => '../node_modules/customerio-reactnative'
    end 
    
    # Next, copy and paste the code below to the bottom of your Podfile: 
    target 'NotificationServiceExtension' do
      # Notice the '-richpush' in the line below. This line of code is different from what you added for your main target. 
      pod 'customerio-reactnative-richpush/apn', :path => '../node_modules/customerio-reactnative'
    end
    ```
    
2.  Open your terminal, go to your project path and install the pods.
    
    ```bash
      pod install --project-directory=ios
    ```
    
3.  Open `ios/<YourAppName>.xcworkspace` in Xcode, and add a new Swift file to your project.
    
    Copy the code here into your file. We’re calling our file `MyAppPushNotificationsHandler.swift` and the associated class `MyAppPushNotificationsHandler`, but you might want to rename things to fit your app.
    
    ```swift
    import Foundation
    import CioMessagingPushAPN
    
    @objc
    public class MyAppPushNotificationsHandler : NSObject {
    
      public override init() {}
    
      @objc(setupCustomerIOClickHandling)
      public func setupCustomerIOClickHandling() {
        // This line of code is required in order for the Customer.io SDK to handle push notification click events.
        // Initialize MessagingPushAPN module to automatically handle push notifications that originate from Customer.io
        MessagingPushAPN.initialize(withConfig: MessagingPushConfigBuilder().build())
      }
    
      @objc(application:deviceToken:)
      public func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        // Register device to receive push notifications with device token
        MessagingPush.shared.application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken)
      }
    
      @objc(application:error:)
      public func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        MessagingPush.shared.application(application, didFailToRegisterForRemoteNotificationsWithError: error)
      }
    }
    ```
    
4.  Open your `ios/AppDelegate.mm` file and import your header file. The name of the header file will depend on your app’s main target name i.e. `YourMainTargetName-Swift.h` and is auto-created by Xcode.
    
    If you’re not a native iOS developer, the `.h` and `.mm` files represent interface and implementation respectively. It’s a convention of XCode to keep these files separate.
    
    ```obj-c
    #import "SampleApp-Swift.h"
    ```
    
5.  Inside AppDelegate’s `@implementation`, create an object of `MyAppPushNotificationsHandler` (remember to substitute the name of your handler).
    
    ```obj-c
    @implementation AppDelegate
    
    MyAppPushNotificationsHandler* pnHandlerObj = [[MyAppPushNotificationsHandler alloc] init];
    ```
    
6.  Update `AppDelegate.mm` to register a device to the current app user and handle push notifications.
    
    ```obj-c
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
      RCTAppSetupPrepareApp(application, true);
    
      NSMutableDictionary *modifiedLaunchOptions = [NSMutableDictionary dictionaryWithDictionary:launchOptions];
        if (launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]) {
            NSDictionary *pushContent = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey];
            if (pushContent[@"CIO"] && pushContent[@"CIO"][@"push"] && pushContent[@"CIO"][@"push"][@"link"]) {
              NSString *initialURL = pushContent[@"CIO"][@"push"][@"link"];
                if (!launchOptions[UIApplicationLaunchOptionsURLKey]) {
                    modifiedLaunchOptions[UIApplicationLaunchOptionsURLKey] = [NSURL URLWithString:initialURL];
                }
            }
        }
    
      RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:modifiedLaunchOptions];
    
    #if RCT_NEW_ARCH_ENABLED
      _contextContainer = std::make_shared<facebook::react::ContextContainer const>();
      _reactNativeConfig = std::make_shared<facebook::react::EmptyReactNativeConfig const>();
      _contextContainer->insert("ReactNativeConfig", _reactNativeConfig);
      _bridgeAdapter = [[RCTSurfacePresenterBridgeAdapter alloc] initWithBridge:bridge contextContainer:_contextContainer];
      bridge.surfacePresenter = _bridgeAdapter.surfacePresenter;
    #endif
    
      NSDictionary *initProps = [self prepareInitialProps];
      UIView *rootView = RCTAppSetupDefaultRootView(bridge, @"SampleApp", initProps, true);
    
      [application registerForRemoteNotifications];
    
      self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
      UIViewController *rootViewController = [UIViewController new];
      rootViewController.view = rootView;
      self.window.rootViewController = rootViewController;
      [self.window makeKeyAndVisible];
      
      [pnHandlerObj setupCustomerIOClickHandling];
    
      [RNNotifications startMonitorNotifications];
    
      return YES;
    }
    
    ...
    
    // Required to register device token.
    - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
    {
      // Register device to receive push notifications with device token
      [pnHandlerObj application:application deviceToken:deviceToken];
    }
    
    // Required for the registration error event.
    - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
    {
      [pnHandlerObj application:application error:error];
    }
    ```
    
7.  In XCode, select your `NotificationServiceExtension`. Go to **File** > **New** > **File** > **Swift File** and click **Next**. Enter a file name, like `NotificationServicePushHandler`, and click **Create**. This adds a new swift file in your extension target.
    
    Copy the code on the right and paste it into this new file (which we’ve called `NotificationServicePushHandler.swift`) file—replacing everything in the file and update `Env.cdpApiKey` with your CDP API key.
    
    ```swift
    import CioMessagingPushAPN
    import Foundation
    import UserNotifications
    
    @objc
    public class NotificationServicePushHandler: NSObject {
    
      public override init() {}
    
      @objc(didReceive:withContentHandler:)
      public func didReceive(
        _ request: UNNotificationRequest,
        withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void
      ) {
        MessagingPushAPN.initializeForExtension(
          withConfig: MessagingPushConfigBuilder(cdpApiKey: Env.cdpApiKey)
            // Optional: specify region where your Customer.io account is located (.US or .EU). Default: US
            //.region(.US)
            .build()
        )
    
        MessagingPush.shared.didReceive(request, withContentHandler: contentHandler)
      }
    
      @objc(serviceExtensionTimeWillExpire)
      public func serviceExtensionTimeWillExpire() {
        MessagingPush.shared.serviceExtensionTimeWillExpire()
      }
    }
    ```
    
8.  Open your `NotificationService.m` file and copy the highlighted lines (beginning on line 2) into your file. The name of the header file on line 2 will depend on your extension’s name i.e. `YourNotificationServiceExtensionName-Swift.h` and is automatically created by Xcode.
    
    After this, you can run your app on a physical device and send yourself a push notification with images and deep links to test your implementation. You’ll have to use a physical device because simulators can’t receive push notifications.
    
    ```swift
    #import "NotificationService.h"
    #import "NotificationServiceExtension-Swift.h"
    
    @interface NotificationService ()
    
    @end
    
    @implementation NotificationService
    
    // Create object of class NotificationServicePushHandler
    NotificationServicePushHandler* nsHandlerObj = nil;
    
    // Initialize the object
    + (void)initialize{
      nsHandlerObj = [[NotificationServicePushHandler alloc] init];
    }
    
    - (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
      [nsHandlerObj didReceive:request 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.
      [nsHandlerObj serviceExtensionTimeWillExpire];
    }
    
    @end
    ```
    

#### APN/Swift[](#APN/Swift)

1.  Open your `ios/Podfile` and add the Customer.io push dependency, highlighted here, to both your main target and `NotificationServiceExtension` target.
    
    ```ruby
    target 'SampleApp' do # Look for the main app target. 
      # Make all file modifications after this line:
      config = use_native_modules!
    
      # Add the following line to add the Customer.io native dependency: 
      pod 'customerio-reactnative/apn', :path => '../node_modules/customerio-reactnative'
    end 
    
    # Next, copy and paste the code below to the bottom of your Podfile: 
    target 'NotificationServiceExtension' do
      # Notice the '-richpush' in the line below. This line of code is different from what you added for your main target. 
      pod 'customerio-reactnative-richpush/apn', :path => '../node_modules/customerio-reactnative'
    end
    ```
    
2.  Open your terminal, go to your project path and install the pods.
    
    ```bash
    pod install --project-directory=ios
    ```
    
3.  In your iOS subfolder, update your `AppDelegate.swift` file to use the Customer.io wrapper class that handles push notifications automatically. This approach replaces the need to manually implement push notification delegate methods.
    
    ```swift
    import UIKit
    import CioMessagingPushAPN
    import UserNotifications
    
    @main
    class AppDelegateWithCioIntegration: CioAppDelegateWrapper<AppDelegate> {}
    
    class AppDelegate: NSObject, UIApplicationDelegate {
      func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
      ) -> Bool {
        ...
    
        // Optional: add if you need UNUserNotificationCenterDelegate methods
        UNUserNotificationCenter.current().delegate = self
        
        // Initialize the Customer.io SDK for push notifications
        MessagingPushAPN.initialize(withConfig: MessagingPushConfigBuilder().build())
    
        return true
      }
    }
    
    extension AppDelegate: UNUserNotificationCenterDelegate {
       // Optional: add this method if you want more control over notifications when your app is in the foreground
       func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
           completionHandler([.banner, .list, .badge, .sound])
       }
    }
    ```
    
4.  Add a notification service extension to call the appropriate Customer.io functions. This lets your app display rich push notifications, including images, etc.
    
    See [Deep Links](/integrations/sdk/react-native/push-notifications/deep-links/) if you want to support deep links from push notifications.
    
    ```swift
    import CioMessagingPushAPN
    import Foundation
    import UserNotifications
    
    class NotificationService: UNNotificationServiceExtension {
    
      override func didReceive(
        _ request: UNNotificationRequest,
        withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void
      ) {
        MessagingPushAPN.initializeForExtension(
          withConfig: MessagingPushConfigBuilder(cdpApiKey: Env.cdpApiKey)
            // Optional: specify region where your Customer.io account is located (.US or .EU). Default: US
            //.region(.US)
            .build()
        )
    
        MessagingPush.shared.didReceive(request, withContentHandler: contentHandler)
      }
    
      override func serviceExtensionTimeWillExpire() {
        // Called just before the extension is 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.
        MessagingPush.shared.serviceExtensionTimeWillExpire()
      }
    }
    ```
    

#### FCM/Objective-C[](#FCM/Objective-C)

1.  Open your `ios/Podfile` and add the Customer.io push dependency, highlighted here, to both your main target and `NotificationServiceExtension` target.
    
    ```ruby
    # Note: You may need to add this line, as required by FCM, to the top of your Podfile if you encounter errors during 'pod install'
    use_frameworks! :linkage => :static
    
    target 'YourApp' do # Look for the main app target. 
      # Make all file modifications after this line:
      config = use_native_modules!
    
      # Add the following line to add the Customer.io native dependency: 
      pod 'customerio-reactnative/fcm', :path => '../node_modules/customerio-reactnative'
    end 
    
    # Next, copy and paste the code below to the bottom of your Podfile: 
    target 'NotificationServiceExtension' do
      # Notice the '-richpush' in the line below. This line of code is different from what you added for your main target. 
      pod 'customerio-reactnative-richpush/fcm', :path => '../node_modules/customerio-reactnative'
    end
    ```
    
2.  Open your terminal, go to your project path and install the pods.
    
    ```bash
      pod install --project-directory=ios
    ```
    
3.  Open `ios/<YourAppName>.xcworkspace` in Xcode, and add a new Swift file to your project.
    
    Copy the code here into your file. We’re calling our file `MyAppPushNotificationsHandler.swift` and the associated class `MyAppPushNotificationsHandler`, but you might want to rename things to fit your app.
    
    ```swift
    import CioMessagingPushFCM
    import FirebaseMessaging
    import Foundation
    
    @objc
    public class MyAppPushNotificationsHandler: NSObject {
    
      public override init() {}
    
      @objc(setupCustomerIOClickHandling)
      public func setupCustomerIOClickHandling() {
        // Initialize MessagingPushFCM module to automatically handle your app’s push notifications that originate from Customer.io
        MessagingPushFCM.initialize(withConfig: MessagingPushConfigBuilder().build())
      }
    
      @objc(didReceiveRegistrationToken:fcmToken:)
      public func didReceiveRegistrationToken(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
        // Register device on receiving a device token (FCM)
        MessagingPush.shared.messaging(messaging, didReceiveRegistrationToken: fcmToken)
      }
    }
    ```
    
4.  Open `AppDelegate.h` and add the `FIRMessagingDelegate` import statement.
    
    If you’re not a native Objective-C developer, the `.h` and `.mm` files represent interface and implementation respectively. It’s a convention of XCode to keep these files separate.
    
    ```obj-c
    #import <RCTAppDelegate.h>
    #import <UIKit/UIKit.h>
    #import <FirebaseMessaging/FIRMessaging.h>
    
    @interface AppDelegate : RCTAppDelegate <FIRMessagingDelegate>
    
    @end
    ```
    
5.  Open your `ios/AppDelegate.mm` file and import your header file, as we’ve shown on line 2 and also import `FirebaseCore` as we’ve shown on line 5. The name of the header file will depend on your app’s main target name i.e. `YourMainTargetName-Swift.h` and is auto-created by Xcode.
    
    ```obj-c
    #import "AppDelegate.h"
    #import <FCMSampleApp-Swift.h>
    #import <React/RCTLinkingManager.h>
    #import <React/RCTBundleURLProvider.h>
    #import <FirebaseCore.h>
    ```
    
6.  In your `AppDelegate.mm` file, create an object of your push notification handler. We called ours `MyAppPushNotificationsHandler`.
    
    ```obj-c
    @implementation AppDelegate
    
    // Create Object of class MyAppPushNotificationsHandler
    MyAppPushNotificationsHandler *pnHandlerObj = [[MyAppPushNotificationsHandler alloc] init];
    ```
    
7.  Update `AppDelegate.mm` to configure Firebase and handle tokens. We’ve highlighted the code here to show what you need to add.
    
    ```obj-c
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
      self.moduleName = @"FCMSampleApp";
      // You can add your custom initial props in the dictionary below.
      // They will be passed down to the ViewController used by React Native.
      self.initialProps = @{};
    
      // Configure Firebase
      [FIRApp configure];
    
      // Set FCM messaging delegate
      [FIRMessaging messaging].delegate = self;
    
      // Use modifiedLaunchOptions for passing link to React Native bridge to sends users to the specified screen
      NSMutableDictionary *modifiedLaunchOptions = [NSMutableDictionary dictionaryWithDictionary:launchOptions];
      if (launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]) {
        NSDictionary *pushContent = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey];
        if (pushContent[@"CIO"] && pushContent[@"CIO"][@"push"] && pushContent[@"CIO"][@"push"][@"link"]) {
          NSString *initialURL = pushContent[@"CIO"][@"push"][@"link"];
          if (!launchOptions[UIApplicationLaunchOptionsURLKey]) {
            modifiedLaunchOptions[UIApplicationLaunchOptionsURLKey] = [NSURL URLWithString:initialURL];
          }
        }
      }
      
      [pnHandlerObj setupCustomerIOClickHandling];
    
      return [super application:application didFinishLaunchingWithOptions:modifiedLaunchOptions];
    }
    
    ...
    
    @end
    ```
    
8.  In XCode, select your `NotificationServiceExtension`. Go to **File** > **New** > **File** > **Swift File** and click **Next**. Enter a file name, like `NotificationServicePushHandler`, and click **Create**. This adds a new swift file in your extension target.
    
    Copy this code into the new file and replace `Env.cdpApiKey` with your CDP API key.
    
    ```swift
    import CioMessagingPushFCM
    import Foundation
    import UserNotifications
    
    @objc
    public class MyAppNotificationServicePushHandler: NSObject {
    
      public override init() {}
    
      @objc(didReceive:withContentHandler:)
      public func didReceive(
        _ request: UNNotificationRequest,
        withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void
      ) {
        MessagingPushFCM.initializeForExtension(
          withConfig: MessagingPushConfigBuilder(cdpApiKey: Env.cdpApiKey)
            // Optional: specify region where your Customer.io account is located (.US or .EU). Default: US
            //.region(.US)
            .build()
        )
    
        MessagingPush.shared.didReceive(request, withContentHandler: contentHandler)
      }
    
      @objc(serviceExtensionTimeWillExpire)
      public func serviceExtensionTimeWillExpire() {
        MessagingPush.shared.serviceExtensionTimeWillExpire()
      }
    }
    ```
    
9.  In your `NotificationService.m` file, import the auto-generated header file—e.g. `NotificationServiceExtension-Swift.h`. You’ll also need to create an object class of `MyAppNotificationServicePushHandler` and call the functions in the code sample here.
    
    Now you can run your app on a physical device and send yourself a push notification with images and deep links to test your implementation. You’ll have to use a physical device because simulators can’t receive push notifications.
    
    ```obj-c
    #import <NotificationServiceExtension-Swift.h>
    #import "NotificationService.h"
    
    @interface NotificationService ()
    
    @end
    
    @implementation NotificationService
    
    // Create object of class MyAppNotificationServicePushHandler
    MyAppNotificationServicePushHandler* nsHandlerObj = nil;
    
    // Initialize the object
    + (void)initialize {
      nsHandlerObj = [[MyAppNotificationServicePushHandler alloc] init];
    }
    
    - (void)didReceiveNotificationRequest:(UNNotificationRequest*)request withContentHandler:(void (^)(UNNotificationContent* _Nonnull))contentHandler {
      [nsHandlerObj didReceive:request withContentHandler:contentHandler];
    }
    
    - (void)serviceExtensionTimeWillExpire {
      [nsHandlerObj serviceExtensionTimeWillExpire];
    }
    
    @end
    ```
    

#### FCM/Swift[](#FCM/Swift)

1.  Open your `ios/Podfile` and add the Customer.io push dependency, highlighted here, to both your main target and `NotificationServiceExtension` target.
    
    ```ruby
    # Note: You may need to add this line, as required by FCM, to the top of your Podfile if you encounter errors during 'pod install'
    use_frameworks! :linkage => :static
    
    target 'YourApp' do # Look for the main app target. 
      # Make all file modifications after this line:
      config = use_native_modules!
    
      # Add the following line to add the Customer.io native dependency: 
      pod 'customerio-reactnative/fcm', :path => '../node_modules/customerio-reactnative'
    end 
    
    # Next, copy and paste the code below to the bottom of your Podfile: 
    target 'NotificationServiceExtension' do
      # Notice the '-richpush' in the line below. This line of code is different from what you added for your main target. 
      pod 'customerio-reactnative-richpush/fcm', :path => '../node_modules/customerio-reactnative'
    end
    ```
    
2.  Open your terminal, go to your project path and install the pods.
    
    When complete, you should see `Pod installation complete!`
    
    ```bash
    pod install --project-directory=ios
    ```
    
3.  Update your `AppDelegate.swift` file to handle push notifications. You can copy the code sample on the right, but you may need to update imports and other things to fit your app.
    
    ```swift
    import UIKit
    import CioMessagingPushFCM
    import UserNotifications
    import Firebase
    import FirebaseMessaging
    
    @main
    class AppDelegateWithCioIntegration: CioAppDelegateWrapper<AppDelegate> {}
    
    class AppDelegate: NSObject, UIApplicationDelegate {
      func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
      ) -> Bool {
    
        ...
    
        // Configure Firebase
        FirebaseApp.configure()
    
        // Optional: Set FCM messaging delegate if you need it. The Customer.io SDK will automatically read FCM tokens
        Messaging.messaging().delegate = self
    
        // Initialize MessagingPushFCM module to automatically handle your app's push notifications that originate from Customer.io
        MessagingPushFCM.initialize(withConfig: MessagingPushConfigBuilder().build())
    
        return true
      }
    
      func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
          // This is required for FCM. The Customer.io SDK does not make changes to other SDKs
          Messaging.messaging().apnsToken = deviceToken
      }
    }
    
    extension AppDelegate: UNUserNotificationCenterDelegate {
       // Optional: add this method if you want fine-grained control over presenting Notifications in foreground
       func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
           completionHandler([.banner, .list, .badge, .sound])
       }
    }
    
     extension AppDelegate: MessagingDelegate {
        // Optional: add this method if you need access to `fcmToken` - Customer.io SDK will read this automatically
        func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
            
        }
    }
    ```
    
4.  Add a notification service extension to call the appropriate Customer.io functions. This lets your app display rich push notifications, including images, etc.
    
    See [Deep Links](/integrations/sdk/react-native/push-notifications/deep-links/) if you want to support deep links from push notifications.
    
    ```swift
    import CioMessagingPushFCM
    import Foundation
    import UserNotifications
    
    class NotificationService: UNNotificationServiceExtension {
    
      override func didReceive(
        _ request: UNNotificationRequest,
        withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void
      ) {
        MessagingPushFCM.initializeForExtension(
          withConfig: MessagingPushConfigBuilder(cdpApiKey: Env.cdpApiKey)
            // Optional: specify region where your Customer.io account is located (.US or .EU). Default: US
            //.region(.US)
            .build()
        )
    
        MessagingPush.shared.didReceive(request, withContentHandler: contentHandler)
      }
    
      override func serviceExtensionTimeWillExpire() {
        // Called just before the extension is 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.
        MessagingPush.shared.serviceExtensionTimeWillExpire()
      }
    }
    ```
    

### 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.

## Push icon (Android)[](#push-icon-android)

You’ll set the icon that appears on normal push notifications as a part of your app manifest—`android/app/src/main/AndroidManifest.xml`. If your icon appears in the wrong size, or if you want to change the standard icon that appears with your push notifications, you’ll need to update your app’s manifest.

```xml
<meta-data
    android:name="com.google.firebase.messaging.default_notification_icon"
    android:resource="@drawable/ic_notification" />
<meta-data
    android:name="com.google.firebase.messaging.default_notification_color"
    android:resource="@color/colorNotificationIcon" />
```

## 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.

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 has not yet been asked to opt into notifications, the method will return `NotDetermined` (only for iOS).

```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)
})
```

### Optional: Remove `POST_NOTIFICATIONS` permission from Android apps[](#optional-remove-post_notifications-permission-from-android-apps)

By default, the SDK includes the `POST_NOTIFICATIONS` permission which is [required by Android 13 to show notifications on Android device](https://developer.android.com/develop/ui/views/notifications/notification-permission). However, if you do not want to include the permission because don’t use notifications, or for any other reason, you can remove the permission by adding the following line to your `android/app/src/main/AndroidManifest.xml` file:

```xml
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" tools:node="remove"/>
```

## Fetch the current device token[](#fetch-the-current-device-token)

You can fetch the currently stored device token using the `CustomerIO.pushMessaging.getRegisteredDeviceToken()` method. This method returns an APN/FCM token in a promise as a string.

```javascript
   let token = await CustomerIO.pushMessaging.getRegisteredDeviceToken()
   if (token) {
    // Use the token as required in your app for example save in a state
        setDeviceToken(token);
   }
```

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

After you set up rich push, you should test your implementation. Below, we show the payload structure we use for iOS and Android. In general, you can use our regular rich push editor; it’s set up to send messages using the JSON structure we outline below.

If you want to fashion your own payload, you can use our [custom payload](/journeys/push-custom-payloads/#getting-started-with-custom-payloads).

[![the rich push editor](https://docs.customer.io/images/push-preview.png)](#4e089ac68a22d5b994db09266a531737-lightbox)

  

 iOS APNs payload

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

```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 payload

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

```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.
                

 Android payload

#### Android payload[](#Android payload)

```json
{
  "message": {
    "data": {
      "title": "string", //(optional) The title of the notification.
      "body": "string", //The message you want to send.
      "image": "string", //https URL to an image you want to include in the notification
      "link": "string" //Deep link in the format remote-habits://deep?message=hello&message2=world
    }
  }
}
```

*   message 
    
    Required The parent object for all push payloads.
    
    *   android object
        
        Contains properties that are **not** interpreted by the SDK but are defined by FCM. You need to write your own code to handle these Android push features.
        
    *   data object
        
        Required Contains all properties interpreted by the SDK.
        
    
    *   android object
        
        Contains properties that are **not** interpreted by the SDK but are defined by FCM. You need to write your own code to handle these Android push features.
        
    *   data object
        
        Contains the `link` property (interpreted by the SDK) and additional properties that you want to pass to your app.
        
    *   notification object
        
        Required Contains properties interpreted by the SDK except for the `link`.