Feed Group Types

Last Edit: Oct 29 2020

Flat Feeds

Flat is the default feed type - and the only feed type that you can follow. It's not possible to follow either aggregated or notification feeds.

Create new feed groups based on the flat type in the dashboard.

Options

Name

Description

Default

Realtime Notifications

Enable realtime notifications

True

Aggregated Feeds

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'

You can create new aggregated feed groups in the dashboard.

Options

There are several options you can configure for aggregated feeds. The most important setting is the aggregation format. This format determines how activities are grouped together.

Name

Description

Type

Realtime Notifications

Enable realtime notifications

true

Aggregation Format

The aggregation format to use. This is used as a key to group activities by.

{{ verb }}_{{ time.strftime("%Y-%m-%d") }}

How Aggregated Feeds Work

When you insert an activity to an aggregated feed we apply the aggregation format. The aggregation format + the activity's data lead to a value for the "group". This group is used to combine the activities.

The aggregation format is applied at write time. Changing the aggregation format only affects activities inserted after the change. The dashboard allows you to preview changes on your existing data though.

Aggregation Format Syntax

The following variables are available:

  • verb the activity verb as it is sent to the APIs (e.g. "like")
  • time the activity creation date and time (or the value sent to APIs)
  • object the activity object as it is sent to the APIs (e.g. Item:13)
  • actor the activity actor (e.g. User:9)
  • feed.group the feed group name (e.g. if the feed is "notification:123", feed.group is notification)
  • feed.user_id the feed user id (e.g. if the feed is "notification:123", feed.user_id is 123))
  • id the internal unique activity id. This will be unique so if you use this nothing will be aggregated. Use this when you don't want aggregation, but only the mark_read/mark_seen functionality.

In addition, you can use any of the custom values you've provided when adding the activity.

Here are some common examples of aggregation formats:

  • Per actor, verb id and day: {{ actor }}_{{ verb }}_{{ time.strftime("%Y-%m-%d") }}

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

  • Follows by actor, everything else grouped by verb and day {% if verb == 'follow' %} {{ actor }}_{{ verb }}_{{ time.strftime("%Y-%m-%d") }} {% else %} {{ verb }}_{{ 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.

Each activity group inside an aggregated feed contains the 15 most recent activities. If you add more than 15 activities to one group, older activities will no longer be visible. Enterprise customers can contact support to increase this limit.

Data Format

The data format in which Aggregated Feeds are returned differs from regular Flat Feeds.

At the top level of the JSON response, the 'results' field contains an array of Activity Groups, plus additional metadata about the feed. Within the results array, each Activity Group contains a count of Activities and unique 'actors' contained within the group.

Notification Feeds

Notification Feed Groups extend the "Aggregated Feed Group" concept with additional features that make them well suited to notification systems:

  • Notification Feeds contain Activity Groups, each with a seen and read status field. These fields can be updated to reflect how a user has interacted with a given notification.

  • When retrieved, the Feed includes a real-time count of the total number of unseen and unread Activity Groups (notifications).

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.

You can create new Notification Feed Groups in the dashboard.

Options

There are several options to configure:

Name

Description

Type

Realtime Notifications

Enable realtime notifications

True

Aggregation Format

The aggregation format to use. The default {{ verb.id }}_{{ time.strftime("%Y-%m-%d") }} (verbs grouped by day) or {{ id }} (to achieve a single activity per group) are most commonly used.

{{ verb }}_{{ time.strftime("%Y-%m-%d") }}

Data Format

Similar to Aggregated Feeds, the data format in which Notification Feeds are retrieved differs from regular Flat Feeds.

At the top level of the JSON response the results field contains an array of Activity Groups, along with overall unseen and unread counts and other metadata about the feed. Within the results array, each Activity Group contains the additional status fields that indicate the group is seen/read.

When reading the feed, set the mark_read and mark_seen parameter. The next time the feed is read, the seen and/or read status will be updated accordingly. Please keep in mind that the first call will always return the read and seen state prior to the change. This allows you to read a notification feed, mark activities as read or seen and display them according to the current state in a single API request.

Comma-separated list of activity group ids to mark as read, or True which means all

Comma-separated list of activity group ids to mark as seen, or True which means all

Name Type Description Default Optional
mark_read array -
mark_seen array -

If passing IDs to mark_seen or mark_read, be sure to pass the ID of the activity group as returned by the API, not the IDs of individual activities.

Here's an example:


// Mark all activities in the feed as seen
notificationFeed.get({mark_seen:true})
    .then(function(data) { /* on success */ })
    .catch(function(reason) { /* on failure */ });

// Mark some activities as read via specific Activity Group Ids
notificationFeed.get({mark_read: ['activityGroupIdOne', 'activityGroupIdTwo']})
    .then(function(data) { /* on success */ })
    .catch(function(reason) { /* on failure */ });
                    

# Mark all activities in the feed as seen
results = notification_feed.get(mark_seen=True)['results']

# Mark some activities as read via specific Activity Group Ids
notification_feed.get(mark_read=[results[0]['id'], results[1]['id']])
                    

# Mark all activities in the feed as seen
result = notification_feed.get(:limit=>5, :offset=>;0, :mark_seen=>;true)

# Mark some activities as read via specific Activity Group Ids
result = notification_feed.get(:limit=>5, :mark_read=>['activity_group_id_1', 'activity_group_id_2'])
                    

# Mark all activities in the feed as seen
$options = ['mark_seen' => true];
$results = $notificationFeed->getActivities(0, 10, $options);

# Mark some activities as read via specific Activity Group Ids
$options = ['mark_read' => ['activity_group_id_1', 'activity_group_id_2']];
$results = $notificationFeed->getActivities(0, 10, $options);
                    

NotificationFeed notifications = client.notificationFeed("notifications", "1");
// Mark all activities in the feed as seen
List<notificationgroup<activity>> activityGroups = notifications.getActivities(new Limit(5), new ActivityMarker().allSeen()).get();
for (NotificationGroup<activity> group : activityGroups) {
    // ...
}
// Mark some activities as read via specific Activity Group Ids
activityGroups = notifications.getActivities(new Limit(5), new ActivityMarker().read("groupID1", "groupID2" /* ... */)).get();</activity></notificationgroup<activity>
                    

notifications := client.NotificationFeed("notifications", "1")
// Mark all activities in the feed as seen
resp, err := notifications.GetActivities(stream.WithNotificationsMarkSeen(true))
if err != nil {
    panic(err)
}
for _, activity := range resp.Results {
    // ...
}
// Mark some activities as read via specific Activity Group Ids
resp, err = notifications.GetActivities(stream.WithNotificationsMarkRead(
    false,              // don't mark all
    groupID1, groupID2, //...
))
                    

// Mark all activities in the feed as seen:
notificationFeed.get(markOption: .seenAll) { result in /* ... */ }

// Mark some activities as read via specific Activity Group Ids:
notificationFeed.get(markOption: .read(["activityGroupIdOne", "activityGroupIdTwo"]) { result in /* ... */ }
                    

// Mark all activities in the feed as seen
var result = await notificationFeed.GetActivities(0, 5, null, ActivityMarker.Mark().AllSeen());

// Mark some activities as read via specific Activity Group Ids
                    

You'll often want to listen to feed changes in real-time. This is explained in the section on real-time updates.

Each activity group inside a notification feed contains the 15 most recent activities. If you add more than 15 activities to one group, older activities will no longer be visible. Enterprise customers can contact support to increase this limit.