Customizing Notifications

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.

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

{
  "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"
      }
    }
  }
}

Comment Added - APN Template

{
  "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 }}"
    }
  }
}

Activity Added - Firebase Template

{
  "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"
      }
    }
  }
}

Activity Added - APN Template

{
  "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 }}"
    }
  }
}

Activity Reaction Added - Firebase Template

{
  "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"
      }
    }
  }
}

Activity Reaction Added - APN Template

{
  "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 }}"
    }
  }
}

Comment Reaction Added - Firebase Template

{
  "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"
      }
    }
  }
}

Comment Reaction Added - APN Template

{
  "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 }}"
    }
  }
}

Follow Created - Firebase Template

{
  "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"
      }
    }
  }
}

Follow Created - APN Template

{
  "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 }}"
    }
  }
}

Activity Reaction - Firebase Template

{
  "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 }}"
      }
    }
  }
}

Activity Reaction - APN Template

{
  "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 }}"
    }
  }
}

Comment Reaction - Firebase Template

{
  "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 }}"
      }
    }
  }
}

Comment Reaction - APN Template

{
  "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 }}"
    }
  }
}

Notification Feed Updated - Firebase Template

{
  "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"
      }
    }
  }
}

Notification Feed Updated - APN Template

{
  "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 }}"
    }
  }
}

Context Variables

Activity Feeds uses the Handlebars 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:

NameTypeDescription
event_typestringThe type of event (comment_added, activity_added, etc.)
senderobjectThe user who triggered the notification
receiverobjectThe user receiving the notification
activityobjectThe activity object containing id, text, and other data
commentobjectComment object (for comment-related notifications)
reactionobjectReaction object (for reaction-related notifications)
Contains: type, id, etc.
feedobjectThe feed where the event occurred
Contains: fid, etc.
followobjectFollow relationship object (for follow notifications)
Contains: source_feed.FID, target_feed.FID, etc.
notification_titlestringGenerated title for notification feed updates
notification_bodystringGenerated body for notification feed updates
notification_statusobjectContains unseen_count and unread_count
aggregated_activityobjectAggregated activity object for notification feeds
Contains: group, etc.

Template Conditional Variables

The templates also include conditional variables for better messaging:

NameTypeDescription
isMentionedInCommentbooleanTrue if user is mentioned in the comment
isActivityOwnerbooleanTrue if user owns the activity being commented on
isMentionedbooleanTrue if user is mentioned in the activity

Configuring Templates

Via API

The Upsert Push Template REST endpoint 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

{
  "enable_push": true,
  "event_type": "comment_added",
  "push_provider_type": "firebase",
  "push_provider_name": "firebase"
}

Enabling Push with Custom Template

{
  "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\"}}}}"
}

Available Fields:

Field NameTypeDescription
enable_pushBooleanIndicates whether push notifications are enabled for this event type.
event_typeString
(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_typeStringThe type of push provider (firebase, apn)
push_provider_nameStringThe name of the configured push provider instance. Can be left empty if you’re not using multi-bundle support.
templateStringThe push notification template as a stringified JSON object.

Example

// 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",
        },
      },
    },
  }),
});

Retrieving Push Templates

You can retrieve existing push templates using the getPushTemplates method:

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