.Net / C#

Custom Ranking

LAST EDIT Nov 30 2023

Stream allows you to configure your own ranking method. You can add multiple ranking methods to a given Flat feed group.

Ranked feeds are only available on Standard plans and higher. Contact support after upgrading your account to enable ranked feeds for your organization.

An example ranking config is shown below:

Available Functions

obs: functions are parsed in lowercase



Basic Arithmetic

The following are supported: + - * / ( ) ^


Log Function natural base


Log Function base 10


Trigonometric sine function


Trigonometric cosine function


Trigonometric tangent function


Absolute value


Minimum value


Maximum value


Truncates to the nearest integer value


Rounds to the nearest integer value


Linear Decay


Exponential Decay


Gauss Decay


Returns a normally distributed number in the range [-inf, +inf] with standard normal distribution (stddev = 1, mean = 0)


Returns a normally distributed number in the range [a, b] with specific normal distribution (stddev = σ, mean = µ)


Returns a random number in the range [0, 1.0)


Returns a random number in the range [a, b)


Converts a time value to a unix timestamp

Adding Activities


Below is an example of how to add activities with custom ranking:

Retrieving Activities


Below is an example of how to retrieve activities sorted by custom ranking:

You can only use limit and offset for pagination with custom ranking.

Configuring ranking can be complex. Feel free to reach out to support if you have questions.

More visibility into ranking variables


If you need to inspect your ranking variables at runtime this can be achieved like so

Decay & Ranking


Stream supports a Linear, Exponential, and Gauss decay. For each decay function, we support 4 arguments: Origin, Scale, Offset, and Decay. You can pass either a timedelta string (such as 3d, 4w), or a numeric value.







The best possible value. If the value is equal to the origin the decay function will return 1.



Determines how quickly the score drops from 1.0 to the decay value. If the scale is set to "3d" the score will be equal to the decay value after 3 days.



Values below the offset will start to receive a lower score.



The score that a value at scale distance from the origin should receive.



left, right or both. If right is specified only apply the decay for the right part of the graph.


You can use s, m, h, d and w to specify seconds, minutes, hours, days and weeks respectively.

The example below defines a simple_gauss with the following params:

  • scale: 5 days

  • offset: 1 day

  • decay: 0.3 day

This means that an activity younger than 1 day (the offset) will return a score of 1. An activity that is exactly 6 days old (offset + scale) will get a score of 0.3 (the decay factor). The full JSON config is shown below:

You can specify defaults for the variables you use. The example above sets popularity to 1 if it's missing from the activity. We highly recommend setting up defaults to prevent errors when retrieving activities without these variables.

Custom ranking is only working on the last 1000 activities of the feed.

Configuring ranking can be complex. Feel free to reach out to support if you have questions!

Analytics & Reaction Counts

Analytics and Reaction Counts can be used in ranking easily, contact support to get them enabled.

In this example, we define defaults for activities that might be missing any analytics or reactions on it. Then, a linear combination of these numbers is adjusted according to passed time.

Reaction counts are cached for 30 minutes. Therefore, when using this as a ranking criteria, you can anticipate a small delay between when a new reaction is added / removed and the recalculation of the score of the activity.

Call time custom parameters


The scoring algorithm is working off of data such as parameters on the activity itself, analytics counters or reaction counters. For most use cases this is enough to present a relevant ranked feed based on those (semi-static) parameters, but it's lacking the capabilities to rank a feed based on a users own preferences.

In order to rank a feed based on a users preferences (i.e a personalized feed) Stream now accepts custom parameters that can be used at call time in the scoring algorithm.

Example: Music service

Consider the example of a music service that lets users upload songs and that they have a "global" front page feed that highlights the latest uploaded songs (activities). A naive approach might be to leave it unranked (i.e ranked by time) but this might not be front page worthy content. A better approach could be to rank the activities in this feed by the number of views or reactions on the activity, like a "new and hot" feed. The best approach is potentially to have a "new and hot" feed that also takes into account the type of activities (i.e type of music) that the user likes.

Consider two different users "the metalhead", which only listens to metal and "the classicist", which only listens classical music. Lets say we have this list of recent activities posted to the "global" feed.

We can then score these activities with the following scoring algorithm:

score = w_rock*classes.rock + w_pop*classes.pop + w_metal*classes.metal + w_classical*classes.classical + w_rap*classes.rap

and at call time we can supply the weights for a specific user, i.e for "the metalhead" we can specify the weights as

{"w_rock": 5, "w_pop": 1, "w_metal": 20, "w_classical": 4, "w_rap": 0}

which will put song4 and song1 at the top of the feed for that user. "The classicist" only cares about classical music with these weights

{"w_rock": 0, "w_pop": 0, "w_metal": 0, "w_classical": 1, "w_rap": 0}

which will order the feed based on the classical score only so song6 and song5 will be at the top of the feed for that user.