Feed features and parameters

There are four feed building steps:

  • Step 1: Candidate Generation
  • Step 2: Ranking
  • Step 3: Visibility filters
  • Step 4: Feed Mixing

All our feed builder features logically fall into one of these steps. Let's break them down!


Step 1. Candidate Generation

Define the pool of content your feed will draw from.
This step sets the foundation for your feed by selecting which content gets considered — from specific users, apps, labels, time windows, and more. Think of it as setting up the raw ingredients before cooking. Filters narrows down the entire universe of recommendable content to exclude content with certain attributes. Use filters to make content more relevant to your users and the nature of your APP.


Time Period

Time period allows you to specify to return only content created within the last ndays.

Since our system is trained to predict what a particular user is likely to interact with or what content in the system will receive a lot of interactions, the recommended content can be created longer in the past if the models think they are the best. Time period can be used if you would only want more recent content to be shown in your feed.

Source

Add an app or client's FID to filter for items coming from this app or client!

Geo location

Add a geolocation adding in latitude and longitude to filter from items coming from users located there.

Author IDS

Specify to return only content from a specific list of Author IDs.

Author IDs can be specified in 3 ways. (only one type at a time is supported at the moment)

  1. Specify a list of specific author IDs, so that only content from these channels will be returned
  2. Specify following, so only content created by users followed by the user_id is returned
  3. Specify the following list of a specific user, so content created by users followed by that specific user is returned

Channels

Specify a list of channels (channel urls), so that only content from these channels will be returned

AI labels

Specify a list of AI labels, so that only content tagged with these AI labels will be returned. When you select an AI label, there is an option to tweak the threshold score, such that only content with label score above the threshold will be returned. This can be used to fine tune the behaviour of the feed. 'mbd system default will be used if a threshold is not specified.

Embed Domains

Specify a list of domains, so that only content with embeded objects from the specific domains will be returned. For example, you can add mint.fun or zora.co to the domain list to make a feed of content with nft related objects embedded, or use drakula.app to make a video feed.

Publication Types

Specify to only return content of specific types. For example, you may want a feed with only images, videos, nfts or music, etc.

Languages

Simply choose the desired languages to filter for items posted in this language.

Engagement

Add certain minimum thresholds of likes, comments, shares in order to filter for items with specific levels of engagement.


Step 2. Ranking

Apply scoring logic to prioritize which candidates surface to the top.
Once you’ve gathered a pool of potential content, this step ranks it using scoring algorithms like balanced_feed_v0.0.1 or custom logic. The goal: highlight the most relevant and engaging content for the user.

Scoring functions

  • DEFAULT: balanced_feed_v0.0.1 – balanced mix of interest + affinity
  • balanced_feed_interest_bias_v0.0.1 – Lean toward user interests
  • balanced_feed_affinity_bias_v0.0.1 – Lean toward social graph affinity
  • user_affinity_all_following_v0.0.1 – Based on interactions from all followed users
  • user_affinity_closest_following_v0.0.1 – Focus on tightest connections
  • user_interest_all_v0.0.1 – Long-term interaction history
  • user_interest_recent_v0.0.1 – Recent behavior-driven interests

Time Decay

Add a time decay element to keep the items in the feed fresh.


Step 3. Visibility Filters

Control what the user actually sees.
Here, you can hide items a user has already interacted with, filter out their own posts, or require social proof (like likes or replies) before surfacing a post. This step shapes the final layer of polish and relevance.

Impression Count

Impression count allows you to specify the number of items returned by the API call to be considered "seen" by the current viewing user (specified by the user_id in API call). For example, if impression_count is set to 5 when calling the API, the first 5 items in the returned list is considered seen by the user, and the items will not be included in future API responses.

Show / Hide Interacted Items

If a user has already interacted with an item, this means the user has already seen the item. However, whether the item should be included in the feed is not clear cut.

We took the opinion that interacted items should not be shown to the same user, and so by default interacted items are not returned in the API response for the user.

However, there is also a case to be made that users might like seeing the same content again, both because the user likely is interested in the content in the first place and doesn't mind seeing it again, or any new conversations surrounding the content might be of interest to the user. Show interacted items can be used as an option to allow the content to still be included in the feeds.

Remove posts created by the current user?

Tick the box so that users don't see their own posts in their feed.

Return only posts with social proof

Tick the box to return only posts that have been interacted with by the people the user follows.


Step 4. Feed Construction / Feed Mixing

Add logic for fallback, cold starts, and promotion feeds (link).
Make sure every user always sees something — even if they’re new or inactive. You can configure fallback feeds, customize cold start behavior, or insert content from other feeds directly into the feed experience.

Fallback config

Set up a feed that the config will fall back to in case your primary feed runs out of content.

Cold Start Configurations

What's Considered Cold Start?

If a user is new to the system and has no interaction history, or if the user has not been actively interacting with content for a long period of time, there is not enough signals to recommend a "good" feed to the user.

Specifying a Cold Start Feed

In cases the user is considered under "cold start", it is recommended that you configure a "cold start feed" to be shown to the user in those cases. This basically means that our APIs uses the feed_id specified by the cold_start_feed when we detect that a user is under "cold start".

Cold start feed should be carefully crafted to make the feed interesting to "cold" users. This can be done by using a combination of the strategies below:

  • use ai_labels in filters to select content topics that represent the topics the users on your platform are more likely to be interested in
  • use author_ids in filters, and curate a "good" list of content creators. Good content creators should be those who are regular users and actively create content that are interesting to other users
  • use author_ids and specify following, to include content created by the users followed by the current user, if the user is a returning user
  • use channels in filters to select a list of quality channels that users on your platform are more likely to be interested in
  • depending on the nature of your platform, it might be beneficial to also use publication_type in filters to return only certain types of publications (only videos, for example)
  • depending on the nature of your platform, it might be beneficial to use exclude ai_labels to avoid content that might not be relevant to your users. You can, for example, choose to exclude web3-specific content by specifying web3 ai_labels in exclusion list

Finally, it is recommended to include a promotion filter in the cold start feed_id, to mix in different strategies mentioned above. For example, the feed can be configured to include ai_labels, author_ids, channels, to ensure the content is of specific types, and then use a promotion filter of following in author_ids, to achieve something like 70% of content from "interesting" labels and sources, and 30% of content from users followed by the viewing user_id.

Promotions

Promotions are power ways of adding variability in your feed. With promotion feeds, you can mix in a different feed (saved as a feed_id with different set of filters and parameters) at a specific percentage, or insert specific items at specific positions in the feed.

Currently, we only support 1 type of promotion (feed or item) in each API call.

Feed Promotion Guide

A concise reference for using feed promotions in the embed Feed API.


Contents

  1. What Are Feed Promotions?
  2. promotion_filters Object
  3. Promotion Types
  4. Example Request & Response
  5. Mixing Algorithm (Pseudo Code)
  6. Tips, Limits & Best Practices
  7. Frequently Asked Questions
  8. Changelog & References

1 What Are Feed Promotions?

A feed promotion is a controlled way to inject extra content into a user’s main feed. Each promotion can either:

  • Blend an entire feed (promotion_type = "feed") at a specified percentage, or
  • Insert specific items (promotion_type = "items") at fixed ranks.

Promoted content is mixed toward the top of each page, boosting visibility without completely overriding the user’s core experience.


2 promotion_filters Object

promotion_filters is an array—one element per promotion (only one is supported today).

FieldTypeRequiredDescription
promotion_typestring"feed" or "items"
promotion_namestringLabel surfaces in source_feed of response items
percentintegerfeed‑typeTarget percentage of the final result that should be promotional
feed_idstringfeed‑typeID of an existing feed whose items will be promoted
filtersobjectfeed‑typeOptional extra filters to refine the promotion feed
promoted_itemsarray<object>items‑typeHand‑picked items with optional 1‑based rank

UI note: The form shown in the product mirrors this schema, revealing required and conditional fields.


3 Promotion Types

3.1 feed (most common)

  • Pulls items from another feed (feed_id).
  • Uses percent to determine the target blend.
  • Items appear at random, skew‑to‑top positions.

3.2 items

  • Promotes an explicit list of items.
  • Provide a rank to pin an item to an exact slot; otherwise the system distributes items evenly.

4 Example Request & Response

curl --request POST \
     --url https://api.mbd.xyz/v2/farcaster/casts/feed/for-you \
     --header 'HTTP-Referer: https://docs.mbd.xyz/' \
     --header 'X-Title: mbd_docs' \
     --header 'accept: application/json' \
     --header 'authorization: Bearer <YOUR TOKEN>' \
     --header 'content-type: application/json' \
     --data '{
  "promotion_filters": [
    {
      "promotion_type": "feed",
      "promotion_name": "video_content",
      "percent": 35,
      "feed_id": "feed_180"
    }
  ],
  "user_id": "3",
  "feed_id": "feed_214"
}'

 

Highlights

  • The main feed is feed_214 (for user 3).
  • feed_180 (curated videos) is promoted at ~35 %.

Partial response:

{
  "item_id": "0x757a…9048",
  "source_feed": "promotion:feed_180"   // promoted
},
{
  "item_id": "0xfd6c…6832",
  "source_feed": "main:feed_214"        // main

 

source_feed prefixes clearly distinguish promoted versus main items.

5 Mixing Algorithm (Pseudo Code)

5.1 Flow Diagram

Main Feed ─────────┐
                  │ (deduplicate)
Promotion Feed ───┘
       │
       ▼
[Generate skew‑biased positions] ←─────────┐
       │                                    │
       └───► [Interleave lists] ────────────┘

Goal: roughly promoPercent % of the first top‑k items come from the promotion feed and are biased toward early ranks.

5.2 Core Pseudo Code

CONST OVERFETCH = 2.0

function mix(main, promo, percent, topK):  
# 1 — Deduplicate  
    main, promo ← removeOverlap(main, promo)

# 2 — Over-fetch so ratios survive later trimming
desired ← topK × OVERFETCH
promoN  ← ceil(desired × percent / 100)
mainN   ← desired − promoN
promo ← first(promo, promoN)
main  ← first(main,  mainN)

# 3 — Choose insertion slots (skewed toward lower numbers)
slots ← skewedPositions(count = promoN, max = promoN + mainN)

# 4 — Interleave
out ← []
for i in 1…(promoN + mainN):
    if i in slots:   out.append(pop(promo))
    else:            out.append(pop(main))

# 5 — Return final page
return first(out, topK)

5.3 Skewed Position Helper

function skewedPositions(count, max):
    assert count ≤ max
    universe ← [1 … max]
    weight(n) = 1 / n^0.35        # lower n ⇒ higher weight
    slots ← weightedUniqueSample(universe, weight, count)
    return sort(slots)

Intuition: Think of drawing numbered tickets—tickets 1–10 are heavier than 90–100. Selected slots therefore cluster near the top without always landing at position 1.

6 Tips, Limits & Best Practices

  • Single promotion per request — chain multiple calls client‑side if you need more.
  • Set reasonable percent values (10–30 % is typical). Values over 50 % may feel spammy.
  • Track source_feed in analytics to verify the real-world blend meets expectations.
  • Quality matters. The algorithm does not re-rank promotion items, so start with a well-ranked feed.
  • Tweak OVERFETCH (default 2.0) if heavy deduplication causes percentage drift.

7 Frequently Asked Questions

Q — Can I promote using filters only (no saved feed)?
A — Yes. Omit feed_id, supply filters, and set promotion_type = "feed". The system treats it as an ad-hoc feed.

Q — Is insertion deterministic?
A — Slots are freshly generated per request, but once chosen, the order remains stable throughout the page.

Q — What if the promotion feed is exhausted?
A — The engine silently back-fills with main-feed items, so the actual percentage may be lower than requested.