Open-source Spryker search tools

Explainable, tunable search relevance for Spryker.

Debug and improve product ranking in Spryker with transparent scoring for Elasticsearch and OpenSearch.

finalScore =

Normalized text relevance + normalized business signals.

01 / 05

How a result gets its score

Every hit is a convex combination of normalized text relevance and a weighted sum of business signals.

The model has exactly two terms. α decides how much influence text relevance receives; 1 − α gives the remaining influence to business signals.

Because both terms are normalized, their contributions remain comparable and the final score stays interpretable.

Implemented by Search Ranking · explained by Search Debug

02 / 05

Normalize Elasticsearch relevance

Elasticsearch's unbounded _score is squashed into a stable range from zero up to—but never reaching—one.

The transformation preserves the ordering of results while preventing large raw scores from overwhelming every other signal.

It uses the same saturation shape that BM25 applies to term frequency, here applied to the complete document score.

score / (score + k)

03 / 05

Choose the saturation point

The parameter k controls where normalized relevance reaches exactly 0.5.

When score = k, the relevance term equals 0.5. Lower values saturate earlier; higher values preserve more differentiation between large Elasticsearch scores.

Rather than choosing k by guesswork, Search Ranking can estimate a practical starting point from representative searches. Import a CSV of typical queries and define the depth to inspect; the package executes the set, samples the highest-ranked results, analyzes their raw _score values, and recommends the observed mean as the initial saturation point.

Representative queries + sampling depth → observed _score distribution → suggested k

04 / 05

Add normalized business signals

The second term combines product-level signals such as click-through rate, conversion rate, availability, or margin.

Each metric is transformed into a value between zero and one before it enters the formula. This makes signals with very different units comparable.

Search Ranking derives an aggregate frequency distribution from the metric data and evaluates the available normalization functions against that observed shape. The analysis view presents the empirical distribution beside the fitted curve and recommends the closest match; the selected expression remains fully configurable.

A low-weight random() signal is also worth including in the business term. It breaks deterministic ties, introduces controlled variation, and prevents the same products from becoming permanently locked into identical positions.

Distribution analysis → normalization-function suggestion · low-weight random() for controlled variation

05 / 05

Keep signal weights comparable

Entered signal weights are force-normalized so their sum always equals one.

Editors can express relative importance without manually maintaining a perfect total. A weight of 30 and a weight of 10 become 0.75 and 0.25.

This normalization runs once when configuration is published, keeping the query itself simple.

wi = enteredWeighti / Σ enteredWeightj

Resources

Seven open-source packages behind one composer require — search relevance, debugging, indexing and analyzer config for Spryker.

Full package overview →

Roadmap

Search Relevance v1 targets the capabilities available in OpenSearch 1.3, which has been the default for Spryker installations for several years.

With Spryker now enabling OpenSearch 3.x, a new generation of ranking features becomes practical. Search Relevance v2 will explore reranking, hybrid retrieval, Learning-to-Rank and other capabilities that previously weren't available.

Origins

This project's starting point is Spryker's own Data-driven ranking best-practice document — which itself documents a real system, not a Spryker invention: the ranking approach originally designed and implemented by Martin Loetsch and Krešimir Slugan at Contorion. Spryker's core never shipped an implementation of it, only the write-up.

search-ranking and search-ranking-optimizer are that idea built out and adapted for Spryker's actual plugin/facade architecture, then extended well past the original scope — locale/store scoping, specificity-aware relevance weighting, and automated black-box optimization among them.