Personalized
Per-user re-ranking driven by analytics history and segment membership. The right engine when you know who the user is.
GET /recommendations/personalized returns items ranked for one specific user, mixing their interaction history with the broader trending signal.
Two endpoints power this:
GET /recommendations/personalized— Fast path. Reads precomputed per-user vectors.GET /recommendations/personalized-from-analytics— Slow path. Walks the user's recent events live; use for users without a precomputed vector.
The API picks the right one automatically based on whether the user has a precomputed vector. You always call personalized.
Request
GET /recommendations/personalized?indexId=<id>&userId=<id>&limit=10
Authorization: Bearer <api-key>| Param | Type | Required | Notes |
|---|---|---|---|
indexId | string | yes | Source index. |
userId | string | yes | Stable user identifier — session id, account id, or hashed email. |
limit | number | no | 1–50, default 10. |
filterBy | string | no | Optional facet constraint. |
segment | string | no | Optional user segment ID. |
Response
{
"items": [
{ "id": "sku-9001", "score": 0.82, "data": { ... } }
],
"userId": "u_abc",
"engine": "personalized" | "personalized-from-analytics" | "trending",
"coldStart": false
}The engine field tells you which path served the request. "trending" means cold start (see below).
Cold start
When a user has < 5 events, personalization is statistically worse than trending. The API detects this and silently falls back. The response carries coldStart: true and engine: "trending" — you can branch your UI labelling on it.
Do not hide the rail when coldStart=true. The user sees something useful (trending). Hiding it hurts conversion for the entire cold-start cohort, which is sometimes 30–40% of homepage views.
Required signal
The userId must be the same string the analytics events use. Otherwise the engine has no history to draw on.
For anonymous visitors, generate a stable session id at first page load (cookie / localStorage) and use it as userId. AACsearch does not require it to be a real account id.
Latency
| Path | p95 (Pro) |
|---|---|
personalized (precomputed) | 120 ms |
personalized-from-analytics | 200 ms |
trending (cold start) | 40 ms |
Configuration
GET /recommendations/personalization-config returns the active config. Key knobs:
historyWindow— How far back to look (default 30 days).decay— Half-life for events (default 7 days).model— Embedding model for re-ranking.
Tune via dashboard → Search → Recommendations → Settings, or PATCH /recommendations/personalization-config.
Code path
packages/api/modules/recommendations/procedures/personalized.ts + personalized-from-analytics.ts. Precomputed vectors are produced by a nightly batch job documented in packages/recommendations/.