# Notification Feeds

Notification feeds let you notify users about relevant interactions, for example

- someone started to follow them
- someone liked their post
- someone left a comment on their post

## Creating notification feeds

The built-in `notification` feed comes with the necessary configurations, but it's also possible to create your own notification feed group:

<partial id="activity-feeds/v3-latest/_default/_partials/custom-notification-group"></partial>

### Aggregation format

The built-in `notification` feed uses the following aggregation format: `"{{ type }}_{{ time.strftime(\"%Y-%m-%d\") }}"`. You can change this syntax by updating the `notification` feed group.

You can see all supported fields and syntax for aggregation in the [Aggregation guide](/activity-feeds/docs/<framework>/aggregation/).

It's possible to turn off aggregation, but still enable notification tracking. In that case every new activity will increase `unread`/`unseen` count. When you have aggregation turned on, `unread`/`unseen` will refer to the number of aggregated groups.

### Adding notification activities

The built-in `notification` groups can automatically create notifications for the most common interactions (see [Built-in notification feed section](#built-in-notification-feed)).

If you want to extend that, or create your own notification feed, you can add notification activities using server-side integration. You can add webhook handlers for the relevant events to create notifications without API calls from your client-side application to your server-side application.

## Built-in notification feed

### Creating notification activities

The built-in `notification` feed allows you to automatically create notification activities.

<codetabs>

<codetabs-item value="javascript" label="JavaScript">

```js
// Eric follows Jane
await ericTimeline.follow(janeFeed, {
  // When true Jane's notification feed will be updated with follow activity
  create_notification_activity: true,
});

// Eric comments on Jane's activity
await ericClient.addComment({
  comment: "Agree!",
  object_id: janeActivity.id,
  object_type: "activity",
  // When true Jane's notification feed will be updated with comment activity
  create_notification_activity: true,
});

// Eric reacts to Jane's activity
await ericClient.addReaction({
  activity_id: janeActivity.id,
  // When true Jane's notification feed will be updated with reaction activity
  type: "like",
  create_notification_activity: true,
});

// Eric reacts to a comment posted to Jane's activity by Sara
await ericClient.addCommentReaction({
  comment_id: saraComment.id,
  type: "like",
  // When true Sara's notification feed will be updated with comment reaction activity
  create_notification_activity: true,
});
```

</codetabs-item>

<codetabs-item value="node" label="Node">

```js
// Eric follows Jane
await serverClient.feeds.follow({
  source: ericTimeline.fid,
  target: janeFeed.fid,
  // When true Jane's notification feed will be updated with follow activity
  create_notification_activity: true,
});

// Eric comments on Jane's activity
await serverClient.feeds.addComment({
  comment: "Agree!",
  object_id: janeActivity.id,
  object_type: "activity",
  // When true Jane's notification feed will be updated with comment activity
  create_notification_activity: true,
  user_id: "eric",
});

// Eric reacts to Jane's activity
await serverClient.feeds.addReaction({
  activity_id: janeActivity.id,
  // When true Jane's notification feed will be updated with reaction activity
  type: "like",
  create_notification_activity: true,
  user_id: "eric",
});

// Eric reacts to a comment posted to Jane's activity by Sara
await serverClient.feeds.addCommentReaction({
  comment_id: saraComment.id,
  type: "like",
  // When true Sara's notification feed will be updated with comment reaction activity
  create_notification_activity: true,
  user_id: "eric",
});
```

</codetabs-item>

</codetabs>

### Reading notification activities

<partial id="activity-feeds/v3-latest/_default/_partials/built-in-notification-feed"></partial>

This is what Jane's notification feed looks like after the above interactions (only relevant fields shown):

- Three aggregated activity groups:
  - `comment-2025-08-04`
  - `reaction-2025-08-04`
  - `follow-2025-08-04`
- `notification_context` has information about the activity/action that triggered the notification
  - Please note that `notification_context` field is only defined if you're using the built-in `notification` feed and `create_notification_activity` flag

<codetabs>

<codetabs-item value="javascript" label="JavaScript">

```js
{
  aggregated_activities: [
    {
      activity_count: 1,
      user_count: 1,
      group: "comment-2025-08-04",
      activities: [
        {
          type: "comment",
          user: {
            id: "eric",
            name: "Eric",
            // other User fields
          },
          notification_context: {
            trigger: {
              text: "Eric commented on your activity",
              type: "comment",
            },
            target: {
              user_id: "jane",
              type: "post",
              text: "As earnestly shameless elsewhere defective estimable fulfilled of",
              id: "a0668408-0eb9-4906-a1cf-be79f988051d",
            },
          },
          // Other activity fields
        },
      ],
    },
    {
      activity_count: 1,
      user_count: 1,
      group: "reaction-2025-08-04",
      activities: [
        {
          type: "reaction",
          user: {
            id: "eric",
            name: "Eric",
          },
          notification_context: {
            target: {
              id: "8966090a-30bf-4fe2-b8bc-b0fe36200e56",
              user_id: "jane",
              type: "post",
              text: "Ask too matter formed county wicket oppose talent",
            },
            trigger: {
              type: "reaction",
              text: "Eric reacted to your activity",
            },
          },
        },
      ],
    },
    {
      activity_count: 1,
      user_count: 1,
      group: "follow-2025-08-04",
      activities: [
        {
          type: "follow",
          user: {
            id: "eric",
            name: "Eric",
          },
          notification_context: {
            target: {
              id: "jane",
              name: "Jane",
            },
            trigger: {
              type: "follow",
              text: "Eric started following you",
            },
          },
        },
      ],
    },
  ];
}
```

</codetabs-item>

<codetabs-item value="node" label="Node">

```js
{
  aggregated_activities: [
    {
      activity_count: 1,
      user_count: 1,
      group: "comment-2025-08-04",
      activities: [
        {
          type: "comment",
          user: {
            id: "eric",
            name: "Eric",
            // other User fields
          },
          notification_context: {
            trigger: {
              text: "Eric commented on your activity",
              type: "comment",
            },
            target: {
              user_id: "jane",
              type: "post",
              text: "As earnestly shameless elsewhere defective estimable fulfilled of",
              id: "a0668408-0eb9-4906-a1cf-be79f988051d",
            },
          },
          // Other activity fields
        },
      ],
    },
    {
      activity_count: 1,
      user_count: 1,
      group: "reaction-2025-08-04",
      activities: [
        {
          type: "reaction",
          user: {
            id: "eric",
            name: "Eric",
          },
          notification_context: {
            target: {
              id: "8966090a-30bf-4fe2-b8bc-b0fe36200e56",
              user_id: "jane",
              type: "post",
              text: "Ask too matter formed county wicket oppose talent",
            },
            trigger: {
              type: "reaction",
              text: "Eric reacted to your activity",
            },
          },
        },
      ],
    },
    {
      activity_count: 1,
      user_count: 1,
      group: "follow-2025-08-04",
      activities: [
        {
          type: "follow",
          user: {
            id: "eric",
            name: "Eric",
          },
          notification_context: {
            target: {
              id: "jane",
              name: "Jane",
            },
            trigger: {
              type: "follow",
              text: "Eric started following you",
            },
          },
        },
      ],
    },
  ];
}
```

</codetabs-item>

</codetabs>

## Notification status

If notification tracking is turned on for the feed group then you'll receive notification status when reading the feed. Notification status tells

- How many unread notifications does the feed have?
- Which notifications are read?
- How many unseen notifications does the feed have?
- Which notifications are seen?

For example, take the notification system on Facebook. If you click the notification icon, all notifications get marked as seen. However, an individual notification only gets marked as read when you click on it.

Here is an example payload for notificaiton status:

<codetabs>

<codetabs-item value="javascript" label="JavaScript">

```js
{
  notification_status: {
    // Number of unread notifications
    unread: 12,
    // Number of unseen notifications
    unseen: 0,
    last_seen_at: 1754309822808392000,
    seen_activities: [],
    last_read_at: 1754309822808392000,
    read_activities: ['reaction-2025-08-04'],
  }
}

// Check if a group is read/seen
const isRead = (lastReadAt && group.updated_at.getTime() < lastReadAt.getTime()) || readActivities.includes(group.group);
const isSeen = (lastSeenAt && group.updated_at.getTime() < lastSeenAt.getTime()) || seenActivities.includes(group.group);
```

</codetabs-item>

<codetabs-item value="node" label="Node">

```js
{
  notification_status: {
    // Number of unread notifications
    unread: 12,
    // Number of unseen notifications
    unseen: 0,
    last_seen_at: 1754309822808392000,
    seen_activities: [],
    last_read_at: 1754309822808392000,
    read_activities: ['reaction-2025-08-04'],
  }
}

// Check if a group is read/seen
const isRead = (lastReadAt && group.updated_at.getTime() < lastReadAt.getTime()) || readActivities.includes(group.group);
const isSeen = (lastSeenAt && group.updated_at.getTime() < lastSeenAt.getTime()) || seenActivities.includes(group.group);
```

</codetabs-item>

</codetabs>

## Marking notifications as seen

<codetabs>

<codetabs-item value="javascript" label="JavaScript">

```js
await notificationFeed.markActivity({
  // Mark all notifications as seen...
  mark_all_seen: true,
  // ...or only selected ones
  mark_seen: [
    /* group names to mark as seen */
  ],
});
```

</codetabs-item>

<codetabs-item value="node" label="Node">

```js
await notificationFeed.markActivity({
  // Mark all notifications as seen...
  mark_all_seen: true,
  // ...or only selected ones
  mark_seen: [
    /* group names to mark as seen */
  ],
  user_id: "<user id>",
});
```

</codetabs-item>

</codetabs>

## Marking notifications as read

<partial id="activity-feeds/v3-latest/_default/_partials/marking-notifications-as-read"></partial>

---

This page was last updated at 2025-08-15T14:14:10.391Z.

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