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

Activity selectors

Activity selectors give you control over which data is shown in a feed. For example you can decide to show only popular activities, or activities that fit the current user’s interests.

This page details what kind of activity selectors are supported by the Stream API, and how can you configure them.

Selector types

Current Feed Selector

Shows activities from the current feed. This is the selector used when reading a user feed.

Parameters

NameTypeDescriptionDefaultRequired
cutoff_timestring, must be formatted as an RFC3339 timestampActivities older than this date won’t be selectedLast 7 daysNo

Scope

The feed we’re currently reading

Example

const last10Days = new Date(Date.now() - 10 * 24 * 60 * 60 * 1000);

const view = await client.feeds.createFeedView({
  view_id: "current_feed_view",
  activity_selectors: [
    {
      type: "current_feed",
      // Optionally provide cutoff time
      cutoff_time: last10Days.toISOString(),
    },
  ],
});

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

Following Feed Selector

Shows activities from feeds the current feed follows. This is the selector used when reading a timeline feed.

Parameters

NameTypeDescriptionDefaultRequired
cutoff_timestring, must be formatted as an RFC3339 timestampActivities older than this date won’t be selectedLast 7 daysNo

Scope

Feeds followed by the feed we’re currently reading

Example

const last10Days = new Date(Date.now() - 10 * 24 * 60 * 60 * 1000);

const view = await client.feeds.createFeedView({
  view_id: "following_feed_view",
  activity_selectors: [
    {
      type: "following",
      // Optionally provide cutoff time
      cutoff_time: last10Days.toISOString(),
    },
  ],
});

const response = await client.feeds.createFeedGroup({
  feed_group_id: "myid",
  default_view_id: "following_feed_view",
});

Selects popular activities from public and visible feeds.

Popularity is computed by the following formula:

activity.popularity = reactions + comments * 2 + bookmarks * 3 + shares * 3;

Parameters

NameTypeDescriptionDefaultRequired
min_popularitynumber (only positive numbers are accepted)Minimum popularity an activity should have to be selected0No
cutoff_timestring, must be formatted as an RFC3339 timestampActivities older than this date won’t be selected-No

Scope

Any feed with public or visible visibility level.

const last10Days = new Date(Date.now() - 10 * 24 * 60 * 60 * 1000);

const view = await serverClient.feeds.createFeedView({
  view_id: "popular_feed_view",
  activity_selectors: [
    {
      type: "popular",
      // Optional parameters
      min_popularity: 70,
      cutoff_time: last10Days.toISOString(),
    },
  ],
});

const response = await client.feeds.createFeedGroup({
  feed_group_id: "myid",
  default_view_id: "popular_feed_view",
});

Proximity Activity Selector

Shows activities based on geographic proximity

Parameters

NameTypeDescriptionDefaultRequired
filterobject, see FilterYou must provide either near or within_bounds keys when using filter-No (if not provided, you need to set location data for user, see example below)
cutoff_timestring, must be formatted as an RFC3339 timestampActivities older than this date won’t be selectedLast 7 daysNo
min_popularitynumber (only positive numbers are accepted)Minimum popularity an activity should have to be selected0No

Scope

The feed we’re currently reading

Example

// Provide filter when reading the feed
await feed.getOrCreate({
  // View id is only required if you want to override the feed group's defaults
  view: "proximity_feed_view",
  filter: {
    within_bounds: {
      $eq: {
        ne_lat: 52.43017,
        ne_lng: 4.924821,
        sw_lat: 52.334272,
        sw_lng: 4.822116,
      },
    },
    // Optionally provide other filter properties, just like when querying activities
    activity_type: "hike",
  },
});

// Use either within_bounds or near filter
await feed.getOrCreate({
  // View id is only required if you want to override the feed group's defaults
  view: "proximity_feed_view",
  filter: {
    near: { $eq: { lat: 52.373558, lng: 4.885261, distance: 10 } },
  },
});

// You can omit filter if location is set for user
const me = client.state.getLatestValue().connected_user;
await client.updateUsersPartial({
  users: [
    {
      id: me.id,
      set: {
        lat: 52.373558,
        lng: 4.885261,
      },
    },
  ],
});

await feed.getOrCreate({
  // View id is only required if you want to override the feed group's defaults
  view: "proximity_feed_view",
  // If filter is not provided, API searches based on user's location
});

Interest Activity Selector

Selects activities that match the logged-in user’s interests. Interest is automatically calculated by Stream API based on which activities the user interacts with.

Parameters

NameTypeDescriptionDefaultRequired
sortarray, see SortSort optionsNewest firstNo
filterobject, see FilterAdditional filter conditions-No
min_popularitynumber (only positive numbers are accepted)Minimum popularity an activity should have to be selected0No

Scope

Feeds that are visible to the logged-in user.

Examples

const view = await client.feeds.createFeedView({
  view_id: "interest_feed_view",
  activity_selectors: [
    {
      type: "interest",
      // Optional parameters
      sort: [{ field: "popularity", direction: -1 }],
      filter: {
        activity_type: "post",
      },
    },
  ],
});

const response = await client.feeds.createFeedGroup({
  feed_group_id: "myid",
  default_view_id: "interest_feed_view",
});

Query Activity Selector

Selects activities using the provided filter query.

Parameters

NameTypeDescriptionDefaultRequired
filterobject, see FilterFilter conditions-Yes
sortarray, see SortSort optionsNewest firstNo

Scope

Feeds that are visible to the logged-in user.

Example

const view = await client.feeds.createFeedView({
  view_id: "query_feed_view",
  activity_selectors: [
    {
      type: "interest",
      filter: { search_data: { $contains: { workout_type: "hike" } } },
      // Optional parameters
      sort: [{ field: "created_at", direction: -1 }],
    },
  ],
});

const response = await client.feeds.createFeedGroup({
  feed_group_id: "myid",
  default_view_id: "query_feed_view",
});

Selector parameters

Supported values for sort and filter objects.

Sort

The following sort options are available:

Fields:

  • created_at
  • popularity

Direction: 1 or -1

Filter

The following filter options are available:

nametypedescriptionsupported operationsexample
idstring or list of stringsThe ID of the activity$in, $eq{ id: { $in: [ 'abc', 'xyz' ] } }
activity_typestring or list of stringsThe type of the activity$in, $eq{ activity_type: { $in: [ 'abc', 'xyz' ] } }
user_idstring or list of stringsThe ID of the user who created the activity$in, $eq{ user_id: { $in: [ 'abc', 'xyz' ] } }
textstringThe text content of the activity$eq, $q, $autocomplete{ text: { $q: 'popularity' } }
search_dataobjectThe extra metadata for search indexing$contains, $path_exists{ search_data: { $contains: { 'category': 'sports', 'status': 'active' } } }
interest_tagslist of stringsTags for user interests$eq, $contains{ interest_tags: { $in: [ 'sports', 'music' ] } }
filter_tagslist of stringsTags for filtering$eq, $contains{ filter_tags: { $in: [ 'categoryA', 'categoryB' ] } }
created_atstring, must be formatted as an RFC3339 timestampThe time the activity was created$eq, $gt, $lt, $gte, $lte{ created_at: { $gte: '2023-12-04T09:30:20.45Z' } }
popularitynumberThe popularity score of the activity$eq, $ne, $gt, $lt, $gte, $lte{ popularity: { $gte: 70 } }
nearobjectIndicates the GEO point to search nearby activities$eq{ near: { $eq: { lat: 40.0, lng: -74.0, distance: 200 } } }
within_boundsobjectIndicates the GEO bounds to search for activities within$eq{ within_bounds: { $eq: { ne_lat: 40.0, ne_lng: -115.0, sw_lat: 32.0, sw_lng: -125.0 } } }
visible_to_userbooleanIndicate whether the activity is visible to the user$eq{ visible_to_user: { $eq: true } }

Combining selectors

You can combine multiple selectors. The example below will include:

  • popular activities from public and visible feeds
  • activities from feeds the user follows
  • activities from feeds the user has access to, and matches the user’s interest

You can set up ranking to decide how these activities are ordered in the resulting feed.

const view = await client.feeds.createFeedView({
  view_id: "foryou_feed_view",
  activity_selectors: [
    { type: "popular" },
    { type: "following" },
    { type: "interest" },
  ],
  // Define the order with ranking
  ranking: { type: "expression", score: "decay_linear(time) * popularity" },
});

const response = await client.feeds.createFeedGroup({
  feed_group_id: "myid",
  default_view_id: "foryou_feed_view",
});
© Getstream.io, Inc. All Rights Reserved.