Skip to main content

Popular, Trending, Chronological

In the quest for hyper-personalization, it's easy to overlook the fundamental importance of baseline recommendation strategies. While sophisticated AI models deliver tailored experiences for known users, what do you show when personalization isn't possible (new visitors) or when you need a simple, globally relevant list (like "Top Sellers" or "What's New")? Furthermore, how do you benchmark the performance of your complex AI models? This is where rule-based baselines – like Popular, Trending, and Chronological rankings – become essential.

These seemingly simple strategies provide crucial fallbacks, power specific UI components, handle cold-start scenarios effectively, and serve as vital benchmarks for measuring the uplift of personalization. However, building, maintaining, and calculating even these "simple" baselines often involves surprising complexity, requiring data pipelines, aggregation logic, scheduled jobs, and dedicated serving infrastructure.

Implementing Baselines with Shaped

Let's illustrate how to set up separate Shaped models to serve different baseline carousels: "Most Popular This Month," "Trending Now (Rising Popularity)," and "Newly Added."

Goal: Create API endpoints for different non-personalized recommendation lists.

1. Ensure Data is Connected: Assume item_metadata (with relevant timestamps like publish_date) and user_interactions (with label for popularity and created_at timestamp) datasets are connected.

2. Define Baseline Models (Separate YAML files or definitions):

  • Model 1: Popular Last 30 Days
popular_model.yaml
model:  
name: popular_last_30_days
policy_configs:
scoring_policy: # Define the baseline logic here
policy_type: popular
mode: sum # Sum the 'label' column for popularity
time_window_in_days: 30 # Consider only the last 30 days
connectors:
- type: Dataset
name: user_events # Needs interaction data with labels and created_at timestamp
id: interactions
- type: Dataset
name: item_catalog
id: items
fetch:
events: |
SELECT user_id, item_id, label, created_at FROM interactions
items: |
SELECT item_id, title, image_url FROM items # Only need item PK
  • Model 2: Trending (Rising Popularity - Last 7 Days)
trending_rising_model.yaml
model:  
name: trending_rising_7d
policy_configs:
scoring_policy:
policy_type: rising-popularity
time_window: 7 # Calculate trend over the last 7 days
connectors:
- type: Dataset
name: user_events
id: interactions
- type: Dataset
name: item_catalog
id: items
fetch:
events: |
SELECT user_id, item_id, 1 AS label, created_at FROM interactions # Use 1 if no specific label
items: |
SELECT item_id, title, image_url FROM items
  • Model 3: Newly Added (Chronological)
chronological_model.yaml
model:  
name: newly_added_items
policy_configs:
scoring_policy:
policy_type: chronological
time_col: "publish_date" # Specify the column to sort by
ascending: false # False means newest first (descending)
connectors:
- type: Dataset
name: item_catalog # Only needs item data with timestamp
id: items
fetch:
items: |
SELECT item_id, title, image_url, publish_date FROM items # Need publish_date

3. Create the Models:

shaped create-model --file popular_model.yaml

shaped create-model --file trending_rising_model.yaml

shaped create-model --file chronological_model.yaml

4. Monitor Creation: Wait for all models (popular_last_30_days, trending_rising_7d, newly_added_items) to become ACTIVE.

5. Fetch Baseline Rankings (Application Logic): Call the rank API for the specific model you need, without providing a user_id.

const { ShapedClient } = require('@shapedai/shaped');

const apiKey = process.env.SHAPED_API_KEY; // Assumes this is set
const itemsLimit = 10;
const shapedClient = new ShapedClient({ apiKey: apiKey });

// --- Get Most Popular (Last 30 Days) ---
const popularResponse = await shapedClient.rank({
modelName: 'popular_last_30_days',
limit: itemsLimit,
returnMetadata: true
});
console.log(`Successfully retrieved ${popularResponse.ids.length} Popular items.`);

// --- Get Trending (Rising Popularity) ---
const trendingResponse = await shapedClient.rank({
modelName: 'trending_rising_7d',
limit: itemsLimit,
returnMetadata: true
});
console.log(`Successfully retrieved ${trendingResponse.ids.length} Trending items.`);

// --- Get Newly Added ---
const newestResponse = await shapedClient.rank({
modelName: 'newly_added_items',
limit: itemsLimit,
returnMetadata: true
});
console.log(`Successfully retrieved ${newestResponse.ids.length} Newest items.`);

6 Use Cases:

  • Use popular_last_30_days for a "Best Sellers" section.
  • Use trending_rising_7d for a dynamic "Trending Now" carousel.
  • Use newly_added_items for a "What's New" feed.
  • Use any of these as fallbacks when personalized ranking for a user fails or isn't possible.

Conclusion: Robust Baselines, Radically Simplified

Effective baseline recommendations are non-negotiable for handling cold starts, providing global discovery points, and benchmarking personalization efforts. Yet, building and maintaining the infrastructure to calculate Popular, Trending (in its various forms), and Chronological rankings manually is a significant engineering task.

Shaped integrates these essential baseline strategies directly into its platform, allowing you to configure and deploy them through simple YAML definitions. Offload the complexity of data pipelines, aggregation logic, scheduling, and serving to Shaped's managed infrastructure. Focus on defining the right baseline logic for your needs, and let Shaped handle the rest, ensuring you have robust, reliable, and easy-to-manage baselines alongside your sophisticated AI models.

Ready to simplify your baseline recommendation strategy?

Request a demo of Shaped today to explore rule-based models. Or, start exploring immediately with our free trial sandbox.