Activity Feeds v3 is in beta — try it out!

Feeds

Creating a Feed

When using server-side SDKs, the user_id parameter is required in the getOrCreate request. It’s needed in order to automatically create a user. Client-side SDKs do not require this parameter as the user is authenticated via token.

$feed = $feedsClient->feed('user', 'john');
$feedResponse = $feed->getOrCreateFeed(
    new GeneratedModels\GetOrCreateFeedRequest(userID: 'john')
);

// More options
$feed2 = $feedsClient->feed('user', 'jack');
$feedResponse2 = $feed2->getOrCreateFeed(
    new GeneratedModels\GetOrCreateFeedRequest(
        userID: 'jack',
        data: new GeneratedModels\FeedInput(
            description: 'My personal feed',
            name: 'jack',
            visibility: 'public'
        )
    )
);

Built-in feed groups

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
storyA feed set up for users to post story activities (activities with expiration data)
storiesA timeline feed which can be used to follow other users’ stories.

Reading a Feed

Here is a basic example of how to read a feed:

$feed = $feedsClient->feed('user', 'john');

$response = $feed->getOrCreateFeed(
    new GeneratedModels\GetOrCreateFeedRequest(userID: 'john')
);

// Access feed data
$feedData = $response->getData()->feed;
$activities = $response->getData()->activities;
$members = $response->getData()->members;

The response will contain the following data.

You have more options when reading a feed, let’s go over a few:

$feed = $feedsClient->feed('user', 'jack');

$response = $feed->getOrCreateFeed(
    new GeneratedModels\GetOrCreateFeedRequest(
        limit: 10,
        filter: (object)['filter_tags' => ['green']],
        externalRanking: (object)['user_score' => 0.8],
        followersPagination: new GeneratedModels\PagerRequest(limit: 10),
        followingPagination: new GeneratedModels\PagerRequest(limit: 10),
        memberPagination: new GeneratedModels\PagerRequest(limit: 10),
        view: 'myview',
        userID: 'jack'
    )
);

Feed Pagination

Here is how you can read the next page on the feed:

$feed = $feedsClient->feed('user', 'jack');

$feedResponse1 = $feed->getOrCreateFeed(
    new GeneratedModels\GetOrCreateFeedRequest(userID: "jack", limit: 10)
);

$feedResponse2 = $feed->getOrCreateFeed(
    new GeneratedModels\GetOrCreateFeedRequest(userID: "jack", limit: 10, next: $feedResponse1->getData()->next)
);

Filtering Examples

filter provides a performant way to read a feed, and only select activities that match a given filter.

Please note that for search feature you should use query activities endpoint

$feed = $feedsClient->feed('user', '123');

// Add a few activities
$feedsClient->upsertActivities(
    new GeneratedModels\UpsertActivitiesRequest(
        activities: [
            [
                'feeds' => [$feed->getFeedIdentifier()],
                'type' => 'post',
                'text' => 'first',
                'filter_tags' => ['green', 'blue'],
                'user_id' => '123',
            ],
            [
                'feeds' => [$feed->getFeedIdentifier()],
                'type' => 'post',
                'text' => 'second',
                'filter_tags' => ['yellow', 'blue'],
                'user_id' => '123',
            ],
            [
                'feeds' => [$feed->getFeedIdentifier()],
                'type' => 'post',
                'text' => 'third',
                'filter_tags' => ['orange'],
                'user_id' => '123',
            ],
        ]
    )
);

// Now read the feed, this will fetch activity 1 and 2
$response = $feedsClient->getOrCreateFeed(
    'user',
    '123',
    new GeneratedModels\GetOrCreateFeedRequest(
        filter: (object)['filter_tags' => ['blue']],
        userID: '123'
    )
);

The filter syntax also supports $or and $and, so here’s an example that’s a little more complicated:

$response = $feedsClient->getOrCreateFeed(
    'user',
    '123',
    new GeneratedModels\GetOrCreateFeedRequest(
        filter: (object)['and' => [
            'filter_tags' => ['green'],
            'filter_tags' => ['orange'],
        ]],
        userID: '123'
    )
);

Filters

What filters you can use when reading a feed depends on the feed group (or view, if provided) configuration.

The activity selectors page explains this in detail, but some quick examples: the user group uses current selector, and the timeline group the following selector by default.

The following filter options are available for the following selector:

nametypedescriptionsupported operationsexample
idstring or list of stringsThe ID of the activity$in, $eq{ id: { $in: [ 'abc', 'xyz' ] } }
filter_tagslist of stringsTags for filtering$eq, $contains{ filter_tags: { $in: [ 'categoryA', 'categoryB' ] } }

The following filter options are available for the current, popular, interest, proximity and query selectors:

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 } } }

The filter syntax also supports $or and $and:

$filter = (object)['and' => [
  'filter_tags' => ['green'],
  'filter_tags' => ['orange'],
]]

When providing filter to read a feed, activity selector filters on group/view level are ignored.

Overview of built-in fields

GetOrCreateFeedResponse

NameTypeDescriptionConstraints
activitiesActivityResponse[]-Required
aggregated_activitiesAggregatedActivityResponse[]-Required
createdboolean-Required
durationstringDuration of the request in millisecondsRequired
feedFeedResponse-Required
followersFollowResponse[]-Required
followers_paginationPagerResponse--
followingFollowResponse[]-Required
following_paginationPagerResponse--
member_paginationPagerResponse--
membersFeedMemberResponse[]-Required
nextstring--
notification_statusNotificationStatusResponse--
pinned_activitiesActivityPinResponse[]-Required
prevstring--

FeedResponse

NameTypeDescriptionConstraints
created_atnumberWhen the feed was createdRequired
created_byUserResponseUser who created the feedRequired
customobjectCustom data for the feed-
deleted_atnumberWhen the feed was deleted-
descriptionstringDescription of the feedRequired
feedstringFully qualified feed ID (group_id:id)Required
filter_tagsstring[]Tags used for filtering feeds-
follower_countintegerNumber of followers of this feedRequired
following_countintegerNumber of feeds this feed followsRequired
group_idstringGroup this feed belongs toRequired
idstringUnique identifier for the feedRequired
member_countintegerNumber of members in this feedRequired
namestringName of the feedRequired
own_capabilitiesFeedOwnCapability[]Capabilities the current user has for this feed-
own_followsFollowResponse[]Follow relationships where the current user's feeds are following this feed-
own_membershipFeedMemberResponseMembership information for the current user in this feed-
pin_countintegerNumber of pinned activities in this feedRequired
updated_atnumberWhen the feed was last updatedRequired
visibilitystringVisibility setting for the feed-

Feed Members

You can add and remove members to a feed. This is useful for building communities where a set of users can add content to the feed.

It’s not possible to set/update member role on client-side. Use server-side SDKs for this. When adding members client-side all new members will have feed_member role:

$feed = $feedsClient->feed('user', 'community_id');

// The following methods are available to edit the members of a feed
$feed->updateFeedMembers(
    new GeneratedModels\UpdateFeedMembersRequest(
        operation: 'upsert',
        members: [
            new GeneratedModels\FeedMemberRequest(
                userID: 'john',
                role: 'feed_moderator',
                custom: (object)['joined' => '2024-01-01']
            ),
        ]
    )
);

// Remove members
$feed->updateFeedMembers(
    new GeneratedModels\UpdateFeedMembersRequest(
        operation: 'remove',
        members: [
            new GeneratedModels\FeedMemberRequest(userID: 'john'),
            new GeneratedModels\FeedMemberRequest(userID: 'jane'),
        ]
    )
);

// Set members (overwrites the list)
$feed->updateFeedMembers(
    new GeneratedModels\UpdateFeedMembersRequest(
        operation: 'set',
        members: [
            new GeneratedModels\FeedMemberRequest(
                userID: 'john',
                role: 'feed_moderator'
            ),
        ]
    )
);

Feed members vs followers

Followers and members might seem like similar concepts, but they serve two different purposes with some key differences.

Followers can only be feeds (for example the timeline feed of Alice follows the user feed of Bob). Followers’ aim is to access the content of a feed they’re interested in and interact with it.

Members can only be users (for example Alice adds Bob as a member to her feed about “Travel Hacks”). The aim of feed members is usually to help out with admin tasks (helpful if you want to build apps similar to Facebook pages) or to decide what activities a user has access to using membership levels (for example Bob becomes a premium member in Alice’s community).

Member invites

You can invite members with the invite flag, where invited users can accept or reject the membership.

$feed = $feedsClient->feed('user', 'alice');

// Invite a member
$feed->updateFeedMembers(
    new GeneratedModels\UpdateFeedMembersRequest(
        operation: 'upsert',
        members: [
            new GeneratedModels\FeedMemberRequest(
                userID: 'john',
                role: 'feed_moderator',
                invite: true,
                custom: (object)['reason' => 'community builder']
            ),
        ]
    )
);

// Accept feed member invite
$feed->acceptFeedMemberInvite(
    new GeneratedModels\AcceptFeedMemberInviteRequest(
        userID: 'john'
    )
);

// Reject feed member invite
$feed->rejectFeedMemberInvite(
    new GeneratedModels\RejectFeedMemberInviteRequest(
        userID: 'john'
    )
);

Query Feeds

Querying feeds allows you to do things like showing the list of communities you’ve joined.

Here’s an example of how to query feeds:

Querying My Feeds

// First page query
$firstPage = $feedsClient->queryFeeds(
    new GeneratedModels\QueryFeedsRequest(
        filter: (object)['created_by_id' => 'john'],
        limit: 10,
        sort: [
            ['field' => 'created_at', 'direction' => -1]
        ]
    )
);

// Second page using next cursor from first page
$secondPage = $feedsClient->queryFeeds(
    new GeneratedModels\QueryFeedsRequest(
        filter: (object)['created_by_id' => 'john'],
        limit: 10,
        sort: [
            ['field' => 'created_at', 'direction' => -1]
        ],
        next: $firstPage->getData()->next
    )
);

Querying Feeds Where I Am a Member

$response = $feedsClient->queryFeeds(
    new GeneratedModels\QueryFeedsRequest(
        filter: (object)[
            'members' => (object)['$in' => ['john']]
        ]
    )
);

Querying feeds by name or visibility

// Search public feeds by name
$response = $feedsClient->queryFeeds(
    new GeneratedModels\QueryFeedsRequest(
        filter: (object)[
            'visibility' => (object)['$eq' => 'public'],
            'name' => (object)['$q' => 'Sports']
        ]
    )
);

// Search public feeds by description
$response2 = $feedsClient->queryFeeds(
    new GeneratedModels\QueryFeedsRequest(
        filter: (object)[
            'visibility' => 'public',
            'description' => (object)['$autocomplete' => 'tech']
        ]
    )
);

Querying feeds by creator name

$response = $feedsClient->queryFeeds(
    new GeneratedModels\QueryFeedsRequest(
        filter: (object)[
            'visibility' => 'public',
            'created_by.name' => (object)['$q' => 'Thompson']
        ]
    )
);

Feeds Queryable Built-in Fields

nametypedescriptionsupported operationsexample
idstring or list of stringsThe ID of the feed$in, $eq{ id: { $in: [ 'abc', 'xyz' ] } }
group_idstring or list of stringsThe ID of the group this feed belongs to$in, $eq{ group_id: { $in: [ 'abc', 'xyz' ] } }
feedstring or list of stringsThe fully qualified feed ID (group_id:id)$in, $eq{ fid: { $in: [ 'abc', 'xyz' ] } }
visibilitystring or list of stringsThe visibility setting of the feed$in, $eq{ visibility: { $eq: 'public' } }
created_by_idstring or list of stringsThe ID of the user who created the feed$in, $eq{ created_by_id: { $in: [ 'abc', 'xyz' ] } }
created_by.namestringThe name of the user who created the feed$eq, $q, $autocomplete{ 'created_by.name': { $autocomplete: 'Frank' } }
namestringThe name of the feed$eq, $q, $autocomplete{ name: { $q: 'Sports' } }
descriptionstringThe description of the feed$eq, $q, $autocomplete{ description: { $autocomplete: 'tech' } }
member_countnumberThe number of members in this feed$eq, $ne, $gt, $lt, $gte, $lte{ member_count: { $gt: 100 } }
memberslist of stringsThe list of members in this feed$in{ members: { $in: [ 'bob', 'alice' ] } }
following_countnumberThe number of feeds this feed follows$eq, $ne, $gt, $lt, $gte, $lte{ following_count: { $gt: 100 } }
following_feedslist of stringsThe list of feeds this feed follows$in{ following_feeds: { $in: [ 'feed1', 'feed2' ] } }
follower_countnumberThe number of followers of this feed$eq, $ne, $gt, $lt, $gte, $lte{ follower_count: { $gt: 100 } }
created_atstring, RFC3339 timestampThe time the feed was created$eq, $gt, $lt, $gte, $lte{ created_at: { $gte: '2023-12-04T09:30:20.45Z' } }
updated_atstring, RFC3339 timestampThe time the feed was updated$eq, $gt, $lt, $gte, $lte{ updated_at: { $gte: '2023-12-04T09:30:20.45Z' } }
filter_tagslist of stringsTags for filtering the feed$eq, $contains, $in{ filter_tags: { $in: [ 'sports', 'news' ] } }

Feeds can be sorted by created_at, updated_at, member_count, follower_count, and following_count.

Be sure to reach out to support if you need additional query feed capabilities.

Query Feed Members

You can query the members of a feed. This is useful for showing the list of members in a community.

$response = $feedsClient->queryFeedMembers('stock', 'apple', new GeneratedModels\QueryFeedMembersRequest(
  filter: (object)[
    'role' => 'moderator'
  ]
));

Feed Members Queryable Built-in Fields

nametypedescriptionsupported operationsexample
user_idstring or list of stringsThe ID of the user who is a member of the feed$in, $eq{ user_id: { $eq: 'user_123' } }
rolestring or list of stringsThe role of the member$in, $eq{ role: { $in: [ 'admin', 'moderator', 'member' ] } }
statusstring or list of stringsThe membership status$in, $eq{ status: { $in: [ 'member', 'pending', 'rejected' ] } }
created_atstring, must be formatted as an RFC3339 timestampThe time the membership was created$eq, $gt, $gte, $lt, $lte{ created_at: { $gte: '2023-12-04T09:30:20.45Z' } }
updated_atstring, must be formatted as an RFC3339 timestampThe time the membership was last updated$eq, $gt, $gte, $lt, $lte{ updated_at: { $gte: '2023-12-04T09:30:20.45Z' } }
© Getstream.io, Inc. All Rights Reserved.