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.
Each activity selector selects the first 1000 activities that match its selection criteria.
This page details what kind of activity selectors are supported by the Stream API, and how can you configure them.
You can create custom feed groups or update the built-in groups with your own activity selector configuration.
Activities older than this window won't be selected
-
No
min_popularity
number (only positive numbers are accepted)
Minimum popularity an activity should have to be selected
0
No
Scope
Any feed with public or visible visibility level.
Example
// Provide filter when reading the feedawait feed.getOrCreate({ 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 filterawait feed.getOrCreate({ filter: { near: { $eq: { lat: 52.373558, lng: 4.885261, distance: 10 } }, },});// You can omit filter if location is set for userconst me = client.state.getLatestValue().connected_user;await client.updateUsersPartial({ users: [ { id: me.id, set: { lat: 52.373558, lng: 4.885261, }, }, ],});await feed.getOrCreate({ // If filter is not provided, but feed group has proximity selector, API searches based on user's location});
// Provide filter when reading the feedawait feed.getOrCreate({ 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 filterawait feed.getOrCreate({ filter: { near: { $eq: { lat: 52.373558, lng: 4.885261, distance: 10 } }, },});// You can omit filter if location is set for userconst me = client.state.getLatestValue().connected_user;await client.updateUsersPartial({ users: [ { id: me.id, set: { lat: 52.373558, lng: 4.885261, }, }, ],});await feed.getOrCreate({ // If filter is not provided, but feed group has proximity selector, API searches based on user's location});
// Provide filter when reading the feedawait feed.getOrCreate({ 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 filterawait feed.getOrCreate({ filter: { near: { $eq: { lat: 52.373558, lng: 4.885261, distance: 10 } }, },});// You can omit filter if location is set for userconst me = client.state.getLatestValue().connected_user;await client.updateUsersPartial({ users: [ { id: me.id, set: { lat: 52.373558, lng: 4.885261, }, }, ],});await feed.getOrCreate({ // If filter is not provided, but feed group has proximity selector, API searches based on user's location});
Selects activities that match the logged-in user's interests. Interests are automatically calculated for each user by Stream API based on which activities the user interacts with.
Interests are based on activity topics. Topics are stored in the interest_tags field of an activity. It can be computed automatically using activity processors or set when creating an activity.
Selects activities from feeds that are suggested to the user based on follow suggestions. This selector uses Stream's intelligent follow suggestion algorithm to discover relevant content from feeds the user might want to follow.
This selector requires an authenticated user. It will return empty results for anonymous users.
Activities older than this window won't be selected
-
No
min_popularity
number (only positive numbers are accepted)
Minimum popularity an activity should have to be selected
5
No
activities_per_feed
number (1-100)
Number of activities to select from each suggested feed
2
No
max_suggested_feeds
number (1-50)
Maximum number of suggested feeds to consider
10
No
min_feed_score
number (0.0-1.0)
Minimum recommendation score for a feed to be included in suggestions
0.3
No
Scope
Activities from user feeds that are suggested based on the follow suggestion algorithm. The selector always suggests feeds from the "user" feed group, regardless of which feed group is being viewed.
When filtering by filter_tags, a plain array (or $eq) uses AND-logic: the activity must contain all of the specified tags. Use $in if you want OR-logic, where the activity must contain any of the specified tags.
The filter syntax also supports $or and $and:
// Get all the activities where filter tags contain both "green" and "orange"let filter = .and([ .in(.filterTags, ["green"]), .in(.filterTags, ["orange"])])
// Get all the activities where filter tags contain both "green" and "orange"val filter = Filters.and( ActivitiesFilterField.filterTags.`in`("green"), ActivitiesFilterField.filterTags.`in`("orange"),)
// Get all the activities where filter tags contain both "green" and "orange"const filter = { $and: [{ filter_tags: ["green"] }, { filter_tags: ["orange"] }],};
// Get all the activities where filter tags contain both "green" and "orange"const filter = { $and: [{ filter_tags: ["green"] }, { filter_tags: ["orange"] }],};
// Get all the activities where filter tags contain both "green" and "orange"const filter = { $and: [{ filter_tags: ["green"] }, { filter_tags: ["orange"] }],};
// Get all the activities where filter tags contain both "green" and "orange"const filter = Filter.and([ Filter.in_(ActivitiesFilterField.filterTags, ['green']), Filter.in_(ActivitiesFilterField.filterTags, ['orange']),])
// Get all the activities where filter tags contain both "green" and "orange"const filter = { $and: [ { filter_tags: ["green"] } { filter_tags: ["orange"] } ],}
// Get all the activities where filter tags contain both "green" and "orange"filter := map[string]any{ "$and": []map[string]any{ {"filter_tags": []string{"green"}}, {"filter_tags": []string{"orange"}}, },}
// Get all the activities where filter tags contain both "green" and "orange"Map<String, Object> filter = new HashMap<>();List<Map<String, Object>> andConditions = List.of( Map.of("filter_tags", List.of("green")), Map.of("filter_tags", List.of("orange")));filter.put("$and", andConditions);
// Get all the activities where filter tags contain both "green" and "orange"var filter = = new{ and = new[] { new { filter_tags = new[] { "green" } }, new { filter_tags = new[] { "orange" } } }}
# Get all the activities where filter tags contain both "green" and "orange"filter = { "$and": [ {"filter_tags": ["green"]}, {"filter_tags": ["orange"]} ]}
# Get all the activities where filter tags contain both "green" and "orange"filter = { "$and" => [ { "filter_tags" => ["green"] }, { "filter_tags" => ["orange"] } ]}
It's also possible to provide filters when reading a feed. When providing filter to read a feed, group-level filters are ignored.
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 match the user's interest
Each activity selector selects the first 1000 activities that match its selection criteria. We suggest taking adventage of the different config options for the selectors to make sure that the selectors return the most relevant activities. When combining selectors, every selector runs independently, so in this case 3 * 1000 activities can be selected.
Once selectors run, ranking is applied to the activities that are returned by the selectors. Even if you have multiple selectors, ranking only runs once.
You can't use more than 3 selectors in a feed group/view configuration.
For activities selected by current and following selectors WebSocket events are delivered to clients (as long as watch: true is used to read the feed). However, for activities selected by other selectors, WebSocket events are not delivered. This means you won't be receiving activity.new events, or updates if other users like/comment/etc. on the activity.
If you combine activity selectors, you'll be still receiving WebSocket events for activities selected by current and following selectors.
Feed groups let you define what activities should be included in the feed and the ranking to sort these activities.
By default all feeds in the given group will have the same settings. However, you might want to experiment with different selectors and rankings. Feed views let you do that by overriding the group's default settings.
Note that any write operation to feed groups/views can take up to 30 seconds to propagate to all API nodes.