Activity Feeds V3 is in closed alpha — do not use it in production (just yet).

Intro & Defaults

Creating Feed Groups & Defaults

There are several feed groups setup by default.

GroupDescription
userA feed setup for the content a user creates. Typically you add activities here when someone writes a post
timelineThe timeline feed is used when you’re following. So if user Charlie is following John, timeline:charlie would follow user:john
foryouA version of the timeline feed that adds popular content, and priorities popularity over recency
notificationA notification feed. Think of the bell icon you see in most apps

You can also create your own feed group. Here’s how to create a feed group using the API:

const following_view = await serverClient.feeds.createFeedView({
  view_id: uuidv4(),
  activity_selectors: [
    {
      type: "following",
    },
  ],
  ranking: { type: "time" },
});

const myFeedGroup = await serverClient.feeds.createFeedGroup({
  feed_group_id: "myid",
  default_view_id: following_view.feed_view.view_id,
  activity_processors: [
    {
      type: "topic",
    },
  ],
  custom: {
    description: "My custom feed group",
  },
});

Activity Ranking

When ranking activities you can specify a ranking formula.

const view = await serverClient.feeds.createFeedView({
  view_id: uuidv4(),
  ranking: { type: "time", score: "decay_linear(time) * popularity" },
  activity_selectors: [
    {
      type: "following",
    },
  ],
});

const response = await serverClient.feeds.createFeedGroup({
  feed_group_id: "mytimeline",
  default_view_id: view.feed_view.view_id,
});

For you Feeds

Many apps want to have a “for you” or personalized feed. There are a couple benefits to a personalized feed:

  • Works well even if your users don’t spend much time setting up follows
  • Can be a mechanism to discover new content or things to follow

Stream offers a few built-in methods to create a for you feed and gives you the API access to do more advanced customization if needed.

This next example is a bit more complicated. It uses an activity processor to add topic data to activities and ranks content you’re likely to engage with higher in the feed.

const view = await serverClient.feeds.createFeedView({
    view_id: uuidv4(),
    ranking: { type: 'expression', score: 'decay_linear(time) * popularity' },
    // Activity selectors change which activities are included in the feed
    // The default "following" selectors gets activities from the feeds you follow
    // The "popular" activity selectors includes the popular activities
    // And "interest" activities similar to activities you've engaged with in the past
    // You can use multiple selectors in 1 feed
    activity_selectors: [
        {
            type: 'popular',
        },
        {
            type: 'following',
        },
        {
            type: 'interest',
        },
    ],
    // Rank for a user based on interest score
    // This calculates a score 0-1.0 of how well the activity matches the user's prior interest
    ranking: {
        type: "interest",
        score: "decay_linear(time) * interest * decay_linear(popularity)"
    },

});

const response = await serverClient.feeds.createFeedGroup({
    feed_group_id: 'mytimeline',
    default_view_id: view.feed_view.view_id,
    // Run the activity processors to analyse topics for text & images
    activity_processors: [
        {type: 'image_topic'},
        {type: 'text_topic'}
    ]
});

const forYouFeed = client.feeds.feed(group: "mytimeline", id: "thierry")
const response = await forYouFeed.getOrCreate({ user_id: 'thierry' })

Aggregation & Notification Feeds

Aggregation groups similar activities together, which is useful for notification feeds and reducing noise.

Aggregation Format

You can create your own aggregated feeds:

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

Notification Feed Example

The built-in notification feed comes with the necessary configurations:

const notificationFeed = client.feed(group: "notification", id: "jane")

// Read notifications
const notifications = (await notificationFeed.getOrCreate({
    limit: 20,
})).aggregated_activities;

Marking Notifications as Read

await notificationFeed.markActivity({
  // Mark all notifications as read...
  mark_all_read: true,
  // ...or only selected ones
  mark_read: [
    /* group names to mark as read */
  ],
});

Updating feed groups

It’s possible to update any custom or built-in feed group or view

await serverClient.feeds.updateFeedView({
  view_id: "<view id to update?",
  // Fields to update
});
await client.feeds.updateFeedGroup({
  feed_group_id: "<id of feed group to update>",
  // Fields to update
});

Deleting feed groups

await serverClient.feeds.deleteFeedView({
  view_id: "view id to delete",
});
await serverClient.feeds.deleteFeedGroup({
  feed_group_id: "<feed group id to delete>",
});
© Getstream.io, Inc. All Rights Reserved.