Photo Store

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.

← Back to the store