const aggregation_view = await serverClient.feeds.createFeedView({
view_id: uuidv4(),
// Group by activity type and day
aggregation: { format: '{{ type }}-{{ time.strftime("%Y-%m-%d") }}' },
});
const myNotificationGrpup = await serverClient.feeds.createFeedGroup({
feed_group_id: "myid",
default_view_id: aggregation_view.feed_view.view_id,
// Enable notification tracking
notification: {
track_read: true,
track_seen: true,
},
});
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:
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:
{
"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
: thetype
field of theactivity
(for example:follow
)time
: creation time of the activityuser_id
: the id of theuser
field of theactivity
custom
: thecustom
field of theactivity
, nested fields can be accessed with.
notation, for example:custom.topic
target_id
: Only defined for notification activities added with thecreate_notification_activity
flag. The id of the activity which triggered the notification (activity.notification_context.target.id
field)id
: the id of theactivity
(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
{% 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. 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. 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 to learn more about notification feeds.
- I'm working with the Stream Feeds React Native SDK and would like to ask questions about this documentation page: https://getstream.io/activity-feeds/docs/react-native/aggregation.md
- View as markdown
- Open in ChatGPT
- Open in Claude