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

Membership levels

Membership levels let you create different tiers among a feed’s audience, and control which activities are available to which users. This gives users the option to post content that only premium members can see.

This page details how you can set up membership levels.

Create membership levels

Use server-side SDKs to create membership levels. You can define unified membership levels for your application, or scope them (for example, to specific users) using custom data.

premiumResponse, err := feedsClient.CreateMembershipLevel(context.Background(), &getstream.CreateMembershipLevelRequest{
  ID:          "premium",
  Name:        "Premium",
  Description: getstream.PtrTo("Weekly QA with me"),
  Custom: map[string]any{
    // Lets you query membership levels by creator.id, useful if you want to scope membership levels to users
    "creator_id": "creator_123",
  },
  // Lets you sort membership levels by priority
  Priority: getstream.PtrTo(100),
  // Users with this membership level can see activities with these tags
  Tags:     []string{"premium"},
})
if err != nil {
  log.Fatal("Error creating Premium membership level:", err)
}
log.Printf("Created Premium membership level: %+v", premiumResponse.Data.MembershipLevel)

innerCircleResponse, err := feedsClient.CreateMembershipLevel(context.Background(), &getstream.CreateMembershipLevelRequest{
  ID:          "inner-circle",
  Name:        "Inner Circle",
  Description: getstream.PtrTo("You can see new videos a week earlier, and weekly QA with me"),
  Custom: map[string]any{
    "creator_id": "creator_123",
  },
  Priority: getstream.PtrTo(200),
  // Users in this membership level can see premium and inner circle content as well
  Tags:     []string{"premium", "inner-circle"},
})
if err != nil {
  log.Fatal("Error creating Inner Circle membership level:", err)
}
log.Printf("Created Inner Circle membership level: %+v", innerCircleResponse.Data.MembershipLevel)

Assign membership level to users

To assign a membership level to a user, you need to add them as a feed member, and set their membership level.

Users still have to follow the feed to see posts in their timelines. Membership levels are only used for authorization purposes.

_, err = feedsClient.UpdateFeedMembers(context.Background(), "creator", "creator-feed-id", &getstream.UpdateFeedMembersRequest{
  Operation: "upsert",
  Members: []getstream.FeedMemberRequest{
    {
      UserID:           "premium-fan-id",
      MembershipLevel:  getstream.PtrTo("premium-membership-level-id"),
    },
  },
})
if err != nil {
  log.Fatal("Error updating feed members:", err)
}

fmt.Println("Feed members updated successfully!")

Create a premium activity

let privateActivity = try await feed.addActivity(
    request: .init(
        text: "Premium content",
        type: "post",
        visibility: .tag,
        visibilityTag: "premium"
    )
)
// Premium users can see full activity, others a preview

Users who don’t have access to the post will only see a preview:

  • No attachments are shown
  • The activity text is truncated (first 20 characters are shown, for example: “Behind the scenes of…”)

Query membership levels

response, err := client.Feeds().QueryMembershipLevels(context.Background(), &getstream.QueryMembershipLevelsRequest{
  Filter: map[string]any{
    "custom": map[string]any{
      "$contains": map[string]any{
        "creator_id": creatorID,
      },
    },
  },
  Sort: []getstream.SortParamRequest{
    {
      Field:     getstream.PtrTo("priority"),
      Direction: getstream.PtrTo(-1),
    },
  },
})
if err != nil {
  log.Fatal("Error querying membership levels:", err)
}

fmt.Printf("Found %d membership levels:\n", len(response.Data.MembershipLevels))

Filter options

nametypedescriptionsupported operationsexample
idstring or list of stringsThe ID of the membership level$in, $eq{ id: { $in: [ 'abc', 'xyz' ] } }
namestring or list of stringsThe name of the membership level$in, $eq{ name: { $in: [ 'abc', 'xyz' ] } }
descriptionstring or list of stringsThe description of the membership level$in, $eq{ description: { $in: [ 'abc', 'xyz' ] } }
prioritynumberThe priority of the membership level$eq, $gt, $lt, $gte, $lte{ priority: { $gte: 100 } }
tagslist of stringsTags the membership level grants access to$eq, $in, $contains{ tags: { $in: [ 'premium', 'inner-circle' ] } }
customobjectCustom data of the membership level$contains, $path_exists{ custom: { $contains: {creator_id: '123' } } }
created_atstring, must be formatted as an RFC3339 timestampThe time the membership level was created$eq, $gt, $lt, $gte, $lte{ created_at: { $gte: '2023-12-04T09:30:20.45Z' } }
updated_atstring, must be formatted as an RFC3339 timestampThe time the membership level was last updated$eq, $gt, $lt, $gte, $lte{ updated_at: { $gte: '2023-12-04T09:30:20.45Z' } }

Sort options

Fields:

  • priority
  • created_at
  • updated_at

Direction: 1 or -1

Update membership levels

updateRequest := &getstream.UpdateMembershipLevelRequest{
  Name:        getstream.PtrTo("Premium"),
  Description: getstream.PtrTo("Weekly QA with me"),
  Custom:      customData,
  Priority:    getstream.PtrTo(100),
  Tags:        []string{"premium"},
}

response, err := feedsClient.UpdateMembershipLevel(context.Background(), premiumMembershipLevelID, updateRequest)

if err != nil {
  log.Fatal("Error updating membership level:", err)
}

log.Printf("Successfully updated membership level: %+v\n", response.Data.MembershipLevel)

Delete membership level

response, err := feedsClient.DeleteMembershipLevel(ctx, premiumMembershipLevelID, &getstream.DeleteMembershipLevelRequest{})
if err != nil {
  log.Fatal("Error deleting membership level:", err)
}
© Getstream.io, Inc. All Rights Reserved.