# Ranking expressions

A ranking expression computes a score for each activity, and the feed is ordered by that score, highest first. This page is the reference for what an `expression` or `interest` ranking can use: activity fields, data types, functions, operators, constants and decay functions. For how to configure ranking on a feed group or feed view, see [Ranking](https://getstream.io/activity-feeds/docs/php/custom-ranking/).

## Activity data

It's not possible to access all fields of an `ActivityResponse` inside the ranking context. Below you'll find the list of supported fields:

| name               | description                                                                                                                                                                                                                                                                                                                                                          |
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `type`             | The type of the activity (e.g. the content type string set when creating the activity)                                                                                                                                                                                                                                                                               |
| `time`             | UNIX timestamp of when the activity was created                                                                                                                                                                                                                                                                                                                      |
| `popularity`       | The popularity score of an activity (formula: `activity.popularity = reactions + comments * 2 + bookmarks * 3 + shares * 3`)                                                                                                                                                                                                                                         |
| `reaction_count`   | The sum of all reactions                                                                                                                                                                                                                                                                                                                                             |
| `reaction_counts`  | Reaction counts by type, you can access specific types with dot notation (for example, `reaction_counts.like`)                                                                                                                                                                                                                                                       |
| `comment_count`    | How many comments the activity has                                                                                                                                                                                                                                                                                                                                   |
| `bookmark_count`   | How many bookmarks the activity has                                                                                                                                                                                                                                                                                                                                  |
| `share_count`      | How many shares the activity has (Increased when an activity is set as the `parent_id` of another activity)                                                                                                                                                                                                                                                          |
| `custom`           | The `custom` field of the `activity`, nested fields can be accessed with `.` notation, for example: `custom.topic`                                                                                                                                                                                                                                                   |
| `selector_source`  | Which activity selector provided this activity (e.g., `"following"`, `"popular"`, `"interest"`). See [Ranking by Selector Source](#ranking-by-selector-source) for usage examples.                                                                                                                                                                                   |
| `interest_score`   | Only available when using `interest` type ranking. A number between -1 and 1 reflecting how much a given activity matches the user's interests. See [Interest weights](https://getstream.io/activity-feeds/docs/php/interest-ranking/) to see how a user's interests are computed/configured.                                                                                     |
| `preference_score` | Available when using `expression` or `interest` type ranking. A number reflecting how much a given activity matches the user's preferences based on activity feedback (show more/less). Activities with `interest_tags` that have strong dislike are filtered out. See [Activity feedback](https://getstream.io/activity-feeds/docs/php/activity-feedback/) for more information. |
| `is_read`          | Boolean. Available when `track_read` is enabled on a custom feed group or the built-in `notification` group (including flat). `true` if the activity (or its aggregated group) has been marked as read. Uses time-based invalidation. **Enterprise plan only.** See [Ranking by Read/Seen Status](https://getstream.io/activity-feeds/docs/php/read-seen-ranking/).               |
| `is_seen`          | Boolean. Available when `track_seen` is enabled on a custom feed group or the built-in `notification` group (including flat). Same time-based invalidation as `is_read`. **Enterprise plan only.** See [Ranking by Read/Seen Status](https://getstream.io/activity-feeds/docs/php/read-seen-ranking/).                                                                            |

Every field the expression references that isn't a built-in field, such as `custom.*`, `external.*`, `metrics.*` and `selector_source`, needs a default value in `defaults`. The default is used for activities that don't have the field, and creating or updating a feed group or feed view without it fails with `expression references fields without defaults: <field>`. Write defaults as nested objects (`{ "custom": { "foo": 0 } }`), not dotted keys (`"custom.foo"`). Built-in fields such as `popularity` or `share_count` can't have defaults.

```php label="PHP"
$createResponse = $feedsClient->createFeedGroup(
    new GeneratedModels\CreateFeedGroupRequest(
        id: "myid",
        defaultVisibility: 'public',
        activitySelectors: [
            new GeneratedModels\ActivitySelectorConfig(
                type: 'following'
            )
        ],
        ranking: new GeneratedModels\RankingConfig(
            type: 'expression',
            score: 'popularity * (custom.isBoosted ? 1.5 : 1)',
            defaults: (object) [
                'custom' => (object) [
                    'isBoosted' => false
                ]
            ]
        )
    )
);
```

## Data types

The following data types are supported in the ranking expression context:

| name    | example           |
| ------- | ----------------- |
| Boolean | `true`, `false`   |
| Integer | `36`, `0b101010`  |
| Float   | `0.2`             |
| String  | `"foo"`           |
| Array   | `["a", "b", "c"]` |
| Map     | `{foo: "bar"}`    |
| Nil     | `nil`             |

## Functions

The following functions can be used in ranking expressions:

| name                           | description                                                                                                                                                                                                                                                                                                                                                                                        |
| ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ln(x)                          | Natural logarithm function                                                                                                                                                                                                                                                                                                                                                                         |
| log10(x)                       | Logarithm function base 10                                                                                                                                                                                                                                                                                                                                                                         |
| sin(x)                         | Trigonometric sine function                                                                                                                                                                                                                                                                                                                                                                        |
| cos(x)                         | Trigonometric cosine function                                                                                                                                                                                                                                                                                                                                                                      |
| tan(x)                         | Trigonometric tangent function                                                                                                                                                                                                                                                                                                                                                                     |
| asin(x)                        | Arcsine function                                                                                                                                                                                                                                                                                                                                                                                   |
| acos(x)                        | Arccosine function                                                                                                                                                                                                                                                                                                                                                                                 |
| atan(x)                        | Arctangent function                                                                                                                                                                                                                                                                                                                                                                                |
| abs(x)                         | Absolute value                                                                                                                                                                                                                                                                                                                                                                                     |
| min(a,b)                       | Minimum value                                                                                                                                                                                                                                                                                                                                                                                      |
| max(a,b)                       | Maximum value                                                                                                                                                                                                                                                                                                                                                                                      |
| trunc(x)                       | Truncates to the nearest integer value                                                                                                                                                                                                                                                                                                                                                             |
| round(x)                       | Rounds to the nearest integer value                                                                                                                                                                                                                                                                                                                                                                |
| decay_linear(t)                | Linear decay, see [Decay & Ranking](#decay--ranking) for more information                                                                                                                                                                                                                                                                                                                          |
| decay_exp(t)                   | Exponential decay, see [Decay & Ranking](#decay--ranking) for more information                                                                                                                                                                                                                                                                                                                     |
| decay_gauss(t)                 | Gaussian decay, see [Decay & Ranking](#decay--ranking) for more information                                                                                                                                                                                                                                                                                                                        |
| rand_normal()                  | Returns a normally distributed number in the range [-inf, +inf] with standard normal distribution (stddev = 1, mean = 0)                                                                                                                                                                                                                                                                           |
| rand_normal(a,b,σ,µ)           | Returns a normally distributed number in the range [a, b] with specific normal distribution (stddev = σ, mean = µ)                                                                                                                                                                                                                                                                                 |
| rand()                         | Returns a random number in the range [0, 1.0)                                                                                                                                                                                                                                                                                                                                                      |
| to_unix_timestamp(t)           | Converts a time value to a UNIX timestamp                                                                                                                                                                                                                                                                                                                                                          |
| dist(lat1,lng1,lat2,lng2,unit) | Returns the distance between the two points given by (lat1,lng1) and (lat2,lng2). By default the unit is in kilometers, but the unit can also be `"M"` for miles or `"N"` for nautical miles. Coordinates written in the expression must be decimals (`51.0`, not `51`). This function can be combined with the external ranking parameters to rank activities based on a user's distance to them. |
| map_lookup(key, map)           | Look up value from a map by key (`0.0` if the key is missing), see [Arrays and Maps](https://getstream.io/activity-feeds/docs/php/external-ranking-data/#arrays-and-maps) for more information                                                                                                                                                                                                                  |
| sum_map_lookup(keys, map)      | Sum values from a map for multiple keys, see [Arrays and Maps](https://getstream.io/activity-feeds/docs/php/external-ranking-data/#arrays-and-maps) for more information                                                                                                                                                                                                                                        |
| in_array(needle, haystack)     | Returns `1.0` if a value exists in an array and `0.0` otherwise, see [Arrays and Maps](https://getstream.io/activity-feeds/docs/php/external-ranking-data/#arrays-and-maps) for more information                                                                                                                                                                                                                |

## Operators

The following operators can be used in ranking expressions:

- Arithmetic operators: `+`, `-`, `*`, `/`, `%` (modulus), `^`, `**` (exponent)

- Logical operators: `not`/`!`, `&&`/ `and`, `||`/`or`

- Conditional: `x ? y : z`, `??`, `if`/`else`

- Comparison: `==`, `!=`, `<`, `>`, `<=`, `>=`

- Control order of evaluation with parentheses `()`

- Array/map operators: `[]` (index), `.`, `?.`, `in` (checks if an array/map has an item/key)

- String operators: `+` (concatenation), `contains`, `startsWith`, `endsWith`

This lets you construct a scoring algorithm like this:

```text
"score":"(a > 2 || (b > 4 && c > 3)) ? 1 : -1"
```

## Constants

The following constants and helpers are also available to use in ranking expressions:

| name           | description                        |
| -------------- | ---------------------------------- |
| `e` / `E`      | Euler's number                     |
| `pi` / `PI`    | π                                  |
| `current_time` | UNIX timestamp of the current time |

## Decay & Ranking

Stream supports linear, exponential, and Gaussian decay. The built-in `decay_linear(t)`, `decay_exp(t)` and `decay_gauss(t)` take one argument and always use the default parameters below (origin now, scale 5 days, no offset, decay 0.5); extra arguments are ignored. To change the parameters, define your own function under `functions` with a `base` of `decay_linear`, `decay_exp` or `decay_gauss`, and call it by name in `score`. All parameter values are strings.

![](https://getstream.imgix.net/images/docs/decay_explainer.png?auto=compress&fit=clip&w=800&h=600)

### Parameters

| name      | description                                                                                                                                                                                  | default |
| --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
| base      | Required. The decay function to use: `decay_linear`, `decay_exp` or `decay_gauss`.                                                                                                           |         |
| origin    | The best possible value, as a number (for example a UNIX timestamp, or a popularity). If the value is equal to the origin, the decay function will return 1.                                 | now     |
| scale     | Determines how quickly the score drops from 1.0 to the decay value. If the scale is set to "3d", the score is equal to the decay value 3 days beyond the offset.                             | 5d      |
| offset    | Values within the offset of the origin score 1. The decay starts beyond the offset.                                                                                                          | 0       |
| decay     | The score that a value at scale distance from the origin should receive.                                                                                                                     | 0.5     |
| direction | `both`, `right` or `left`. With `right`, only values below the origin decay (for timestamps, older activities) and values above it score 1. With `left`, only values above the origin decay. | both    |

>
> **Info:** For `scale` and `offset` you can use s, m, h, d, w and y to specify seconds, minutes, hours, days, weeks and years, with a whole number (for example `36h`, not `1.5d`). A plain number is used as is.
>

The example below defines a simple_gauss with the following parameters:

- **scale**: 5 days

- **offset**: 1 day

- **decay**: 0.3

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 example also defines a `popularity_gauss` that scores activities with a popularity of 100 or more as 1 (`origin: "100"` with `direction: "right"`), and lowers the score of less popular activities. A function applied to something other than time needs an `origin`, because the default origin is the current time. The full example:

```php label="PHP"
$createResponse = $feedsClient->createFeedGroup(
    new GeneratedModels\CreateFeedGroupRequest(
        id: "myid",
        defaultVisibility: 'public',
        activitySelectors: [
            new GeneratedModels\ActivitySelectorConfig(
                type: 'following'
            )
        ],
        ranking: new GeneratedModels\RankingConfig(
            type: 'expression',
            score: 'simple_gauss(time)*popularity_gauss(popularity)',
            functions: [
                'simple_gauss' => [
                    'base' => 'decay_gauss',
                    'scale' => '5d',
                    'offset' => '1d',
                    'decay' => '0.3'
                ],
                'popularity_gauss' => [
                    'base' => 'decay_gauss',
                    'origin' => '100',
                    'direction' => 'right',
                    'scale' => '100',
                    'offset' => '5',
                    'decay' => '0.5'
                ]
            ]
        )
    )
);
```

## Ranking by Selector Source

When using multiple [activity selectors](https://getstream.io/activity-feeds/docs/php/activity-selectors/), each activity is tagged with a `selector_source` field indicating which selector provided it. This enables you to prioritize activities from specific sources in your ranking expressions.

```php label="PHP"
// Example 1: Simple boost - following activities get 2x multiplier
$createResponse = $feedsClient->createFeedGroup(
  new GeneratedModels\CreateFeedGroupRequest(
    id: 'selector_timeline',
    activitySelectors: [
      new GeneratedModels\ActivitySelectorConfig(type: 'following'),
      new GeneratedModels\ActivitySelectorConfig(
        type: 'popular',
        minPopularity: 1
      )
    ],
    ranking: new GeneratedModels\RankingConfig(
      type: 'expression',
      score: 'selector_source == "following" ? popularity * 2 : popularity',
      defaults: (object) [
        'selector_source' => ''
      ]
    )
  )
);

// Example 2: Multiple selectors with different bonuses
$createResponse = $feedsClient->createFeedGroup(
  new GeneratedModels\CreateFeedGroupRequest(
    id: 'multi_selector_timeline',
    activitySelectors: [
      new GeneratedModels\ActivitySelectorConfig(type: 'following'),
      new GeneratedModels\ActivitySelectorConfig(type: 'interest'),
      new GeneratedModels\ActivitySelectorConfig(
        type: 'popular',
        minPopularity: 1
      )
    ],
    ranking: new GeneratedModels\RankingConfig(
      type: 'expression',
      score: '
        (selector_source == "following" ? 10 : 0) +
        (selector_source == "interest" ? 5 : 0) +
        popularity
      ',
      defaults: (object) [
        'selector_source' => ''
      ]
    )
  )
);
```

**Important notes:**

- **Defaults required:** You must provide `selector_source` in the `defaults` map (typically as an empty string `""`)
- **Duplicate activities:** If an activity matches multiple selectors, it keeps a single `selector_source`. `following` takes precedence over the other selectors
- **Valid sources:** `following`, `popular`, `interest`, `query`, `proximity`, `current_feed`, `follow_suggestion`

---

For the most recent version of this documentation, visit [https://getstream.io/activity-feeds/docs/php/ranking-expressions/](https://getstream.io/activity-feeds/docs/php/ranking-expressions/).