Skip to main content

Personalized Grids Like Netflix

Think about interfaces like Netflix, YouTube, or major e-commerce marketplaces. They often present content not just as a single ranked list, but as a grid. Rows might represent different genres, categories, brands, or topics, while the columns within each row show specific items ordered by relevance. This grid layout is incredibly effective for discovery – it allows users to quickly scan different themes (rows) while also diving into specific relevant items (columns) within those themes.

Building such an interface, however, presents a significant personalization challenge. You need to solve two ranking problems simultaneously:

  1. Row Ranking: Which attributes (genres, categories, brands) are most relevant to this specific user, and in what order should they appear vertically?
  2. Item Ranking: Within each selected row attribute, which specific items are most relevant to this user, and how should they be ordered horizontally?

Simply showing globally popular categories or randomly ordered items within rows misses the mark. True personalization requires optimizing both dimensions based on individual user preferences. Building this capability from scratch involves tackling complex, multi-stage modeling and significant engineering efforts, akin to those faced by major platforms trying to optimize similar layouts.

Building a Personalized Grid with Shaped

Let's illustrate creating a personalized grid where rows are defined by category.

Goal: For test_user, display a grid with the 10 most relevant categories as rows, and the 10 most relevant items within each of those categories as columns.

1. Ensure Data is Connected: Assume item_metadata (with an accurate category column and other features) and user_interactions datasets are connected and used for model training.

2. Define Your Shaped Model (YAML): A standard model definition works. Crucially, the attribute you want to use for rows (category in this case) MUST be included as a field in your fetch.items query.

grid_ranking_model.yaml
model:
name: personalized_grid_engine
connectors:
- type: Dataset
name: item_catalog_with_category
id: items
- type: Dataset
name: user_activity
id: interactions
fetch:
items: |
SELECT
item_id,
title,
description,
category, # <-- The attribute defining the rows MUST be selected
image_url,
product_url
FROM items
events: |
SELECT user_id, item_id, timestamp AS created_at, event_type FROM interactions

3. Create the Model:

Run the following command to create a model from the configuration file:

shaped create-model --file grid_ranking_model.yaml

4. Monitor Training: Wait for the model personalized_grid_engine to become ACTIVE.

You can run the following command to check the status of the model training.

shaped view-model --model-name personalized_grid_engine 

5. Fetch the Personalized Grid (Application Backend Logic): When you need to display the grid for test_user:

  • Step A (Your Backend): Identify the user_id ('test_user') and the name of the item attribute column that defines the rows ('category').

  • Step B (Your Backend): Call Shaped's /rank_attribute_grid API endpoint.

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

const apiKey = process.env.SHAPED_API_KEY;
const shapedClient = new ShapedClient({ apiKey });
const gridData = await shapedClient.rankAttributeGrid({
modelName: 'personalized_grid_engine',
userId: 'test_user',
attributeName: 'category', // Must match a column name in items data
rowLimit: 10,
colLimit: 10,
returnMetadata: true
});
console.log(`Successfully retrieved grid with ${gridData.rows.length} rows.`);

  • Step C (Frontend): The API response contains a structured list of rows. Each row includes the attribute_value (e.g., 'Action', 'Comedy') and a list of ranked items (with metadata if requested) for that attribute, already personalized for the user. Use this structured data to directly render the grid UI.

6. Clean Up (Optional):

Run the following line of code if you want to delete your model.
shaped delete-model --model-name personalized_grid_engine

Conclusion: Sophisticated Layouts, Radically Simplified

Personalized grid layouts, like those popularized by Netflix, offer a superior discovery experience but traditionally demand substantial engineering effort, involving complex dual-ranking problems, potentially multi-armed bandit systems, and near real-time data infrastructure.

Shaped cuts through this complexity with the dedicated /rank_attribute_grid API endpoint. By leveraging a single, powerful underlying model and handling the sophisticated optimization internally, Shaped delivers a fully personalized grid structure through one simple API call. Avoid the deep dive into bandit implementation, stream processing, and multi-model orchestration. Build engaging, dynamic grid interfaces efficiently and focus on your core product experience.

Ready to build personalized discovery grids without the engineering headache?

Request a demo of Shaped today to see attribute grid ranking in action. Or, start exploring immediately with our free trial sandbox.