The Stream Blog

Example Ranking Methods for Your Feeds

In this short tutorial we will show you how to use Custom Ranking for your activity streams and news feeds. By default all feeds on Stream are ranked chronologically. Custom ranking allows you to take full control over how your feeds are sorted. Some common use cases include:

  • Showing popular activities higher in the feed
  • Pinning activities to the top
  • Increasing the rank of events that are about to start
  • Boosting editorial or promoted content

This post will show you clear examples for all 4 of those use cases, but first let’s go over the basics of ranked feeds.

Ranked feeds – The basics

Ranked feeds allow you to define a scoring formula for your activities. Within the scope of the ranking method you have access to any of the custom attributes you’ve added to your activities. Here’s a very basic ranking method:

    "score": "decay_linear(time) * popularity ^ 0.5",
     "defaults": {
        "popularity": 1

The above uses a simple linear time decay on the “time” field of the activity. It combines the decay score with the square root of a custom attribute called “popularity” sent as part of the activity. If the popularity attribute is missing from the activity payload, we’ll use the default of 1.

Ranked feeds – Examples

Ranking methods are a very powerful tool. The following five examples will give you a bit of inspiration for your own application.

Showing popular activities higher in the feed (Reddit style):

Variations of the following “viral” formula can be used to generate a ranking that is a function of activity popularity and creation time:

{"score": "decay_gauss(time)*log(likes+0.5*comments+1)"}

Note the use of the log function to limit the effect of very popular activities. The speed of the decay function is also configurable. You can learn more about that in the docs.

“Pinning” activities:

Another common use case is forcing activities to always appear at the top of a feed, sometimes called “pinning”. This method ensures that activities with the custom attribute “is_pinned” set to a value of 1 will always show up at the top of the feed.

{"score": "decay_linear(time) +is_pinned","defaults": {"is_pinned": 0}}

Increasing the rank of events that are about to start

Another common use is applications which want to show specific activities when they are about to start. Some use cases include soccer matches, or tickets going on sale, for example.

Here’s an example that shows activities that are about to start higher in the feed:

{"functions":{ "indicator_right":{"base":"decay_gauss","scale":"1s","direction":"left""},"score": "decay_gauss(time)*indicator_right(time)"}

Here we are using the auxiliary function indicator_right that gives a score equal to zero to all activities that happened in the past and a score of one to activities in the future. By multiplying it by decay_gauss we get a forward looking ranking function (see image below)

Promoted or Editorial activities

Sometimes you’ll want to boost promoted or editorial activities. Here are two different approaches:

Formula #1 :

{"score": "decay_gauss(time)^(1/promoted)", "defaults":{"promoted:1"}}

This will ensure that promoted activities will have a slower decay, where promoted is always a float larger than one for promoted activities. We recommend starting with promoted=2 and then tweaking it if that value doesn’t work. Remember: the bigger the promoted value, the slower the decay for boosted activities.

Formula #2 :

{"score": "decay_gauss(time)*promoted", "defaults":{"promoted":1}}

This is another alternative that is more aggressive but easier to interpret; for instance, setting promoted equal to 2 makes boosted activities stay at the top at least as long as scale+offset. In general, if promoted is larger than 2, the activity will stay on top of other non-boosted activities for at least scale+offset.

Analytics and ranked feeds

You can also use Stream’s analytics data as an input to your ranking functions. (Note that analytics features are only available on enterprise plans.)

The ranking method shown below uses the “click” and “like” events from analytics on a feed:

{"score": "decay_gauss(time)*log(analytics_clicks+0.5*analytics_likes)"}

Using analytics data makes it easy to rank activities based on engagement metrics such as clicks, hover events, video watches, and so on.

Personalized feeds vs Ranked feeds

One question we often get is about the difference between ranked and personalized feeds. There are 2 main differences:

  • For the personalized feeds we create a custom endpoint for your app. This gives us more flexibility in customizing the behavior and ranking logic.
  • The personalized feeds can utilize Stream’s machine learning capabilities.

Stream’s personalization can be used for:

  • Feed Ranking
  • A discovery-based feed (like Instagram’s Explore section)
  • Follow suggestions
  • Content suggestions
  • Email optimization

Personalized feeds are custom built per app and work well for a wide variety of use cases.


Ranking methods give you full control over sorting your activities. Our documentation clarifies the functions you can use, and hopefully this post has given you a few additional ideas to try. Feel free to reach out to us if you have any questions!