Cookbook: integrate with a content feed¶
This guide shows how to cookbook: integrate with a content feed in a reliable, repeatable way.
Who this is for¶
Engineers integrating recommendations into a feed-like product (articles, videos, collections).
What you will get¶
- A surface plan for feed placements (
home,related,next_up) - A minimal request + attribution pattern that supports offline eval and experiments
- Pitfalls to avoid for infinite scroll and delayed outcomes
Goal¶
Integrate recommendations into a feed-like product (articles, videos, collections) with attribution that supports both offline evaluation and online experiments.
Typical surfaces¶
home: personalized feed modulesrelated: “related content” blocks on detail pagesnext_up: “watch next” / “read next”
Use surfaces to represent “where the list appears”, not “what the algorithm is”. You can change algorithms without breaking instrumentation if surfaces stay stable.
Minimal serving integration¶
- Call
POST /v1/recommendwith a stablerequest_id. - Render results in the feed module.
- Log exposure and outcomes with that same
request_id.
Example request:
curl -fsS http://localhost:8000/v1/recommend \
-H 'Content-Type: application/json' \
-H 'X-Request-Id: feed-req-1' \
-H 'X-Dev-User-Id: dev-user-1' \
-H 'X-Dev-Org-Id: demo' \
-H 'X-Org-Id: demo' \
-d '{"surface":"related","k":8,"user":{"user_id":"u_9","session_id":"s_9"}}'
Outcomes: decide what counts as “success”¶
Pick one primary outcome to start:
- click →
click - long read / watch completion →
conversion
If you change the definition of “conversion”, treat it as an evaluation contract change and communicate it (otherwise metric trends become incomparable).
Verify¶
- Validate schemas with
recsys-eval validate. - Slice join rates by platform (web/app) and surface (
home,related). - Track “empty recs” rate per surface; it’s a fast signal of missing signals or bad rules.
Pitfalls¶
- Infinite scroll creates many recommendation calls
- Fix: log one exposure per rendered module instance; avoid reusing
request_idacross modules. - Outcome events missing
item_id - Symptom: conversions exist but can’t be attributed to ranked lists.
- Delayed outcomes
- For long reads/watches, outcomes may arrive minutes later. Ensure your event pipeline preserves
request_id.
Read next¶
- Exposure logging & attribution: Exposure logging and attribution
- Event join logic: Event join logic (exposures ↔ outcomes ↔ assignments)
- Run evaluation and decide ship/hold/rollback: How-to: run evaluation and make ship decisions