Push Templates

LAST EDIT Oct 04 2024
All apps using push v2 or created after January 18, 2022 do not need to configure any template in general. However, some platforms might still need to add templates. This is a general description of templating. For templating in v2, see details here. For migrating to v2, see details here.

For both Firebase and APN, the payload that is being sent is rendered using the handlebars templating language, to ensure full configurability for your app.

Stream provides the following variables in the template rendering context:

Context Variables

Copied!

Name

Type

Description

channel

object

Channel object. You can access the channel name and any other custom field you have defined for this channel

sender

object

Sender object. You can access the user name, id or any other custom field you have defined for the user

receiver

object

Receiver object. You can access the user name, id or any other custom field you have defined for the user

message

object

Message object. You can access the text of the message (or a preview of it if the message is too large) or any other custom field you have defined for the message

members

array

Channel members. You can access the user name, id and any other custom field of each member (i.e. excluding sender)

otherMembers

array

Like members but the user who will be receiving the notification is excluded (i.e. excluding sender and receiver)

unread_count

integer

Number of unread messages

unread_channels

integer

Number of unread channels for this user

members and otherMembers aren't available in the v2 template context.

Defaults

Copied!

v1

Copied!

When editing APN/Firebase settings, if you leave the notification_template or data_templatefield empty, default templates will be used.

v2

Copied!

Editing data template is forbidden. There is no default for notification_template, it's sent only if set. apn_template is introduced for apn templating under firebase.

APN default (v1):

Firebase default notification template (v1):

Firebase default data template (v1):

APN default and Firebase default APN template (v2):

Generic default data payload (v2):

Limitations

Copied!

There are some limitations that Stream imposes on the push notification handlebars template to make sure no malformed payloads are being sent to push providers.

1: Custom Arrays Can't Be Indexed

Copied!

For example, given the context:

And the template:

The rendered payload will be:

2: Interpolating Whole Lists and Objects Isn't Allowed

Copied!

For example, given the context:

And the template:

The rendered payload will be:

3: Unquoted fields that aren't in the context will be rendered as empty strings

Copied!

For example, given the context:

And the template:

The rendered payload will be:

Advanced Use Cases

Copied!

For advanced use cases (e.g. A list of channel members in the notification title, conditional rendering, etc), Stream provides some handlebars helper functions.

Helper Functions

Copied!

name

type

description

implodemembers

function

takes the list of channel members and implodes it into a single string, using a custom limit, separator and suffix.

json

function

renders passed parameter as JSON (e.g {"channel":{{{ json channel }}}})

each

function

For loop. Use this to access the current variable, @index for the current index and @first and @last as convenience booleans to determine if the iteration is at its first/last element

if

function

If function. Tests trueness of given parameter. Supports else statement. (e.g {{#if sender.name}}{{ sender.name }}{{/if}})

unless

function

Unless function. Tests falseness of given parameter. Supports else statement. (e.g {{#unless sender.name}}Missing name{{/unless}})

equal

function

Equality check function. Tests equality of the given 2 parameters. Supports else statement. (e.g {{#equal channel.type "messaging" }}This is the messaging channel{{else}}This is another channel{{/equal}} )

unequal

function

Inequality check function. Tests inequality of the given 2 parameters. Supports else statement. (e.g {{#unequal channel.type "messaging" }}This is another channel{{else}}This is the messaging channel{{/unequal}} )

ifLt

function

If less than. Supports else statement.

ifLte

function

If less than or equal. Supports else statement.

ifGt

function

If greater than. Supports else statement.

ifGte

function

If greater than or equal. Supports else statement.

remainder

function

Calculates the difference between the length of an array and an integer (e.g {{remainder otherMembers 2}}

truncate

function

Truncate given text to given length (e.g {{ truncate message.text 2000 }})

Most of the functions above are straight forward, except for implodeMembers, which will be detailed further.

The full function signature is: {{implodeMembers otherMembers|members [limit=] [separator=] [nameField=] [suffixFmt=]}}

Function Parameters

Copied!

name

type

description

default

otherMembers | members

array

Which member array to implode

limit

integer

How many member names to show before adding the suffix

3

nameField

string

Field name from which field to retrieve the member's name. Note: does not support nesting

name

separator

string

Separator to use for channel members

,

suffixFmt

string

Format string to use for the suffix. Note: only %d is allowed for formatting

and %d other(s)

Examples

Copied!

Let's put these helpers to use in a few examples:

Example 1

Copied!

Rendering channel members in the notification title. Each member's name is stored in the fullName field.

What we want to achieve:

How we will achieve it: using implodeMembers with a custom name field (leaving others empty so that defaults will be used):

Example 2

Copied!

Rendering channel members in the notification title. Each member's name is stored in the nested details.name field.

What we want to achieve:

How we will achieve it: since implodeMembers doesn't support nested fields, we need to use a bunch of helpers such as each, ifLte. Note how the use of ~ will trim the whitespaces so that the title in rendered in a single row: