# Customizing Notifications

<admonition type="info">

Customizing push content is optional, as Activity Feeds provides well-designed default templates. Just make sure to enable push notifications for the event types you plan to support.

</admonition>

Once push notifications are enabled for your app, you can customize the templates to match your app's needs. This lets you control how notifications appear on users' devices for activities, reactions, comments, and other feed events.

## Push Notification Templates

Activity Feeds supports templating for both Firebase and APNs. Configuring templates is optional — if no custom templates are provided, Activity Feeds will automatically use default templates for Firebase and APNs.

### Default Templates

Activity Feeds uses specific default templates for different notification types. Here are the actual templates used by the system:

#### Comment Added - Firebase Template

<Tabs>

```json label="JSON"
{
  "data": {
    "sender": "stream.feeds",
    "type": "{{ event_type }}",
    "body": "{{ truncate comment.text 150 }}",
    "title": "{{#if isMentionedInComment}}{{ sender.name }} mentioned you in a comment{{else}}{{#if isActivityOwner}}{{ sender.name }} commented on your activity{{else}}{{ sender.name }} commented on an activity you were mentioned in{{/if}}{{/if}}",
    "fid": "{{ feed.fid }}",
    "activity_id": "{{ activity.id }}",
    "comment_id": "{{ comment.id }}",
    "receiver_id": "{{ receiver.id }}"
  },
  "android": {
    "priority": "high"
  },
  "apns": {
    "payload": {
      "aps": {
        "alert": {
          "title": "{{#if isMentionedInComment}}{{ sender.name }} mentioned you in a comment{{else}}{{#if isActivityOwner}}{{ sender.name }} commented on your activity{{else}}{{ sender.name }} commented on an activity you were mentioned in{{/if}}{{/if}}",
          "body": "{{ truncate comment.text 150 }}"
        },
        "sound": "default",
        "mutable-content": 1,
        "content-available": 0,
        "category": "stream.feeds"
      }
    }
  }
}
```

</Tabs>

#### Comment Added - APN Template

<Tabs>

```json label="JSON"
{
  "payload": {
    "aps": {
      "alert": {
        "title": "{{#if isMentionedInComment}}{{ sender.name }} mentioned you in a comment{{else}}{{#if isActivityOwner}}{{ sender.name }} commented on your activity{{else}}{{ sender.name }} commented on an activity you were mentioned in{{/if}}{{/if}}",
        "body": "{{ truncate comment.text 150 }}"
      },
      "sound": "default",
      "mutable-content": 1,
      "content-available": 0,
      "category": "stream.feeds"
    },
    "stream": {
      "sender": "stream.feeds",
      "type": "{{ event_type }}",
      "fid": "{{ feed.fid }}",
      "activity_id": "{{ activity.id }}",
      "comment_id": "{{ comment.id }}",
      "receiver_id": "{{ receiver.id }}"
    }
  }
}
```

</Tabs>

#### Activity Added - Firebase Template

<Tabs>

```json label="JSON"
{
  "data": {
    "sender": "stream.feeds",
    "type": "{{ event_type }}",
    "body": "{{ truncate activity.text 150 }}",
    "title": "{{#if isMentioned}}{{ sender.name }} mentioned you in an activity{{else}}{{ sender.name }} posted a new activity{{/if}}",
    "fid": "{{ feed.fid }}",
    "activity_id": "{{ activity.id }}",
    "receiver_id": "{{ receiver.id }}"
  },
  "android": {
    "priority": "high"
  },
  "apns": {
    "payload": {
      "aps": {
        "alert": {
          "title": "{{#if isMentioned}}{{ sender.name }} mentioned you in an activity{{else}}{{ sender.name }} posted a new activity{{/if}}",
          "body": "{{ truncate activity.text 150 }}"
        },
        "sound": "default",
        "mutable-content": 1,
        "content-available": 0,
        "category": "stream.feeds"
      }
    }
  }
}
```

</Tabs>

#### Activity Added - APN Template

<Tabs>

```json label="JSON"
{
  "payload": {
    "aps": {
      "alert": {
        "title": "{{#if isMentioned}}{{ sender.name }} mentioned you in an activity{{else}}{{ sender.name }} posted a new activity{{/if}}",
        "body": "{{ truncate activity.text 150 }}"
      },
      "sound": "default",
      "mutable-content": 1,
      "content-available": 0,
      "category": "stream.feeds"
    },
    "stream": {
      "sender": "stream.feeds",
      "type": "{{ event_type }}",
      "fid": "{{ feed.fid }}",
      "activity_id": "{{ activity.id }}",
      "receiver_id": "{{ receiver.id }}"
    }
  }
}
```

</Tabs>

#### Activity Reaction Added - Firebase Template

<Tabs>

```json label="JSON"
{
  "data": {
    "sender": "stream.feeds",
    "type": "{{ event_type }}",
    "body": "Reacted :{{ reaction.type }}: to your activity",
    "title": "{{ sender.name }}",
    "fid": "{{ feed.fid }}",
    "activity_id": "{{ activity.id }}",
    "reaction_type": "{{ reaction.type }}",
    "receiver_id": "{{ receiver.id }}"
  },
  "android": {
    "priority": "high"
  },
  "apns": {
    "payload": {
      "aps": {
        "alert": {
          "title": "{{ sender.name }}",
          "body": "Reacted :{{ reaction.type }}: to your activity"
        },
        "sound": "default",
        "mutable-content": 1,
        "content-available": 0,
        "category": "stream.feeds"
      }
    }
  }
}
```

</Tabs>

#### Activity Reaction Added - APN Template

<Tabs>

```json label="JSON"
{
  "payload": {
    "aps": {
      "alert": {
        "title": "{{ sender.name }}",
        "body": "Reacted :{{ reaction.type }}: to your activity"
      },
      "sound": "default",
      "mutable-content": 1,
      "content-available": 0,
      "category": "stream.feeds"
    },
    "stream": {
      "sender": "stream.feeds",
      "type": "{{ event_type }}",
      "fid": "{{ feed.fid }}",
      "activity_id": "{{ activity.id }}",
      "reaction_type": "{{ reaction.type }}",
      "receiver_id": "{{ receiver.id }}"
    }
  }
}
```

</Tabs>

#### Comment Reaction Added - Firebase Template

<Tabs>

```json label="JSON"
{
  "data": {
    "sender": "stream.feeds",
    "type": "{{ event_type }}",
    "body": "Reacted :{{ reaction.type }}: to your comment",
    "title": "{{ sender.name }}",
    "fid": "{{ feed.fid }}",
    "activity_id": "{{ activity.id }}",
    "comment_id": "{{ comment.id }}",
    "reaction_type": "{{ reaction.type }}",
    "receiver_id": "{{ receiver.id }}"
  },
  "android": {
    "priority": "high"
  },
  "apns": {
    "payload": {
      "aps": {
        "alert": {
          "title": "{{ sender.name }}",
          "body": "Reacted :{{ reaction.type }}: to your comment"
        },
        "sound": "default",
        "mutable-content": 1,
        "content-available": 0,
        "category": "stream.feeds"
      }
    }
  }
}
```

</Tabs>

#### Comment Reaction Added - APN Template

<Tabs>

```json label="JSON"
{
  "payload": {
    "aps": {
      "alert": {
        "title": "{{ sender.name }}",
        "body": "Reacted :{{ reaction.type }}: to your comment"
      },
      "sound": "default",
      "mutable-content": 1,
      "content-available": 0,
      "category": "stream.feeds"
    },
    "stream": {
      "sender": "stream.feeds",
      "type": "{{ event_type }}",
      "fid": "{{ feed.fid }}",
      "activity_id": "{{ activity.id }}",
      "comment_id": "{{ comment.id }}",
      "reaction_type": "{{ reaction.type }}",
      "receiver_id": "{{ receiver.id }}"
    }
  }
}
```

</Tabs>

#### Follow Created - Firebase Template

<Tabs>

```json label="JSON"
{
  "data": {
    "sender": "stream.feeds",
    "type": "{{ event_type }}",
    "title": "{{ sender.name }} started following you",
    "fid": "{{ feed.fid }}",
    "source_fid": "{{ follow.source_feed.FID }}",
    "target_fid": "{{ follow.target_feed.FID }}",
    "receiver_id": "{{ receiver.id }}"
  },
  "android": {
    "priority": "high"
  },
  "apns": {
    "payload": {
      "aps": {
        "alert": {
          "title": "{{ sender.name }} started following you"
        },
        "sound": "default",
        "mutable-content": 1,
        "content-available": 0,
        "category": "stream.feeds"
      }
    }
  }
}
```

</Tabs>

#### Follow Created - APN Template

<Tabs>

```json label="JSON"
{
  "payload": {
    "aps": {
      "alert": {
        "title": "{{ sender.name }} started following you"
      },
      "sound": "default",
      "mutable-content": 1,
      "content-available": 0,
      "category": "stream.feeds"
    },
    "stream": {
      "sender": "stream.feeds",
      "type": "{{ event_type }}",
      "fid": "{{ feed.fid }}",
      "source_fid": "{{ follow.source_feed.FID }}",
      "target_fid": "{{ follow.target_feed.FID }}",
      "receiver_id": "{{ receiver.id }}"
    }
  }
}
```

</Tabs>

#### Activity Reaction - Firebase Template

<Tabs>

```json label="JSON"
{
  "data": {
    "sender": "stream.feeds",
    "type": "{{ event_type }}",
    "body": "Reacted :{{ reaction.type }}: to your activity",
    "title": "{{ sender.name }}",
    "fid": "{{ feed.fid }}",
    "activity_id": "{{ activity.id }}",
    "reaction_type": "{{ reaction.type }}",
    "receiver_id": "{{ receiver.id }}"
  },
  "android": {
    "priority": "high"
  },
  "apns": {
    "payload": {
      "aps": {
        "alert": {
          "title": "{{ sender.name }}",
          "body": "Reacted :{{ reaction.type }}: to your activity"
        },
        "sound": "default",
        "mutable-content": 1,
        "content-available": 0,
        "category": "stream.feeds"
      },
      "stream": {
        "sender": "stream.feeds",
        "type": "{{ event_type }}",
        "fid": "{{ feed.fid }}",
        "activity_id": "{{ activity.id }}",
        "reaction_type": "{{ reaction.type }}",
        "receiver_id": "{{ receiver.id }}"
      }
    }
  }
}
```

</Tabs>

#### Activity Reaction - APN Template

<Tabs>

```json label="JSON"
{
  "payload": {
    "aps": {
      "alert": {
        "title": "{{ sender.name }}",
        "body": "Reacted :{{ reaction.type }}: to your activity"
      },
      "sound": "default",
      "mutable-content": 1,
      "content-available": 0,
      "category": "stream.feeds"
    },
    "stream": {
      "sender": "stream.feeds",
      "type": "{{ event_type }}",
      "fid": "{{ feed.fid }}",
      "activity_id": "{{ activity.id }}",
      "reaction_type": "{{ reaction.type }}",
      "receiver_id": "{{ receiver.id }}"
    }
  }
}
```

</Tabs>

#### Comment Reaction - Firebase Template

<Tabs>

```json label="JSON"
{
  "data": {
    "sender": "stream.feeds",
    "type": "{{ event_type }}",
    "body": "Reacted :{{ reaction.type }}: to your comment",
    "title": "{{ sender.name }}",
    "fid": "{{ feed.fid }}",
    "activity_id": "{{ activity.id }}",
    "comment_id": "{{ comment.id }}",
    "reaction_type": "{{ reaction.type }}",
    "receiver_id": "{{ receiver.id }}"
  },
  "android": {
    "priority": "high"
  },
  "apns": {
    "payload": {
      "aps": {
        "alert": {
          "title": "{{ sender.name }}",
          "body": "Reacted :{{ reaction.type }}: to your comment"
        },
        "sound": "default",
        "mutable-content": 1,
        "content-available": 0,
        "category": "stream.feeds"
      },
      "stream": {
        "sender": "stream.feeds",
        "type": "{{ event_type }}",
        "fid": "{{ feed.fid }}",
        "activity_id": "{{ activity.id }}",
        "comment_id": "{{ comment.id }}",
        "reaction_type": "{{ reaction.type }}",
        "receiver_id": "{{ receiver.id }}"
      }
    }
  }
}
```

</Tabs>

#### Comment Reaction - APN Template

<Tabs>

```json label="JSON"
{
  "payload": {
    "aps": {
      "alert": {
        "title": "{{ sender.name }}",
        "body": "Reacted :{{ reaction.type }}: to your comment"
      },
      "sound": "default",
      "mutable-content": 1,
      "content-available": 0,
      "category": "stream.feeds"
    },
    "stream": {
      "sender": "stream.feeds",
      "type": "{{ event_type }}",
      "fid": "{{ feed.fid }}",
      "activity_id": "{{ activity.id }}",
      "comment_id": "{{ comment.id }}",
      "reaction_type": "{{ reaction.type }}",
      "receiver_id": "{{ receiver.id }}"
    }
  }
}
```

</Tabs>

#### Notification Feed Updated - Firebase Template

<Tabs>

```json label="JSON"
{
  "data": {
    "sender": "stream.feeds",
    "type": "{{ event_type }}",
    "title": "{{ notification_title }}",
    "body": "{{ notification_body }}",
    "fid": "{{ feed.fid }}",
    "receiver_id": "{{ receiver.id }}"
  },
  "android": {
    "priority": "high",
    "collapse_key": "notification_feed_{{ aggregated_activity.group }}"
  },
  "apns": {
    "headers": {
      "apns-collapse-id": "notification_feed_{{ aggregated_activity.group }}"
    },
    "payload": {
      "aps": {
        "alert": {
          "title": "{{ notification_title }}",
          "body": "{{ notification_body }}"
        },
        "badge": {{ notification_status.unseen_count }},
        "sound": "default",
        "mutable-content": 1,
        "content-available": 0,
        "category": "stream.feeds"
      }
    }
  }
}
```

</Tabs>

#### Notification Feed Updated - APN Template

<Tabs>

```json label="JSON"
{
  "collapse_id": "notification_feed_{{ aggregated_activity.group }}",
  "payload": {
    "aps": {
      "alert": {
        "title": "{{ notification_title }}",
        "body": "{{ notification_body }}"
      },
      "badge": {{ notification_status.unseen_count }},
      "sound": "default",
      "mutable-content": 1,
      "content-available": 0,
      "category": "stream.feeds"
    },
    "stream": {
      "sender": "stream.feeds",
      "type": "{{ event_type }}",
      "fid": "{{ feed.fid }}",
      "receiver_id": "{{ receiver.id }}"
    }
  }
}
```

</Tabs>

## Context Variables

Activity Feeds uses the [Handlebars](http://handlebarsjs.com/) templating language to render push notification payloads for both Firebase and APN providers. This allows you to create dynamic, personalized notifications with conditional logic and data interpolation.

Activity Feeds provides the following variables in the template rendering context:

| Name                  | Type   | Description                                                                                                 |
| --------------------- | ------ | ----------------------------------------------------------------------------------------------------------- |
| `event_type`          | string | The type of event (comment_added, activity_added, etc.)                                                     |
| `sender`              | object | The user who triggered the notification                                                                     |
| `receiver`            | object | The user receiving the notification                                                                         |
| `activity`            | object | The activity object containing id, text, and other data                                                     |
| `comment`             | object | Comment object (for comment-related notifications)                                                          |
| `reaction`            | object | Reaction object (for reaction-related notifications). Contains: `type`, `id`, etc.                          |
| `feed`                | object | The feed where the event occurred. Contains: `fid`, etc.                                                    |
| `follow`              | object | Follow relationship object (for follow notifications). Contains: `source_feed.FID`, `target_feed.FID`, etc. |
| `notification_title`  | string | Generated title for notification feed updates                                                               |
| `notification_body`   | string | Generated body for notification feed updates                                                                |
| `notification_status` | object | Contains unseen_count and unread_count                                                                      |
| `aggregated_activity` | object | Aggregated activity object for notification feeds. Contains: `group`, etc.                                  |

### Template Conditional Variables

The templates also include conditional variables for better messaging:

| Name                   | Type    | Description                                       |
| ---------------------- | ------- | ------------------------------------------------- |
| `isMentionedInComment` | boolean | True if user is mentioned in the comment          |
| `isActivityOwner`      | boolean | True if user owns the activity being commented on |
| `isMentioned`          | boolean | True if user is mentioned in the activity         |

## Configuring Templates

### Via API

The [Upsert Push Template REST endpoint](https://getstream.github.io/protocol/?urls.primaryName=Chat#/product%3Achat/UpsertPushTemplate) allows you to enable push notifications for specific event types and optionally define custom templates. Activity Feeds supports event types like `comment_added`, `activity_added`, `activity_reaction`, and more.

#### Enabling Push with Default Template

<Tabs>

```json label="JSON"
{
  "enable_push": true,
  "event_type": "comment_added",
  "push_provider_type": "firebase",
  "push_provider_name": "firebase"
}
```

</Tabs>

#### Enabling Push with Custom Template

<Tabs>

```json label="JSON"
{
  "enable_push": true,
  "event_type": "comment_added",
  "push_provider_type": "firebase",
  "push_provider_name": "firebase",
  "template": "{\"data\":{\"sender\":\"stream.feeds\",\"type\":\"{{ event_type }}\",\"body\":\"{{ truncate comment.text 150 }}\",\"title\":\"{{ sender.name }} commented on your activity\",\"fid\":\"{{ feed.fid }}\",\"activity_id\":\"{{ activity.id }}\",\"comment_id\":\"{{ comment.id }}\",\"receiver_id\":\"{{ receiver.id }}\"},\"android\":{\"priority\":\"high\"},\"apns\":{\"payload\":{\"aps\":{\"alert\":{\"title\":\"{{ sender.name }} commented on your activity\",\"body\":\"{{ truncate comment.text 150 }}\"},\"sound\":\"default\",\"mutable-content\":1,\"content-available\":0,\"category\":\"stream.feeds\"}}}}"
}
```

</Tabs>

**Available Fields:**

| Field Name           | Type                                                                                                                               | Description                                                                                                    |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| `enable_push`        | Boolean                                                                                                                            | Indicates whether push notifications are enabled for this event type.                                          |
| `event_type`         | String (comment_added, activity_added, activity_reaction_added, comment_reaction_added, follow_created, notification_feed_updated) | The type of event used to apply the corresponding custom push configuration.                                   |
| `push_provider_type` | String                                                                                                                             | The type of push provider (firebase, apn)                                                                      |
| `push_provider_name` | String                                                                                                                             | The name of the configured push provider instance. Can be left empty if you're not using multi-bundle support. |
| `template`           | String                                                                                                                             | The push notification template as a stringified JSON object.                                                   |

#### Example

<Tabs>

```javascript label="Node"
// Enable push notifications for comment_added events with custom template
const response = await client.upsertPushTemplate({
  enable_push: true,
  event_type: "feeds.comment.added",
  push_provider_type: "firebase",
  push_provider_name: "firebase",
  template: JSON.stringify({
    data: {
      sender: "stream.feeds",
      type: "{{ event_type }}",
      body: "{{ truncate comment.text 150 }}",
      title: "{{ sender.name }} commented on your activity",
      fid: "{{ feed.fid }}",
      activity_id: "{{ activity.id }}",
      comment_id: "{{ comment.id }}",
      receiver_id: "{{ receiver.id }}",
    },
    android: {
      priority: "high",
    },
    apns: {
      payload: {
        aps: {
          alert: {
            title: "{{ sender.name }} commented on your activity",
            body: "{{ truncate comment.text 150 }}",
          },
          sound: "default",
          "mutable-content": 1,
          "content-available": 0,
          category: "stream.feeds",
        },
      },
    },
  }),
});
```

```go label="Go"
// Enable push notifications for comment_added events with custom template
template := map[string]any{
  "data": map[string]any{
    "sender":      "stream.feeds",
    "type":        "{{ event_type }}",
    "body":        "{{ truncate comment.text 150 }}",
    "title":       "{{ sender.name }} commented on your activity",
    "fid":         "{{ feed.fid }}",
    "activity_id": "{{ activity.id }}",
    "comment_id":  "{{ comment.id }}",
    "receiver_id": "{{ receiver.id }}",
  },
  "android": map[string]any{
    "priority": "high",
  },
  "apns": map[string]any{
    "payload": map[string]any{
      "aps": map[string]any{
        "alert": map[string]any{
          "title": "{{ sender.name }} commented on your activity",
          "body":  "{{ truncate comment.text 150 }}",
        },
        "sound":             "default",
        "mutable-content":   1,
        "content-available": 0,
        "category":          "stream.feeds",
      },
    },
  },
}

templateJSON, err := json.Marshal(template)
if err != nil {
  log.Fatal("Error marshaling template:", err)
}

response, err := client.UpsertPushTemplate(context.Background(), &getstream.UpsertPushTemplateRequest{
  EnablePush:       getstream.PtrTo(true),
  EventType:        "feeds.comment.added",
  PushProviderType: "firebase",
  PushProviderName: getstream.PtrTo("firebase"),
  Template:         getstream.PtrTo(string(templateJSON)),
})

if err != nil {
  log.Fatal("Error upserting push template:", err)
}
```

```php label="php"
// Enable push notifications for comment_added events with custom template
$template = json_encode([
    "data" => [
        "sender" => "stream.feeds",
        "type" => "{{ event_type }}",
        "body" => "{{ truncate comment.text 150 }}",
        "title" => "{{ sender.name }} commented on your activity",
        "fid" => "{{ feed.fid }}",
        "activity_id" => "{{ activity.id }}",
        "comment_id" => "{{ comment.id }}",
        "receiver_id" => "{{ receiver.id }}"
    ],
    "android" => [
        "priority" => "high"
    ],
    "apns" => [
        "payload" => [
            "aps" => [
                "alert" => [
                    "title" => "{{ sender.name }} commented on your activity",
                    "body" => "{{ truncate comment.text 150 }}"
                ],
                "sound" => "default",
                "mutable-content" => 1,
                "content-available" => 0,
                "category" => "stream.feeds"
            ]
        ]
    ]
]);

$request = new \GetStream\GeneratedModels\UpsertPushTemplateRequest(
    eventType: "feeds.comment.added",
    pushProviderType: "firebase",
    enablePush: true,
    pushProviderName: "firebase",
    template: $template
);

$response = $feedsClient->upsertPushTemplate($request);
```

</Tabs>

### Retrieving Push Templates

You can retrieve existing push templates using the `getPushTemplates` method:

<Tabs>

```php label="php"
// Retrieve push templates for a specific provider
$response = $feedsClient->getPushTemplates(
    pushProviderType: "firebase",
    pushProviderName: "firebase"
);
```

```js label="Node"
// Retrieve push templates for a specific provider
client.getPushTemplates({
  push_provider_type: "firebase",
  push_provider_name: "firebase",
});
```

</Tabs>

## Limitations

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

For example, given the context:

<Tabs>

```json label="JSON"
{
  "sender": {
    "name": "Bob",
    "some_array": ["foo", "bar"]
  }
}
```

</Tabs>

And the template:

<Tabs>

```json label="JSON"
"title": {{ sender.some_array.[0] }}
```

</Tabs>

The rendered payload will be:

<Tabs>

```json label="JSON"
"title": ""
```

</Tabs>

### 2: Interpolating Whole Lists and Objects Isn't Allowed

For example, given the context:

<Tabs>

```json label="JSON"
{
  "sender": {
    "name": "bob",
    "some_array": ["foo", "bar"],
    "address": {
      "street": "willow str"
    }
  }
}
```

</Tabs>

And the template:

<Tabs>

```json label="JSON"
"title": "{{ sender.some_array }} {{ sender.address }}"
```

</Tabs>

The rendered payload will be:

<Tabs>

```json label="JSON"
"title": "[] {}"
```

</Tabs>

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

For example, given the context:

<Tabs>

```json label="JSON"
{
  "sender": {
    "name": "bob"
  }
}
```

</Tabs>

And the template:

<Tabs>

```json label="JSON"
"title": {{ sender.missing_field }}
```

</Tabs>

The rendered payload will be:

<Tabs>

```json label="JSON"
"title": ""
```

</Tabs>

## Advanced Use Cases

For advanced use cases (e.g. conditional rendering, data validation, etc), Stream provides handlebars helper functions that can be used in Activity Feeds templates.

### Helper Functions

| name     | type     | description                                                                                                                                                               |
| -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| json     | function | renders passed parameter as JSON (e.g `{"activity":{{{ json activity }}}}` )                                                                                              |
| each     | function | For loop. Use this to access the current variable, @index for the current index and @first and @last as convenience booleans                                              |
| 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 event_type "comment_added" }}Comment{{else}}Other{{/equal}}` ) |
| unequal  | function | Inequality check function. Tests inequality of the given 2 parameters. Supports else statement.                                                                           |
| 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.                                                                                                                        |
| truncate | function | Truncate given text to given length (e.g `{{ truncate activity.text 150 }}`)                                                                                              |

### Function Parameters

These helper functions can be combined to create sophisticated conditional logic in your notification templates. They are particularly useful for:

- Conditional messaging based on event types
- Data validation and fallback values
- Text truncation for different screen sizes
- Complex logic for personalized notifications

### Examples

#### Example 1: Conditional Event Type Messaging

<Tabs>

```json label="JSON"
{
  "aps": {
    "alert": {
      "title": "{{#equal event_type 'comment_added'}}New Comment{{else}}{{#equal event_type 'activity_reaction'}}New Reaction{{else}}Activity Update{{/equal}}{{/equal}}",
      "body": "{{ sender.name }}: {{#if comment}}{{ truncate comment.text 150 }}{{else}}{{ truncate activity.text 150 }}{{/if}}"
    }
  }
}
```

</Tabs>

#### Example 2: Advanced Conditional Logic

<Tabs>

```json label="JSON"
{
  "data": {
    "title": "{{#if isMentionedInComment}}{{ sender.name }} mentioned you{{else}}{{#if isActivityOwner}}{{ sender.name }} commented on your activity{{else}}{{ sender.name }} commented{{/if}}{{/if}}",
    "body": "{{#unless comment.text}}No comment text{{else}}{{ truncate comment.text 150 }}{{/unless}}"
  }
}
```

</Tabs>


---

This page was last updated at 2026-04-22T16:42:41.848Z.

For the most recent version of this documentation, visit [https://getstream.io/activity-feeds/docs/node/push_template/](https://getstream.io/activity-feeds/docs/node/push_template/).