# Aggregation

Aggregated feeds are helpful if you want to group activities. Here are some examples of what you can achieve using aggregated feeds:

- 'Eric followed 10 people'

- 'Julie and 14 others liked your photo'

This page shows what variables and syntax you can use to create aggregation expressions.

## Creating aggregated feeds

You can create feed groups with aggregation using the API:

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

## Reading aggregated feeds

When you insert an activity to an aggregated feed we apply the aggregation format. When reading the feed you can read the aggregated activities, together with the latest activities of that group.

Here is an example API response for reading an aggregated feed:

```json
{
  "aggregated_activities": [
    {
      "activities": [
        /** latest non-aggregated activities of the group */
      ],
      "activity_count": 3, // how many activities are there in the group?
      "user_count": 2, // how many different users are in the group?
      "group": "reaction-2025-07-30", // reaction activities for the given day
      "score": 0, // score of the group, used when ranking is configured as well
      "created_at": 1753883232814202000,
      "updated_at": 1753883232814202000
    }
  ],
  "activities": [
    /** non-aggregated activities of the feed */
  ]
}
```

## Aggregation Format Syntax

The following variables are available:

- `type`: the `type` field of the `activity` (for example: `follow`)
- `time`: creation time of the activity
- `user_id`: the id of the `user` field of the `activity`
- `custom`: the `custom` field of the `activity`, nested fields can be accessed with `.` notation, for example: `custom.topic`
- `target_id`: Only defined for notification activities added with the `create_notification_activity` flag. The id of the activity which triggered the notification (`activity.notification_context.target.id` field)
- `id`: the id of the `activity` (this is a unique field and turns off aggregation, you shouldn't need to use this field in your aggregation expression)

Here are some common examples of aggregation formats:

- Per user, activity type and day:
  `{{ user_id }}_{{ type }}_{{ time.strftime("%Y-%m-%d") }}`

- Per activity type and day:
  `{{ type }}_{{ time.strftime("%Y-%m-%d") }}`

- Follows by user, everything else grouped by verb and day

```text
{% if verb == 'follow' %}
  {{ user_id }}_{{ type }}_{{ time.strftime("%Y-%m-%d") }}
{% else %}
  {{ type }}_{{ time.strftime("%Y-%m-%d") }}
{% endif %}
```

The aggregation rule uses the [Jinja2 Template Syntax](http://jinja.pocoo.org/docs/dev/). Control structures like  `if`  and  `else`  are available, as well as these filters:   `int` ,   `lower`   and   `strftime`   to format the  `time`  variable. The options for  `strftime`  are documented [here](http://strftime.org/). Please get in touch with support if you need help with your aggregation formula.

## Notification Feeds

Most often the reason you want to enable aggregation on a feed is to create a notification feed. To fully support this use-case, we also should be able to track which notifications are seen or read by users. To achieve this you can turn on `notification` tracking for feed groups.

Follow the [Notification guide](/activity-feeds/docs/<framework>/notification_feeds/) to learn more about notification feeds.

---

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

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