Under the hood
How the personalisation works
The whole store is ranked by Crystallize Discovery. No separate recommendation service, no model retrained overnight — just one vector per customer and one ranking rule per surface.
1A vocabulary you own
The range is described in three vocabularies. Each dimension is a topic map in the PIM, and every topic path becomes a vector key: /brand/nikon → brand:nikon. Topics are the single source of truth — taste is derived, never maintained separately.
Brand & system
“brand”
- brand[1, 0.5, 0.25]
- system[1, 0.5]
Use case
“usecase”
- usecase[1, 0.7, 0.45, 0.3]
Product type & level
“gear”
- category[1, 0.5]
- level[1]
- price-tier[0.8]
The weights are positional. A lens listing brand:tamron before brand:nikon weighs 1.0 on Tamron and 0.5 on Nikon — so a Nikon owner sees third-party glass that fits, but Nikon's own lenses first.
2The profile is built from orders, not guesses
The customer's vector is calculated server-side from their order history in Crystallize. Every purchased line contributes its own product vector, weighted by quantity, by how much was spent and by how long ago it was bought (a 180-day half-life). The result is sent to Discovery as context.userTaste.
Pick a customer at the top right to see their actual order history and the vector it produces.
3Your rules stay on top
Taste is one term among several. Margin, stock, sales and campaign weight sit alongside it, and every surface has its own balance. This list is exactly what is sent as rankBy.
Front page
- Brand & systemtasteCosine× 1.70
- Use casetasteCosine× 1.40
- Product type & leveltasteCosine× 0.80
- Sold, 30 daysfieldBoost× 0.55
- MarginfieldBoost× 0.35
- RatingfieldBoost× 0.30
- CampaignfieldBoost× 0.25
- In stockinStockBoost× 0.25
- Newnessrecency× 0.20
Category page
- Brand & systemtasteCosine× 1.40
- Use casetasteCosine× 1.20
- Product type & leveltasteCosine× 1.00
- Sold, 30 daysfieldBoost× 0.55
- MarginfieldBoost× 0.35
- RatingfieldBoost× 0.30
- CampaignfieldBoost× 0.25
- In stockinStockBoost× 0.25
- Newnessrecency× 0.20
Search
- Search relevancerelevance× 2.00
- Brand & systemtasteCosine× 0.90
- Use casetasteCosine× 0.80
- Product type & leveltasteCosine× 0.40
- Sold, 30 daysfieldBoost× 0.30
- In stockinStockBoost× 0.20
Every hit gets a rankScore and a rankExplain whose contributions add up exactly to the score. Click the score badge on a card to see the maths.
4The taxonomy
Six topic maps classify the range. The same maps drive the filters on the category pages and the vectors in Discovery.
Brand /brand
- Canon
- Nikon
- Sony
- Fujifilm
- Panasonic
- OM System
- Leica
- Hasselblad
- DJI
- GoPro
- Insta360
- Sigma
- Tamron
- Viltrox
- +30 more
System & mount /system
- Canon RF
- Canon EF
- Sony E
- Nikon Z
- Nikon F
- Fujifilm X
- Fujifilm GFX
- Micro Four Thirds
- L-Mount
- Any system
Product type /category
- Mirrorless camera
- Compact camera
- Action camera
- Video camera
- Zoom lens
- Prime lens
- Telephoto lens
- Wide-angle lens
- Macro lens
- Drone
- Flash
- Studio lighting
- Tripod
- Gimbal
- +7 more
Use case /usecase
- Wildlife & nature
- Portrait
- Landscape
- Sport & action
- Travel
- Film & video
- Vlog & content
- Studio
- Astro & night
- Street
- Product photography
- Wedding & events
Level /level
- Beginner
- Enthusiast
- Professional
Price tier /price-tier
- Budget
- Mid-range
- Premium
- Flagship
5The APIs
Discovery API
The whole frontend: front page, campaign blocks, category listings, facets, search, similar products.
context + rankBy + nearestTo, public and unauthenticated.
Shop API
Basket and checkout.
hydrate → place → createFromCart, with tax calculated from the market's rate.
Core API
Customers, customer groups and order history.
Read server-side to build the profile vector. Never exposed to the browser.