# Push notifications

 There's a new version available!

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

Get started setting up push notifications for Android. Our Android SDK supports push notifications over FCM, including rich push messages with links and images.

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 rich 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 [Firebase Cloud Messaging (FCM)](/journeys/push-getting-started/#for-android).

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

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

1.  Set up [FCM](/journeys/push-getting-started/#for-android).
2.  [Set up push](#set-up-push).
3.  [Identify a person](/integrations/sdk/android/identify). When someone starts the app, they automatically generate a device token. Identifying the person associates the device token with the person in Customer.io, so that they can receive push notifications.
4.  Set up a campaign to send a push notification through the Customer.io composer.

## Set up push[](#set-up-push)

1.  You must implement the Push Messaging SDK to use push notification features.
    
    ```groovy
    implementation 'io.customer.android:messaging-push-fcm:3.11.1'
    ```
    
2.  Initialize the push module. The push module has an [optional config object](#push-module-config), explained below. See [deep links](#deep-links) for help configuring links.
    
    ```kotlin
     CustomerIO.Builder(
         siteId = "siteId",
         apiKey = "apiKey",
         appContext = application,
     ).apply {
         addCustomerIOModule(
             ModuleMessagingPushFCM()
         )
         autoTrackScreenViews(true)
         setRequestTimeout(8000L)
         setRegion(Region.US)
         build()
     }
    ```
    

The SDK adds a `FirebaseMessagingService` to the app manifest automatically, so you don’t have to perform additional setup to handle incoming push messages.

However, if your application implements its own `FirebaseMessagingService`, make sure that when you call `onMessageReceived` and `onNewToken` methods, you also call `CustomerIOFirebaseMessagingService.onMessageReceived` and `CustomerIOFirebaseMessagingService.onNewToken` respectively.

```kotlin
class FirebaseMessagingService : FirebaseMessagingService() {

 override fun onMessageReceived(message: RemoteMessage) {
    val handled = CustomerIOFirebaseMessagingService.onMessageReceived(context, message)
    if (handled) {
        logger.breadcrumb(this, "Push notification has been handled", null)
    }
 }
 
override fun onNewToken(token: String) {
    CustomerIOFirebaseMessagingService.onNewToken(context, token)
}
```

Push notifications launched from the SDK are currently posted to our default channel—`[your app name] Channel`. In the future, we plan to let you customize channels/categories so that users can subscribe and unsubscribe to content categories as necessary.

### Push module configuration[](#push-module-config)

`ModuleMesagingPushFCM` has an optional configuration object.

The `notificationCallback` is A callback that notifies client on push notification related actions. For now, this callback is only useful for [handling deep links](/integrations/sdk/android/rich-push/), but we have plans to add more methods in future releases. It defaults to `null`.

The `redirectDeepLinksToOtherApps` flag enables (true) or disables (false) the ability to open non app links outside the app. It is `true` by default.

*   `true`: links not supported by your app will be opened in other matching apps. If a matching app isn’t found, the host app opens to default landing page.
*   `false`: unsupported links open the host app to its default landing page.

```kotlin
CustomerIO.Builder(
    siteId = "siteId",
    apiKey = "apiKey",
    appContext = application,
).apply {
    addCustomerIOModule(
        ModuleMessagingPushFCM(
            config = MessagingPushModuleConfig.Builder().apply {
                setNotificationCallback(this)
                setRedirectDeepLinksToOtherApps(false)
            }.build()
        )
    )
    setRegion(Region.US)
    build()
}
```

### Push click behavior[](#push-click-behavior)

The `pushClickBehavior` config lets you customize your application’s response when your audience taps a push notification. This includes going to specific deep links or launcher screens based on the notification payload. Note that the SDK tracks `opened` metrics for all click behaviors.

```kotlin
builder.addCustomerIOModule(
  ModuleMessagingPushFCM(
    config = MessagingPushModuleConfig.Builder().apply {
      setPushClickBehavior(PushClickBehavior.ACTIVITY_PREVENT_RESTART)
    }.build()
  )
)
```

The available options are:

*   `ACTIVITY_PREVENT_RESTART` **(Default)**: If your app is already in the foreground, the SDK will not re-create your app when your audience clicks a push notification. Instead, the SDK will reuse the existing activity. If your app *is not* in the foreground, we’ll launch a new instance of your deep-linked activity. We recommend that you use this setting if your app has screens that your audience shouldn’t navigate away from—like a shopping cart screen.
    
*   `ACTIVITY_NO_FLAGS`: If your app is in the foreground, the SDK will re-create your app when your audience clicks a notification. The activity is added on top of the app’s existing navigation stack, so if your audience tries to go back, they will go back to where they previously were.
    
*   `RESET_TASK_STACK`: No matter what state your app is in (foreground, background, killed), the SDK will re-create your app when your audience clicks a push notification. Whether your app is in the foreground or background, the state of your app will be killed so your audience cannot go back to the previous screen if they press the back button.
    

## Capture push metrics[](#capture-push-metrics)

Customer.io supports device-side metrics that help you determine the efficacy of your push notifications: `delivered` when a push notification is received by the app and `opened` when a push notification is clicked.

By default, the `messaging-push-fcm` SDK automatically tracks `opened` and `delivered` for push notifications originating from Customer.io. Otherwise, you can track push metrics with the `trackMetric` method.

```kotlin
CustomerIO.instance().trackMetric(
    deliveryID = deliveryId,
    deviceToken = deliveryToken,
    event = MetricEvent.delivered
)
```

## Deep links[](#deep-links)

Deep links provide a way to link to a screen in your app. Our SDK supports redirects for notification links [registered in Android](https://developer.android.com/training/app-links/deep-linking) by default. You can customize this behavior using `CustomerIOPushNotificationCallback`.

*   To register a deep link, you must first add [intent filters](https://developer.android.com/training/app-links/deep-linking#adding-filters) in your `AndroidManifest.xml` file.
    
    ```xml
    <intent-filter android:label="deep_linking_filter">
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <!-- Accepts URIs that begin with "remote-habits://settings” -->
        <data
            android:host="settings"
            android:scheme="remote-habits" />
    </intent-filter>
    ```
    
*   `CustomerIOPushNotificationCallback`—a URL handler feature provided by the SDK. When configuring your `CustomerIO` instance, you can set the callback to handle notification behavior.
    
    ```kotlin
    class MainApplication : Application(), CustomerIOPushNotificationCallback {
      override fun onCreate() {
        super.onCreate()
        val builder = CustomerIO.Builder(
          siteId = "YOUR-SITE-ID",
          apiKey = "YOUR-API-KEY",
          appContext = this
        )
        builder.addCustomerIOModule(
          ModuleMessagingPushFCM(
            config = MessagingPushModuleConfig.Builder().apply {
              setNotificationCallback(this)
              setRedirectDeepLinksToOtherApps(true)
            }.build()
          )
        )
        builder.build()
      }
    
      override fun createTaskStackFromPayload(
        context: Context,
        payload: CustomerIOParsedPushPayload
      ): TaskStackBuilder? {
        // return TaskStackBuilder of your choice if you plan to handle the deep link yourself
        // and make sure to track notification metrics in the right place
        //
        // return null if you want CustomerIO SDK to do it for you
        TODO("Pass the link to your Deep link managers")
      }
    }
    ```
    

 When someone taps a push notification with a deep link, the SDK calls the `CustomerIOPushNotificationCallback` specified in `CustomerIO.Builder` object before it looks for default supported links.

The notification handler returns the [`TaskStackBuilder`](https://developer.android.com/reference/android/app/TaskStackBuilder). If the handler is not set or returns `null`, the SDK tries to open the link in your app. If your app doesn’t support the link *and* `redirectDeepLinksToOtherApps` in the `MessagingPushModuleConfig` is true, the SDK will open the link in a web browser (if a web browser app is available). By default, `redirectDeepLinksToOtherApps` is true.

 Don’t forget to capture metrics

When you provide `CustomerIOPushNotificationCallback`, don’t forget to [capture notification metrics](/integrations/sdk/android/push/#capture-push-metrics), otherwise our dashboards might not show notification conversions properly.

## Customizing Push Notifications[](#customizing-push-notifications)

You can customize the icon and color of push notifications by updating your [`AndroidManifest` as recommended by FCM](https://firebase.google.com/docs/cloud-messaging/android/client#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" />
```

However, if you want more control over your notifications’ appearance and behavior, Customer.io SDK provides an option to override these settings on the app side. You can customize notification appearance by implementing `CustomerIOPushNotificationCallback` and overriding the `onNotificationComposed` method.

```kotlin
class MainApplication : Application(), CustomerIOPushNotificationCallback {
  override fun onCreate() {
    super.onCreate()
    val builder = CustomerIO.Builder(
      siteId = "YOUR-SITE-ID",
      apiKey = "YOUR-API-KEY",
      appContext = this
    )
    builder.addCustomerIOModule(
      ModuleMessagingPushFCM(
        config = MessagingPushModuleConfig.Builder().apply {
          setNotificationCallback(this)
          setRedirectDeepLinksToOtherApps(true)
        }.build()
      )
    )
    builder.build()
  }

  override fun onNotificationComposed(
    payload: CustomerIOParsedPushPayload,
    builder: NotificationCompat.Builder
  ) {
    // Customize your notification here
  }
}
```

Customer.io SDK does not let you override `PendingIntent` for notifications. If you want to override the behavior when people tap your notifications, you can implement `createTaskStackFromPayload` as [described above in deep links](#deep-links).

## Test Rich Push[](#test-rich-push)

After you set up your push implementation, you should test it. Simply set up a push notification that includes an image and link.

This is what the payload looks like on our end. If you’ve set up your app to use other data—custom keys outside the scope of our SDK—you can use our Custom Payload Editor; you’re welcome to place custom keys inside the `message.data` object, but you’ll need to do additional development to support keys beyond our standard `title`, `body`, `link`, and `image`.

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