# How the Blending Pipeline Merges Ranked Posts with Ads, Who to Follow, and Prompts in X Algorithm

> Discover how the X algorithm's Blending Pipeline merges ranked posts with ads, 'Who to Follow,' and prompts. Understand the detailed process for a richer, personalized feed.

- Repository: [SpaceXAI Org/x-algorithm](https://github.com/xai-org/x-algorithm)
- Tags: architecture
- Published: 2026-09-10

---

**The Blending Pipeline in [`home-mixer/selectors/blender_selector.rs`](https://github.com/xai-org/x-algorithm/blob/main/home-mixer/selectors/blender_selector.rs) partitions heterogeneous feed items by type, applies configurable ad-spacing strategies to blend posts with advertisements, then layers prompts, Who to Follow modules, and rich UI components at predetermined positions to produce the final ordered timeline.**

The X Algorithm repository (`xai-org/x-algorithm`) powers the ranking and serving infrastructure for the platform's main feed. After the Post Pipeline generates ranked content, the Blending Pipeline performs the final assembly step, ensuring that organic posts, sponsored content, and engagement modules appear in the correct sequence with appropriate spacing constraints.

## Overview of the Blending Architecture

The Blending Pipeline serves as the terminal orchestration layer within the For You candidate pipeline. Implemented in [`home-mixer/selectors/blender_selector.rs`](https://github.com/xai-org/x-algorithm/blob/main/home-mixer/selectors/blender_selector.rs), it consumes a raw `candidates` vector containing mixed `FeedItem` types—including `ScoredPost`, `AdIndexInfo`, `WhoToFollowModule`, and `Prompt`—and produces a unified `SelectResult` ready for client consumption.

The pipeline guarantees that:
- **Ad spacing rules** are enforced through pluggable blender strategies
- **High-priority content** (prompts, push-to-home posts) receives fixed positional placement
- **Tracking metadata** captures dropped items for analytics and debugging

## Step-by-Step Feed Construction Process

The `BlenderSelector` executes a deterministic sequence of operations to transform partitioned inputs into the final feed.

### Partitioning Incoming Feed Items

The process begins with `partition_feed_items` (lines 5-13), which iterates through the raw candidate vector and separates items into typed collections:

- `posts`: `Vec<ScoredPost>` — The organic ranked content
- `ads`: `Vec<AdIndexInfo>` — Sponsored content candidates
- `wtf_modules`: `Vec<WhoToFollowModule>` — Account recommendation modules
- `prompts`: `Vec<Prompt>` — Interactive engagement prompts
- `push_to_home`: `Option<PushToHomePost>` — Prioritized content requiring top placement
- `frames`: `Vec<Frame>` — Rich UI cards requiring spacing logic
- `feed_survey`: `Option<FeedSurvey>` — Optional feedback collection module

This type-safe partitioning enables subsequent steps to apply specialized logic to each content category.

### Blending Posts with Advertisements

Once partitioned, posts and ads merge through a selected **AdsBlender** implementation. The blending occurs at line 70:

```rust
let mut blended = blender.blend(posts, ads);

```

The system instantiates the blender based on the request parameter `AdsBlenderType` (lines 53-68). Available strategies include:

- **PartitionOrganicAdsBlender**: The default implementation defined in [`home-mixer/ads/partition_organic_blender.rs`](https://github.com/xai-org/x-algorithm/blob/main/home-mixer/ads/partition_organic_blender.rs), which partitions organic content around ad slots
- **SafeGapAdsBlender**: Enforces conservative minimum spacing between advertisements
- **MultiRiskAdsBlender**: Handles tiered risk categories for sensitive content adjacency
- **TimeGapAdsBlender**: Configurable temporal spacing between sponsored insertions

Each strategy ensures that ads appear at valid intervals without compromising the perceived quality of the organic feed.

### Inserting Prompts and Engagement Modules

After the post-ad blend completes, the pipeline layers non-content items at fixed positions:

**Prompts** receive front-of-feed priority. The `insert_prompts` function (lines 72-11) places all prompt items at the constant `PROMPTS_POSITION` defined in [`home-mixer/params/param.rs`](https://github.com/xai-org/x-algorithm/blob/main/home-mixer/params/param.rs), ensuring users see interactive elements before scrolling.

**Who to Follow** recommendations insert via `insert_who_to_follow` (lines 73-25). The system places only the first module at the stable `WHO_TO_FOLLOW_POSITION`. If the target index exceeds the current vector length, the insertion point clamps to the end of the feed to avoid out-of-bounds placement.

### Pinning Priority Content and Rich Media

Additional UI components merge in strict sequence:

- **Push-to-Home**: When a `PushToHomePost` exists, `pin_push_to_home` (lines 74-38) forces it to index 0, overriding standard ordering
- **Frames**: Rich media cards are scheduled using `frames::plan` to respect mutual spacing rules, then merged via `insert_planned_frames` (lines 75-62)
- **Feed Surveys**: Optional surveys attach at the fixed `FEED_SURVEY_POSITION` (lines 76-75)

### Tracking and Finalization

The selector maintains accountability for content removal. It counts dropped posts and ads during the blending phase (lines 78-85) and constructs placeholder entries for the `non_selected` response field (lines 88-94). The final `SelectResult` returned at lines 91-94 contains both the merged `selected` vector and these tracking placeholders, enabling downstream analytics to reconcile input candidates with served content.

## Configuring the Blending Behavior

To utilize the Blending Pipeline in a Rust service:

```rust
use xai_home_mixer::selectors::BlenderSelector;
use xai_home_mixer::candidate_pipeline::for_you_candidate_pipeline::ForYouCandidatePipeline;
use xai_home_mixer::models::query::ScoredPostsQuery;

// 1. Configure query parameters
let mut query = ScoredPostsQuery::default();
query.params.set(AdsBlenderType, "partition_organic_low_risk");

// 2. Obtain candidates from upstream ranking (simplified)
// let candidates: Vec<FeedItem> = post_pipeline_result;

// 3. Execute blending
let blender = BlenderSelector::new();
let result = blender.select(&query, candidates);

// 4. Consume the ordered feed
for item in result.selected {
    match item {
        FeedItem::Post(post) => println!("Post: {}", post.id),
        FeedItem::Ad(ad) => println!("Ad: {}", ad.advertiser_id),
        FeedItem::Prompt(prompt) => println!("Prompt: {}", prompt.text),
        _ => {}
    }
}

```

This implementation demonstrates configuring the `AdsBlenderType` parameter to select the low-risk organic partitioning strategy, then invoking `select` to produce the final blended sequence containing posts, ads, and UI modules in their designated order.

## Summary

- The **Blending Pipeline** resides in [`home-mixer/selectors/blender_selector.rs`](https://github.com/xai-org/x-algorithm/blob/main/home-mixer/selectors/blender_selector.rs) and serves as the final feed assembly stage for the X Algorithm
- **Partitioning logic** (`partition_feed_items`) separates mixed candidates into typed vectors (posts, ads, prompts, frames) before merging
- **AdsBlender implementations** (selected via `AdsBlenderType`) enforce spacing rules, with `PartitionOrganicAdsBlender` as the default strategy
- **Fixed position constants** (`PROMPTS_POSITION`, `WHO_TO_FOLLOW_POSITION`, `FEED_SURVEY_POSITION`) determine placement for non-post content
- **Push-to-Home** content always pins to index 0 when present, processed by `pin_push_to_home`
- The pipeline tracks removed items and returns both `selected` and `non_selected` entries in the `SelectResult` for observability

## Frequently Asked Questions

### What file contains the core Blending Pipeline implementation?

The primary logic lives in [`home-mixer/selectors/blender_selector.rs`](https://github.com/xai-org/x-algorithm/blob/main/home-mixer/selectors/blender_selector.rs) within the `xai-org/x-algorithm` repository. This file defines the `BlenderSelector` struct and its `select` method, which orchestrates the partitioning, blending, and insertion operations that produce the final feed.

### How does the system choose which ad spacing strategy to apply?

The strategy is determined by the `AdsBlenderType` parameter in the request query. The pipeline selects the corresponding implementation—such as `PartitionOrganicAdsBlender`, `SafeGapAdsBlender`, or `TimeGapAdsBlender`—to handle the merge between posts and ads according to specific spacing constraints and risk tolerances.

### Where are the insertion positions for prompts and Who to Follow defined?

Constants including `PROMPTS_POSITION` and `WHO_TO_FOLLOW_POSITION` are defined in [`home-mixer/params/param.rs`](https://github.com/xai-org/x-algorithm/blob/main/home-mixer/params/param.rs). These values specify the exact indices where prompts (front of feed) and Who to Follow modules appear in the final output sequence.

### Can multiple Who to Follow modules appear in a single blended feed?

No. The current implementation in `insert_who_to_follow` (lines 73-25) processes only the first element of the `wtf_modules` vector. Additional recommendation modules beyond the first are discarded during the blending process, ensuring at most one Who to Follow insertion per feed request.