Push Notifications - Custom Code Payloads
We’ve covered how to get started with Customer.io Push, but if you want to customize your push notifications even further and add things like deep links or images, custom payloads are the answer!
Getting started with custom payloads
Creating a custom payload for your push notification gives you granular control over the notiification and its behaviour and appearance, in the same way as coding your email(s) in HTML does. It’s a bit more complex, but you can use it to add images, deep links, or interactions.
To access the custom payload editor, use this toggle:


You can then write or paste your custom code into the editor. Note there are different tabs for Android and iOS so that you can send custom code for each platform separately but, if you are using Firebase Cloud Messaging, you can just use the Android tab to send custom code that will be used for both Android and iOS.
Guidelines
First and foremost, identify what you’ll be doing with your custom payload: do you want to send people to a deep link in your app or show them an image? Next, make sure that your app supports that functionality. Many of these features require custom app development.
- If it does, your engineering team should be able to provide the JSON code for you.
- If it doesn’t, reach out to your engineering team and ask what your payload should be.
All apps are unique, there are many ways your custom code could be structured. Talk to your app developers to understand the payload you should send.
Once you have your payload, you’ll need to ensure that:
- Your JSON code is valid.
- The code you use follows the guidelines for the specific provider:
- Apple Push Notification Service (APNS - iOS notifications)
- Firebase Cloud Messaging (FCM - Android and iOS notifications)
Basic Example: Android (and iOS via FCM)
Here’s the most basic example of a custom payload for sending to Android and iOS devices via Firebase Cloud Messaging:
{
"message": {
"notification": {
"body": "YOUR MESSAGE BODY HERE",
"title": "YOUR MESSAGE TITLE HERE"
}
}
}
Sending iOS-specific fields via FCM
Basic Example: iOS (when sending via APNS)
And here’s the most basic example of a custom payload for sending to iOS devices via Apple Push Notification Service:
{
"aps": {
"alert": {
"body": "YOUR MESSAGE BODY HERE",
"title": "YOUR MESSAGE TITLE HERE"
}
}
}
Using liquid in push notifications
As always, you can use customer or event data in your custom payload. While you can technically use liquid in any string field, you probably want to limit liquid to body
, title
, and subtitle
(on iOS) fields.
Here’s a basic Android (and iOS via FCM) example using customer and event data:
{
"message": {
"notification": {
"body": "Hi {{customer.first_name}}, your {{event.event_title}} has been booked!",
"title": "All set!"
}
}
}
And the same in iOS (when sending via APNS):
{
"aps": {
"alert": {
"body": "Hi {{customer.first_name}}, your {{event.event_title}} has been booked!",
"title": "All set!"
}
}
}
This would result in a push notification that looks like this (on iOS):
Custom push payload reference
While you can send push notifications to both iOS and Android devices using FCM, if you want to provide a custom payload, you must provide separate payloads for your iOS and Android audiences.
If your custom payload does not match the shape below, or you provide an incorrect data type for a key, your notification may fail.
Check your iOS notification setup
Android custom push payload
If you want to send a message, your push notification must include a message.notification
object with a body
, reflecting the message you want to send. You can pass additional options for the android push in the meassage.android.notification
object.
The message.data
object contains custom data that your app to interprets. Custom data isn’t supported natively; things like custom image handling and deep linking require additional development. Talk to your app’s developer(s) to understand the custom data that you can pass to your app. If you want to send a silent, custom data-only push, you can omit the message.notification
object and send a data key instead.
The following shows the shape of an Android custom push payload; you’ll find a deeper explanation of the keys allowed in this payload below.
{
"message": {
"notification": {
"title": "string", //(optional) The title of the notification.
"body": "string" //(optional) The message you want to send.
},
"data": {
//Optional key-value pairs that your app interprets.
//We don't validate the keys or values you provide.
},
"android": {
"notification": {
//(Optional) Contains options specific to an android notification.
"icon": "string",
"sound": "string",
"tag": "string",
"color": "#rrggbb",
"click_action": "string",
"body_loc_key": "string",
"body_loc_args": "stringified,array",
"title_loc_key": "string",
"title_loc_args": "stringified,array"
}
}
}
}
Key | Type | Description |
---|---|---|
message.notification object | ||
title |
Optional, string |
The notification's title. |
body |
Optional, string |
The notification's body text. |
message.data object | ||
Custom keys | Optional, any type | Custom key-value pairs that your app will interpret. We don't validate the keys or data you provide. Customer.io and FCM assume that your app understands how to interpret this data. |
message.android.notification object —Android notification options | ||
icon |
Optional, string |
Sets the notification icon to |
sound |
Optional, string |
The sound that plays when the device receives the notification. Supports |
tag |
Optional, string |
Identifier to replace existing notifications in the notification drawer. If empty, each request creates a new notification. If you specify a tag, and a notification with the same tag is already being shown, the new notification replaces the existing one in the notification drawer. |
color |
Optional, string |
The notification's icon color, in |
click_action |
Optional, string |
The action that occurs when user taps on the notification. Launches an activity with a matching intent filter when a person taps the notification. |
body_loc_key |
Optional, string |
The key to the body string in the app's string resources that you want to use to localize the body text to the user's current localization. See String Resources for more information. |
body_loc_args |
Optional, JSON array as string |
Variable string values used in place of the format specifiers in
|
title_loc_key |
Optional, string |
The key to the title string in the app's string resources that you want to use to localize the title text to the user's current localization. See String Resources for more information. |
title_loc_args |
Optional, JSON array as string |
Variable string values used in place of the format specifiers in
See Formatting and Styling for more information. |
iOS custom push payload (FCM)
This section is for Google Firebase Cloud Messaging!
If you want to send a message, your push notification must include a message.ios.notification.
object with a body
, reflecting the message you want to send. You can pass additional options for the push in the meassage
object.
The message.data
object contains custom key-value pairs that you’ve set up your app to interpret. Custom data isn’t supported natively; things like custom image handling and deep linking require additional development. Talk to your app’s developer(s) to understand the custom data that you can pass to your app. If you want to send a silent, custom data-only push, you can omit the message.notification
object and send a data key instead.
The following shows the basic shape of an iOS custom push payload for FCM. Google supports a subset of iOS push payload options (as listed in the APNs section above); you’ll find a deeper explanation of the keys allowed in Google’s documentation.
{
"message": {
"ios": {
"notification": {
// represents the aps.alert object
"title": "string",
"body": "string"
}
},
"data": {
//Optional key-value pairs that your app interprets.
//We don't validate the keys or values you provide.
},
// iOS message options (iOS keys outside the alert payload) go here
"mutable_content": true
}
}
iOS custom push payload (APNs)
APNs) !
If you want to send a message through the Apple Push Notification service (APNs), your push notification must include a aps.alert
object with a body
, reflecting the message you want to send. You can pass additional options for the push in the aps
object (outside
You can pass additional options for the android push in the aps
object (outside of the alert
). Where the alert
represents the message, these settings tell the device how to handle the message—whether to play a sound or add the message to a thread of notifications, etc.
You can also pass additional, custom data outside the aps
object. This is data that your app is set up to interpret. Custom data isn’t supported natively; things like custom image handling and deep linking require additional development. Talk to your app’s developer(s) to understand the custom data that you can pass to your app. You can omit the alert
and send a silent push, with just custom data (setting "content-available": 1
), though it’s not the most common use case.
The following shows the shape of an iOS custom push payload using APNs; you’ll find a deeper explanation of the keys allowed in this payload below.
{
"aps": {
"alert": {
//can be string or object
//alert object keys
"body": "string",
"title": "string",
"subtitle": "string",
"launch-image": "string",
// localization arguments
"title-loc-key": "string",
"title-loc-args": ["array", "of", "strings"],
"subtitle-loc-key": "string",
"subtitle-loc-args": ["array", "of", "strings"],
"loc-key": "string",
"loc-args": ["array", "of", "strings"]
},
// message options
"badge": number,
"sound": "string or dictionary",
"thread-id": "string",
"category": "string",
"content-available": number, 0 (default) or 1,
"mutable-content": number, 0 (default) or 1,
"target-content-id": string,
},
"custom-keys": "Optional, any type"
}
Key | Type | Description |
---|---|---|
aps.alert can be a string (simple message) or object (recommended). Below are the keys supported by the aps.alert object. | ||
title |
Optional, string |
The title of the notification. Apple Watch displays this string in the short look notification interface. |
| Optional, string | Additional information about the purpose of the notification. |
body |
Optional, string |
The notification's body text. While this is "optional" in the sense that you can send an empty notification to perform a background update, you should consider this key required otherwise. |
|
String |
The name of the launch image file. If a person launches your app, the this is the image or storyboard that appears, instead of your app's normal launch image. |
|
String |
The value in your strings file representing a localized title string. Use this key instead of the |
|
Array of strings |
An array of replacement string values for variables in your title string. Each |
|
String |
The value in your strings file representing a localized subtitle string. Use this key, instead of the |
|
Array of strings |
An array of replacement string values for variables in your title string. Each %@ character in
the string specified by |
|
String |
The value in your strings file representing a localized message string. Use this key, instead of the |
|
Array of strings |
An array of strings containing replacement values for variables in your message text. Each |
aps options—these are keys determining how the device handles the `alert`. | ||
|
Optional, number |
The number to display in a badge on your app’s icon. Use |
sound |
Optional, string |
The name of a sound file in your app’s main bundle or in the |
|
Optional, string |
An identifier to group related notifications. This value corresponds to the |
|
Optional, string |
The notification’s type. This string must correspond to the identifier of one of the
|
|
Optional, number (0 or 1) |
The background notification flag. Enter |
|
Optional, number (0 or 1) |
The notification service app extension flag. Set to |
|
Optional, string |
The identifier of the window brought forward. The value of this key is populated on the |
Custom keys — optional, any type. Custom keys and values that your app is set up to interpret—image handling, etc. We don't validate the keys or data you provide. Customer.io and APNs assume that your app understands how to interpret this data. |
Got feedback?
We’re hoping to get your feedback on how you’re using custom payloads, if there’s anything you’re struggling with, or if there’s anything you’re really enjoying about it and want to make sure we keep.