Skip to content

Developer Introduction

Bizzkit Ecommerce Search is a multi-host search platform that ingests product, content, and behavioral data from external systems (PIM, CMS, Builder.io, Google Analytics, and more) and provides fast, AI-enhanced search capabilities to storefronts and back-office applications.

Think of Ecommerce Search as the search brain of a Bizzkit-powered ecommerce site: it takes raw product data from PIM, editorial content from CMS and Builder.io, and commercial signals from analytics — then makes all of that searchable, filterable, and rankable in real time.

High-Level Data Flow

Hold "Ctrl" to enable pan & zoom
graph TD
    subgraph Sources["External Data Sources"]
        PIM
        CMS
        Builder["Builder.io"]
        GA4["GA4 (Google)"]
        BAIA["BAIA (AI)"]
        ERP
    end

    subgraph Courier["Courier (Ingestion Hub)"]
        CourierAPI["Courier API (on-demand)"]
        CourierRunner["Courier Runner (scheduled)"]
    end

    subgraph ECSCore["Ecommerce Search Core (Search Platform)"]
        AdminAPI["Admin API (config, ingest)"]
        SearchHost["Search Host (read-only queries)"]
        JobRunner["Job Runner (index rebuilds)"]

        subgraph Infra["Shared Infrastructure"]
            ES["Elasticsearch (search index)"]
            SQL["SQL Server"]
            Redis["Redis (cache)"]
            ASB["Azure Service Bus (messaging)"]
        end

        AdminAPI --> Infra
        SearchHost --> Infra
        JobRunner --> Infra
    end

    subgraph Consumers
        Storefront["Storefront (React, Next.js)"]
        AdminUI["Admin UI (Ecommerce Search config)"]
        OtherProducts["Other Bizzkit Products (via C#/TS SDKs)"]
        CustomerSolution["Customer Solution"]
    end

    PIM --> Courier
    CMS --> Courier
    Builder --> Courier
    GA4 --> Courier
    BAIA --> Courier
    ERP --> ECSCore

    CourierAPI --> ECSCore
    CourierRunner --> ECSCore

    ECSCore --> Storefront
    ECSCore --> AdminUI
    ECSCore --> OtherProducts
    ECSCore <--> CustomerSolution

Essential Concepts

Segments

A segment allows a customer to model their different markets, languages, and assortments as separate search configurations. Products, SKUs, configurations, experiences, and business rules are all scoped to a segment. Language dictionaries are the exception: they belong to a language and can be shared by several segments (see Language dictionary).

A segment typically represents a combination of market, language, and channel. For example:

Segment ID Meaning
b2c-dk-en B2C site, Denmark, English
b2b-se-sv B2B site, Sweden, Swedish

When you call any Ecommerce Search API, you specify which segment you're operating on via the segmentId parameter.

Products & SKUs

  • Product — A logical grouping of variants (e.g., "Running Shoe Model X").
  • SKU (Stock Keeping Unit) — The actual sellable item with a specific price, size, color, and stock status (e.g., "Running Shoe Model X, Black, Size 42").

A single product can have many SKUs. In search results, Ecommerce Search returns products with their matching SKUs grouped together.

Time-based pricing

Prices on a SKU can be planned ahead of time. A SKU can be ingested with several prices, each with its own validFrom date, and Ecommerce Search switches to the next price when its date is reached. Price changes take effect on an hourly basis. This makes it possible to prepare a campaign price, such as for Black Friday, without ingesting the SKU again when the campaign starts or ends. The ingested prices must always include the price that is currently active. See Pricing strategies.

Fields

Fields are the data attributes available on products and SKUs. Each field has a type that determines whether it can be searched, filtered, or used as a facet.

Field Type Searchable Filterable / Facet
Product Name Predefined Yes No
Product Number Predefined Yes Filter only
Product ID Predefined Yes Filter only
Short Description Predefined Yes No
Long Description Predefined Yes No
Alternative Search Words Predefined Yes No
SKU Name Predefined Yes No
SKU Number Predefined Yes Filter only
SKU EAN Predefined Yes Filter only
SKU ID Predefined Yes Filter only
String Attribute Dynamic (per SKU) Yes Yes
Number Attribute Dynamic (per SKU) No Yes
Interval Attribute Dynamic (per SKU) No Yes
Categories Predefined Yes Yes
Category IDs Predefined No Yes
Price Predefined No Yes
Price Group Predefined No No
In Stock Predefined No Yes
Stock Predefined No No
Searchable IDs Predefined No Yes
Product Metadata Dynamic (per SKU) No No
SKU Metadata Dynamic (per SKU) No No
Media Predefined No No
Rating Predefined No No
Savings Predefined No No
  • Searchable fields are matched against the user's search phrase during keyword search. Which fields are searchable is configurable per segment — the table above shows the defaults. Fields can also be marked as quick-searchable, meaning they are included in quick search (typeahead) queries — by default only Product Name and SKU Name.
  • Filterable fields can be used in search request filters and can appear as facets. Which fields are exposed as allowed filters is controlled by publication configuration. Fields marked Filter only (Product Number, Product ID, SKU Number, SKU EAN, SKU ID) can be added as allowed filters for service-level filtering but cannot be used as customer-facing facets.
  • Dynamic fields (String Attribute, Number Attribute, Interval Attribute) are created from the ingested product data — their names come from PIM attribute definitions.

Parameters

Parameters are inputs to the commercial sort scoring system. They are not searchable and not filterable — their sole purpose is to influence how products are ranked in search results.

A parameter takes a raw input value from one of three sources:

  • An external source, where values such as sales count or margin are ingested from an ERP or analytics system.
  • A field already ingested into Ecommerce Search, such as a number attribute like rating.
  • Signals, where Ecommerce Search collects the values itself from Bizzkit Event Tracking (see Signal parameters).

The input value is then normalized into a score between 0 and 1, which feeds into the commercial sort calculation.

The normalization strategy depends on the parameter type:

Parameter Type Normalization Strategy Example Use Case
Term Matches a string value against configured partitions. If the value matches a partition, the score is 1; otherwise 0. Brand = "Premium" → boost
Range Checks whether a numeric value falls within a configured range. If it does, the score is 1; otherwise 0. Price between 100–500 → boost
Rank Ranks all SKUs by a numeric value using interpolation across clusters, producing a continuous score between 0 and 1. Sales count → top sellers ranked higher
AI Ranking Similar to Rank, but scores on automatically collected signals. Clicks last 24 hours → popular products ranked higher

Each parameter has partitions — named segments within the parameter that define how values map to commercial boost. For example, a Term parameter for "brand" might have partitions for "Premium" and "Economy", each contributing differently to the sort score.

Signal parameters

A signal parameter is an AI Ranking parameter that uses the Signals source. Instead of ingesting values from an external system, Ecommerce Search fetches pre-aggregated conversion and engagement data from Bizzkit Event Tracking and keeps it up to date automatically. The available signal types are:

  • Turnover: revenue per product, from order events.
  • Line count: order lines per product, from order events.
  • Clicks: clicks per product, from click events.

Signal parameters require an active Event Tracking integration, and only the signal types whose events are tracked are useful. See Signal parameters.

Scopes

A scope defines a named configuration for the Search Host. It controls which fields are returned, which facets are shown, and default result counts. Critically, every scope has a scope type that tells Ecommerce Search what the user's intent is.

Scope Types

Each scope is assigned a ScopeType that represents the user intent behind the request:

Scope Type Intent
FullSearch User is on a search results page (typed a search phrase)
Browse User is on a category or overview page (no search phrase)
QuickSearch User is typing in the search box (quick search/suggestions)
Details User is viewing a product detail page
Basket User is on the basket/cart page
Checkout User is on the checkout page
OrderConfirmation User is on the order confirmation page
Bands Request is for a page widget (e.g., recommendations, related products)
MachineSearch Request is system-to-system, not triggered by an end user

Why Scope Type Matters for Tracking

Using the correct scope and scope type is essential for tracking and analytics to work correctly. Ecommerce Search sends an event for each search request to Bizzkit Event Tracking, where the scope type is used to capture user intent and build analytics such as:

  • Findability metrics — measuring whether a search (FullSearch) led to a product view (Details) and eventually a purchase (OrderConfirmation). If the wrong scope type is used, Ecommerce Search cannot connect these steps in the user journey.
  • Search funnel analysis — tracking the path from search → browse → details → checkout. Each step must use its corresponding scope type so the analytics pipeline can reconstruct the user's session.
  • Popular search phrases — only requests with FullSearch scope type are counted as real searches. If a Browse request is miscategorized as FullSearch, it inflates search phrase statistics.

Common mistakes:

Mistake Impact
Using FullSearch for category pages Category views counted as searches, inflating search metrics
Using Browse for actual search queries Real searches invisible in findability reports
Using FullSearch for quick search/typeahead Every keystroke counted as a full search
Not using Details for product page loads Findability cannot detect if a search led to a product view

Rule of thumb: Match the scope type to the page the user is on, not to the type of data you're fetching.

Traffic filtering

Searches made by crawlers or by your own systems, such as monitoring and load tests, should not count in the analytics. Traffic filtering keeps them out of search tracking:

  • Crawlers are filtered automatically based on the user agent in the X-Forwarded-User-Agent header.
  • IP addresses and CIDR ranges configured through the Admin API are filtered based on the X-Forwarded-For header.

When the search request is made from your backend, forward the end user's user agent and IP address in these headers, otherwise the filtering cannot work. See Traffic filtering.

Common Scope Configurations

Scope ID Scope Type Use Case
full-search FullSearch Search results page (products + content + suggestions)
browse Browse Category browsing (no text query)
quick-search QuickSearch Quick search/suggestions while typing
details Details Product detail page (fetch related data)

Publications

Ecommerce Search uses a draft → publish workflow for configuration changes:

  1. Draft: Administrators configure business rules, synonyms, parameters, etc. in the Admin UI.
  2. Publish: A snapshot of all configuration is created and pushed live.
  3. Live: Search queries use the published snapshot. The previous publication remains available as a rollback target.

This means configuration changes are not applied immediately — they require an explicit publish step. This is important to understand when integrating, as changes to business rules or synonyms won't affect search results until they're published.

Targets

Targets are user-defined conditions that allow integrators to pass contextual information from the storefront into the search request. Ecommerce Search uses targets as additional conditions when resolving business rules, making it possible to customize search behavior based on context that only the calling application knows about.

A target is created through the Admin API with an ID, a name, and a set of predefined values. Once created, its values can be used as conditions on experiences and business rules in the Admin UI. For example:

Target ID Name Values
weather Weather sunny, raining, snowing
gender Gender male, female
campaign Campaign holiday, summer-sale, black-friday

When the storefront makes a search request, it can include targets in the targets field:

1
2
3
4
5
6
7
8
9
{
  "segmentId": "b2c-dk-en",
  "scopeId": "full-search",
  "phrase": "jacket",
  "targets": {
    "weather": ["raining"],
    "campaign": ["summer-sale"]
  }
}

These target values are then used as conditions in business rule matching. A business rule conditioned on weather = raining would only be selected as the best fit when the search request includes that target value. This enables scenarios like:

  • Weather-based merchandising — Boost rain jackets when the storefront knows it's raining at the user's location.
  • Campaign-specific ranking — Show different pinned products or facets during a holiday campaign vs. a summer sale.
  • Gender-targeted facets — Display different filter options depending on the audience segment.

Targets are entirely customer-defined — Ecommerce Search does not prescribe what targets should exist. The storefront team decides which contextual dimensions are relevant and creates them through the Admin API. The integrating application is then responsible for passing the appropriate target values in each search request.

A campaign target depends on the storefront sending the target value, so the storefront decides when the campaign runs. To start and stop a campaign on a schedule without any change to the storefront, use a time-based variant of an experience instead. See Targets.

Experiences

An experience is a named set of search settings that Ecommerce Search selects from the search request. It consists of conditions, which decide when the experience applies, and the business rules (described below) that define its settings: facets, parameters, category boosts, pins, relevance weights, affinity weights, semantic search boost, and bury rules.

Experiences are what users create and edit in the Admin UI, typically through the Playground. An experience for the "Shoes" category, for example, can show a shoe width facet and rank by a different parameter than the rest of the shop. Business rules are inherited from less specific experiences, so an experience only needs to define the settings that differ. Experiences can also be tagged, so that users can find them again in long lists. See Experiences.

Time-based variants

A time-based variant is a version of an experience that applies only during a scheduled period. A period has a required start time and an optional end time, and Ecommerce Search activates and expires the variant automatically. This lets merchandisers prepare campaign, seasonal, or product launch settings in advance, and have the normal setup return automatically when the campaign ends. A period is also a business rule condition, and it takes priority over other conditions when Ecommerce Search selects the best fit. See Time-based experiences.

Business Rules

Business rules are conditional configurations that modify search behavior based on context. Each business rule has a type that determines what aspect of the search it controls:

Business Rule Type What It Controls
Facets Which facet filters appear in the search results (e.g., color, size, brand)
Parameter Which parameter is used and how it is partitioned, one rule per parameter
Category Boost Products in a category and its subcategories ranked higher, one per category
Pinned Products Specific products forced to the top of results in a defined order
Relevance Boost Which fields are boosted and by how much (e.g., boost title over description)
Affinities Personalization weights based on user affinity data
Semantic Search Boost Whether AI vector embeddings are used for meaning-based matching
Bury Products that are moved below the rest of the results (see Bury)

Conditions and Best-Fitting Matching

Business rules support inheritance through a best-fitting matching algorithm. Each business rule can be configured with conditions — such as which scope is used, which category the user is browsing, whether a search phrase is present, or custom target values (e.g., device type, campaign).

When a search request comes in, Ecommerce Search evaluates the conditions from the request against the available business rules independently for each business rule type. For each type, it finds the business rule whose conditions best match the current request:

  1. Candidate selection — Ecommerce Search finds all business rules of a given type whose conditions are fully satisfied by the incoming request.
  2. Best fit — Among the candidates, the rule that matched the most conditions wins. This means a more specific rule (e.g., one conditioned on scope + category + phrase) will beat a less specific one (e.g., conditioned on scope only).
  3. Fallback — If no business rule's conditions are met, a fallback rule (one with no conditions) is used, if one exists. This acts as the default configuration.

This means you can set up a general default business rule for each type and then create more specific overrides for particular contexts — without duplicating the full configuration. For example:

Rule Name Type Conditions Effect
Default facets Facets (none — fallback) Show color, size, brand, price
Shoes category facets Facets Category = "Shoes" Show color, size, brand, price + shoe width
Default relevance Relevance Boost (none — fallback) Standard field weights
Holiday campaign relevance Relevance Boost Target: campaign = "holiday" Boost "gift" and "seasonal" fields

In this example, a search request browsing the "Shoes" category would use the "Shoes category facets" rule for facets (more specific match) but the "Default relevance" rule for relevance boosting (no specific relevance rule for shoes). Each business rule type is resolved independently.

Bury is the one exception to the best-fit selection: all bury rules whose conditions are met apply at the same time.

Bury

Bury ranks products lowest instead of hiding them. Each bury rule matches one field and value, such as In stock = false or Category = Clearance. A product that matches any active bury rule is moved below all non-buried products, but it is still returned in search and category pages. Matching several bury rules does not push a product further down. Bury is useful for out-of-stock products that should stay searchable, or for products with low business value. See Bury products.

Affinities

Affinities are the personalization mechanism of Ecommerce Search. They allow search results to be boosted based on how well a product's attributes align with a user's preferences or an audience's profile. The core idea is simple: products are tagged with affinity values (e.g., "this product is 0.8 vegan"), and users or audiences are also tagged with affinity values (e.g., "this user is 0.6 interested in vegan"). When these overlap, the product gets a ranking boost.

Affinities are organized by data sources — each source represents a distinct origin of affinity data (e.g., Google Analytics, a recommendation engine, manually curated segments). A business rule of type Affinities controls which data sources are active and their relative weight.

Item Affinities

Every product/SKU in Ecommerce Search can have item affinities — numerical values (0 to 1) representing how strongly the product is associated with specific attributes. These are ingested alongside product data, typically from PIM or a recommendation engine.

For example, a product might have:

Attribute Affinity Value
vegan 0.8
color_yellow 0.4
sustainable 0.9

User Affinities

User affinities represent an individual user's preferences. They are ingested per user (identified by userId) and map the same attributes to preference scores. User affinities are typically derived from behavioral data — what the user has browsed, purchased, or interacted with.

When a search request includes a userId, Ecommerce Search looks up that user's affinities and computes a personalized boost for each product:

boost = item affinity × user affinity × weight

where the weight comes from the active Affinities business rule for the data source.

User affinities have a time-to-live (30 days) — they expire automatically, reflecting that user preferences change over time.

Audience Affinities

Audience affinities represent the preferences of a group of users rather than an individual. An audience is created through the Admin preview API with an ID (e.g., male, returning-customers, high-spenders) and a set of affinity values per data source — similar to user affinities, but shared across all members of the audience. In the Admin UI, the Playground can preview search results as a member of an audience.

When a search request includes audienceIds, Ecommerce Search applies the audience's affinity profile to boost results. This is useful when individual user-level data isn't available but you know which audience segment the user belongs to.

Audiences are flexible beyond demographic segments — they can also model physical locations. For example, an audience can represent a physical shop (e.g., shop-copenhagen), where the affinity values reflect the products that shop actually has in stock. A customer visiting the Copenhagen shop would have audienceIds: ["shop-copenhagen"] passed in their search requests, causing Ecommerce Search to boost products available in that shop's storage. In this model, "audience" effectively means "the context of someone visiting this shop."

The scoring works the same way as user affinities:

boost = item affinity × audience affinity × weight

Both user affinities and audience affinities can be active simultaneously — their boosts are additive.

  1. Item affinities are ingested with product data and stored per SKU.
  2. User affinities are ingested per user via the Admin API and indexed in a dedicated user affinity index in Elasticsearch.
  3. Audience affinities are ingested via the Admin preview API.
  4. At search time, the active Affinities business rule determines which data sources are used and their weights.
  5. For each product in the result set, the affinity score is calculated by multiplying item affinities with user/audience affinities and the configured weight.
  6. The affinity boost is added to the product's commercial sort score, influencing the final ranking.

Facets & Filters

  • Facets are the filter navigation you see on a search results page (e.g., "Color: Red (12), Blue (8), Green (3)"). Ecommerce Search returns facets alongside search results so the UI can render filter options with counts.
  • Filters are applied in search requests to narrow results. There are three types:
    • String filter — Exact value match (e.g., "COLOR": {"values": ["Black"]}).
    • Range filter — Numeric range (e.g., price between 100 and 500).
    • Price range filter — Specialized price filtering with currency awareness.

Filters sent in a search request are validated against a published allowed filter list. Only filters matching an allowed field name are applied. This prevents callers from filtering on arbitrary internal fields.

Domain Filters

A domain filter is a filter that is applied to the Elasticsearch query as a hard constraint — it restricts which documents are considered without affecting facet counts. Domain filters come from three sources:

  1. Scope configuration — Filters configured directly on a scope (e.g., inStock: true), baked into the published configuration. These are always applied regardless of what the caller sends.
  2. Authenticated filters — Filters extracted from a signed JWT token (see below).
  3. Regular filters on non-facet fields — When a caller sends a regular filter on a field that is not currently used as a facet, that filter is also treated as a domain filter.

The distinction between a domain filter and a facet filter matters because of how facet counts are calculated. When a filter targets a field that is also a facet, Ecommerce Search must compute how the filter affects the facet values and their counts — the facet still needs to show the user which values are available and how many results each value would produce if selected. A domain filter, by contrast, simply restricts the result set without this facet-count calculation overhead.

For example, a scope for a B2B storefront might have a domain filter inStock: true so that out-of-stock products never appear, no matter what filters the caller includes. Because inStock is configured as a domain filter on the scope, it silently constrains results without appearing in the facet navigation.

How Authenticated Filters Become Domain Filters

Ecommerce Search supports authenticated search via a signed JWT token passed in the authenticationToken field of the search request. This token is created server-side (using the Bizzkit.Sdk.Search.Authenticated SDK) and can contain filters embedded as claims.

When Ecommerce Search receives a search request with an authentication token:

  1. The token is validated against the segment's signing keys.
  2. Filters from the token's claims are extracted as authenticated filters.
  3. Authenticated filters bypass the allowed filter list — they are not subject to the same allowlist validation as regular filters.
  4. Authenticated filters are merged with domain filters and regular filters to form the full set of domain filters applied to the Elasticsearch query.

This mechanism is used when a backend system needs to enforce filters that the frontend cannot tamper with. For example:

  • A B2B portal issues a token with priceGroup: "wholesale" so the customer only sees wholesale prices.
  • A customer-specific token restricts search results to a particular assortment or catalog subset.

The key difference between filter types:

Filter Type Source Validated Against Allowlist Treated As Domain Filter Can User Override?
Regular filter (facet field) Search request body Yes No (affects facet counts) Yes
Regular filter (non-facet field) Search request body Yes Yes Yes
Scope domain filter Scope configuration No (preconfigured) Yes No
Authenticated filter JWT token claims No (trusted) Yes No

Suggestions

Suggestions are typeahead entries shown as the user types in the search box, providing a fast path to relevant results. Suggestions are generated by a suggestion generator that you configure in the Admin UI.

The suggestion generator lets you select which fields are used to produce suggestion candidates. While it is possible to include product names, this often doesn't work well in practice — generating a unique suggestion for every product creates too many low-value entries. Instead, suggestions tend to work best when built from broader fields like categories and brands, which group many products under a single, high-value suggestion.

For example, typing "run" would suggest "Running shoes" (a category) or "Nike" (a brand) rather than listing individual product names like "Nike Air Zoom Pegasus 40 Black Size 42".

Suggestions that contain a registered misspelling are filtered out of the suggestion results automatically, so users only see correctly spelled suggestions. If "djor" is registered as a misspelling of "dior", a suggestion such as "djor perfume" is not shown. See Misspelling filtering.

Quick Search Spotlight

Quick Search Spotlight is a list of up to 10 search phrases shown when the user activates the search box, before they start typing. It guides users who don't yet know what they are looking for toward trending or promoted searches.

When the phrase is empty and the scope has Quick Search Spotlight enabled, the search response returns the phrases in quickSearchSpotlights instead of suggestions. Once the user starts typing, regular suggestions take over. By default, the list is filled automatically with the most popular search phrases from the last 30 days. Merchandisers can add manual, scheduled phrases at specific positions, and only phrases that return at least one result are shown. See Quick Search Spotlight.

Language Dictionary

Ecommerce Search models search language understanding through six separate dictionary types, each representing a distinct aspect of how natural language works. This is an intentional design choice — rather than mirroring how Elasticsearch technically handles text analysis, Ecommerce Search models how a language actually works.

Dictionary type What It Does Example
Synonyms Maps words with the same meaning so either term finds the same results "car" ↔ "automobile"
Hypernyms Maps specific terms to broader categories (is-a relationships) "denim" → "pants", "espresso" → "coffee"
Irregular Words Handles irregular forms that standard stemming cannot resolve "mice" → "mouse", "children" → "child"
Misspellings Replaces known common misspellings in the search phrase with their correct form "recieve" → "receive", "definately" → "definitely"
Ignored Words Removes common words with little meaning from both product texts and searches "the", "of", "is"
Stemming Overrides Prevents words with different meanings from being stemmed to the same root "training" is not stemmed to "train"

Each dictionary type serves a different linguistic purpose and is managed separately, in the Admin UI or through the Admin API. Together, they allow search to understand the nuances of language rather than relying solely on Elasticsearch's built-in text analysis. Two further dictionary types, Taboos and Related tag groupings, control suggestions rather than text analysis.

Each dictionary has a language, and a segment can use any number of dictionaries in its own language. This makes it possible to share a general dictionary across all segments of a language and add a specialized dictionary to a single segment. Segments use a copy of each dictionary that is made when the segment is published, so dictionary changes take effect at the next publication. See Dictionaries.

Misspellings

Misspellings are not part of the text analysis pipeline. Instead, Ecommerce Search replaces registered misspellings in the search phrase before anything else happens in the search request. The corrected phrase is then used everywhere: for products, content, suggestions, and redirects. It is also returned as usedPhrase in the search response. A search for "kitten calender" therefore returns the results for "kitten calendar", and a misspelled category name can redirect to the category without a separate phrase mapping.

Misspellings only correct the search phrase, never the product texts. A word registered as a misspelling becomes unsearchable, so misspellings should only be used for real spelling mistakes. Setting forceSearch on the request skips the replacement. See Misspellings.

Did You Mean

Ecommerce Search does not use fuzzy search, so a typo is only corrected automatically if it is registered as a misspelling. Did You Mean covers the remaining cases. It finds an alternative phrase for small typos, missing or superfluous spaces, and missing hyphens, such as "bicykle" → "bicycle" or "icecream" → "ice cream". The alternatives are based on the indexed products, content, and spelling data, so they are not manually curated.

In a unified search, Did You Mean is fetched in parallel with the other searches and returned in didYouMean. If the original phrase finds no results, Ecommerce Search automatically searches again with the first Did You Mean alternative and returns the new phrase in usedPhrase. Did You Mean is also available as a separate endpoint, POST /did-you-mean. To stop Did You Mean from changing a correctly spelled word, register that word as the correct spelling in a misspelling dictionary. See Did You Mean.

Redirects

Redirects allow Ecommerce Search to detect when a user's search phrase exactly matches a known entity and instruct the frontend to navigate the user to a dedicated page instead of showing generic search results. Many shops invest significant effort in optimizing category landing pages with curated branding, tailored boost configurations, and subcategory navigation — redirects ensure users reach these optimized pages when their search intent clearly maps to a specific category or product.

Ecommerce Search can automatically trigger redirects when a search phrase matches a category name, product name, SKU ID, SKU number, or a custom string attribute (e.g., brand). Beyond automatic detection, administrators can define phrase mappings — manual redirects that map a specific phrase to a target (e.g., "fancy pants" redirects to the "Pants" category). Specific phrases can also be excluded from automatic redirect detection when a redirect would be disruptive (e.g., "sale" or "new arrivals").

Redirects are resolved for FullSearch and QuickSearch scopes, after misspellings have been replaced in the phrase. The redirect check therefore sees the same corrected phrase as the search, so a misspelled category or brand name still redirects.

For full details on the redirect mechanism, see the Redirects concept page. For frontend implementation guidance, see Handling Redirects.

Commercial Sort

Commercial sort allows ranking products based on commercial parameters like profit margin, popularity scores, or manually assigned weights — beyond pure text relevance. This is configured per segment and business rule.

Ecommerce Search doesn't just search products — it also indexes editorial content (articles, pages) from CMS and Builder.io. A unified search request can return both products and content in a single response, making it suitable for building search experiences that blend products with related editorial content.

Ecommerce Search has two AI-powered features, both built on the Bizzkit AI Assistant (BAIA), that help when keyword matching falls short:

Semantic search Agentic search
Approach Matches products on the meaning of the phrase, using vector embeddings, so products don't have to contain every word Uses an AI agent to reason about the user's intent and pick out specific products
When it applies For the most frequent search phrases and for phrases that often return zero results. It is applied when the matching experience has a Semantic Search Boost business rule, or when the keyword search returns no results As a fallback when the keyword search returns zero results and no Did You Mean correction was applied
Effect on results Boosts semantically similar products Pins the products the agent suggests into the results
How it is enabled Configured per segment in the AI search settings. There is no request field Preview feature. The request must set agenticSearch to true, and the feature must be enabled

Both features can be enabled at the same time. Changes to the semantic search configuration use BAIA tokens, which may affect cost. See Semantic search and Agentic search.

How Keyword Search Works

Understanding the text analysis pipeline is important for troubleshooting why a search matches (or doesn't match) certain products. When product and content data is indexed, the text goes through a multi-step analysis pipeline that transforms raw text into searchable tokens. The same pipeline is applied to search queries at query time, ensuring that indexed text and query text are compared in the same normalized form.

Misspelling replacement comes first

Before a search phrase reaches the text analysis pipeline, Ecommerce Search replaces any registered misspellings in the phrase. This happens once per search request, so every part of the request — products, content, suggestions, and redirects — works on the corrected phrase. Product texts are never changed by misspellings, so this step only applies to the search phrase.

The Text Analysis Pipeline

  Raw text input (search phrases: after misspelling replacement)
       │
       ▼
  ┌──────────────────────────────┐
  │ 1. HTML Stripping            │  Remove HTML tags from content
  ├──────────────────────────────┤
  │ 2. Language Normalization    │  Normalize Unicode characters (e.g., accents, diacritics)
  ├──────────────────────────────┤
  │ 3. Tokenization              │  Split text into individual words/tokens
  ├──────────────────────────────┤
  │ 4. Lowercase                 │  Convert all tokens to lowercase
  ├──────────────────────────────┤
  │ 5. Elision                   │  Remove articles from contractions (e.g., "l'homme" → "homme")
  ├──────────────────────────────┤
  │ 6. Ignored Words             │  Remove stop words / noise words
  ├──────────────────────────────┤
  │ 7. Scandinavian Normalization│  Normalize Scandinavian characters (å, ä, ö, etc.)
  ├──────────────────────────────┤
  │ 8. Possessive 's Stemmer     │  Remove English possessive suffixes ("cat's" → "cat")
  ├──────────────────────────────┤
  │ 9. Stemming Overrides        │  Apply manual stemming overrides before the language stemmer
  ├──────────────────────────────┤
  │ 10. Language Stemmer         │  Reduce words to their root form ("running" → "run")
  ├──────────────────────────────┤
  │ 11. Multiwords               │  Handle compound words and multi-word expressions
  ├──────────────────────────────┤
  │ 12. Hypernyms                │  Expand terms to broader categories ("espresso" → "coffee")
  ├──────────────────────────────┤
  │ 13. Synonyms                 │  Expand terms to equivalent words ("car" ↔ "automobile")
  ├──────────────────────────────┤
  │ 14. Irregular Words          │  Handle irregular forms ("mice" → "mouse")
  └──────────────────────────────┘
       │
       ▼
  Searchable tokens stored in Elasticsearch

Why This Matters

  • Order matters. The pipeline processes text sequentially — each step feeds into the next. For example, stemming overrides are applied before the language stemmer, so that "training" can be kept apart from "train".
  • The Language Dictionary concepts map to specific stages. The Ignored Words, Stemming Overrides, Hypernyms, Synonyms, and Irregular Words you configure are applied at specific points in this pipeline, and Misspellings are applied to the search phrase before the pipeline starts. This is why they are modeled as separate concepts — they operate at different stages of the search.
  • Both index-time and query-time. The same pipeline is used when indexing documents and when processing search queries, ensuring that the tokens generated from a query can match the tokens stored in the index.
  • Troubleshooting searches. If a search term doesn't match as expected, use the diagnostics feature in the Admin UI — it shows the misspelling replacement and the output of each pipeline step, so you can see exactly how a term was transformed at every stage. This makes it straightforward to identify whether a term was replaced as a misspelling, removed as a stop word (step 6), stemmed to an unexpected root (step 10), or missing a synonym mapping (step 13).

Diagnostics

The diagnostics feature is one of the most useful tools available to developers working with Ecommerce Search. It is accessible from the Admin UI and provides deep visibility into how Ecommerce Search processes search phrases and matches them against products. Instead of guessing why a search returns certain results (or no results), diagnostics lets you inspect every step of the process.

Analyze: Understand How a Search Phrase Is Processed

The Analyze tool takes a search phrase, replaces misspellings, and runs it through the entire text analysis pipeline, returning the output of each step. For every step, you can see:

  • Which tokens exist after the step has been applied.
  • Whether a token was affected by the step (changed, expanded, or removed) or passed through unaffected.
  • The final set of "must match" terms — the tokens that a product document must contain to be considered a match.

For example, analyzing the phrase "Skincare product with low allegies" would show:

Step Output What Happened
Misspellings Skincare product with low allergies allegies replaced by allergies
HTML Stripping Skincare product with low allergies No change (no HTML)
Tokenization Skincare, product, with, low, allergies Split into tokens
Lowercase skincare, product, with, low, allergies Skincare lowercased
Ignored Words skincare, product, low, allergies with removed (stop word)
Language Stemmer skincar, product, low, allergi Stemmed to root forms
Synonyms skincar, product, low, allergi No synonyms configured
(final) → Must match: skincar AND product AND low AND allergi These are the tokens used for matching

This makes it immediately clear why a product might not be found — perhaps the misspelling wasn't in the dictionary, a term was unexpectedly removed as a stop word, or stemming produced an unexpected root form.

Match: Understand Why a Product Does or Doesn't Match

The Match tool goes a step further — given a search phrase and a specific product or SKU identifier, it shows:

  • Field-level matching — For each searchable field on the product (name, description, category, etc.), it highlights which parts of the field value matched the search tokens and which didn't. This lets you see exactly where in the product data a match was found (or why it was missed).
  • Term-level matching — For each token that the search query was analyzed into, it shows whether that token was found in the product. If any required token is missing, that explains why the product doesn't appear in results.
  • Filter exclusion — If filters were applied, it shows whether the product was excluded by a filter rather than by text matching. This distinguishes between "the product doesn't match the search phrase" and "the product matches but was filtered out."

When to Use Diagnostics

Scenario Which Tool What to Look For
A search phrase returns no results Analyze Check if important tokens are being removed as stop words or stemmed unexpectedly
A specific product doesn't appear in results Match Check which terms matched and which didn't — is a field missing data?
A product appears when it shouldn't Match Check which fields are producing unexpected matches
A synonym or misspelling correction isn't working Analyze Check the specific pipeline step to see if the dictionary entry was applied
Results changed after a language dictionary update Analyze Compare the pipeline output before and after to see how tokens changed
A product shows in search but not when filters applied Match Check if the filter exclusion flag indicates filter-based removal

Playground

The Playground is an interactive tool in the Admin UI that lets both developers and daily users see exactly which business rules are in effect for a given search context and how they shape the search results. Where diagnostics focuses on text analysis and token matching, the Playground focuses on business rule resolution and result ranking.

What the Playground Shows

When you open the Playground, you define a set of conditions — the same conditions that a real search request would carry (scope, category, search phrase, targets, etc.). The Playground then:

  1. Resolves business rules — For each business rule type (Facets, Parameter, Pinned Products, Relevance Boost, Affinities, Semantic Search Boost, Bury), it shows which specific rule was selected as the best fit and whether the match is exact or a fallback. This makes the inheritance model fully transparent.
  2. Previews search results — Executes a search with the resolved business rules applied, showing the actual product results in a grid view.
  3. Explains scoring — For each product in the results, it breaks down the commercial sort score: which parameters contributed, what the normalized values were, and how the partition weights affected the final ranking.
  4. Shows affinity influence — If personalization (affinities) is active, it shows how user affinity data affected the result ordering.

Why the Playground Matters

The Playground bridges the gap between configuration and outcome. Without it, understanding why a particular search returns certain results in a specific order requires mental simulation of the best-fitting algorithm across multiple business rule types. With the Playground, you can:

  • Verify business rule inheritance — Confirm that a more specific rule (e.g., for a particular category + scope) correctly overrides the default fallback rule.
  • Test before publishing — The Playground works with draft configuration, so you can preview how upcoming changes will affect search results before publishing them live.
  • Debug unexpected ranking — If products appear in an unexpected order, the score explanation reveals exactly which parameters and weights produced that ranking.
  • Collaborate with non-developers — Product managers and merchandisers can use the Playground to validate that their business rule changes produce the intended results, without needing developer assistance.

Architecture Overview

Deployable Hosts

Ecommerce Search is composed of five deployable services split across two subsystems:

Host Subsystem Purpose
Admin API Ecommerce Search Core Configuration, ingestion endpoints, business rules, publication management
Search Host Ecommerce Search Core Read-only search queries, facets, suggestions, SKU export (optimized for high query throughput)
Job Runner Ecommerce Search Core Background jobs: index rebuilds, cleanup, suggestion generation
Courier API Courier Data ingestion hub — coordinates data intake from PIM, CMS, Builder.io, GA4, BAIA
Courier Runner Courier Background scheduled ingestion tasks (daily syncs)
Hold "Ctrl" to enable pan & zoom
graph LR
    subgraph ECSCore["Ecommerce Search Core"]
        AdminAPI["Admin API (config, ingest, business rules, publish)"]
        SearchHost["Search Host (search, facets, suggestions, SKU export)"]
        JobRunner["Job Runner (index rebuild, cleanup, suggestion gen)"]
    end

    subgraph Courier["Courier"]
        CourierAPI["Courier API (webhook receiver, on-demand ingest)"]
        CourierRunner["Courier Runner (scheduled daily sync jobs)"]
    end

Technology Stack

Technology Role
Elasticsearch Primary search index (products, content, suggestions, spelling dictionaries)
SQL Server Relational store for ingested data, configurations, business rules (EF Core)
Redis Multi-layer cache for published configurations and frequently accessed data
Azure Service Bus Asynchronous messaging for event-driven processing

Which API Do I Need?

I want to... Use this API Authentication
Search for products/content on a storefront Search Host Anonymous or JWT
Export SKUs for data processing Search Host Anonymous or JWT
Configure segments, business rules, synonyms Admin API OAuth2 (token)
Push product/content data into Ecommerce Search Admin API OAuth2 (token)
Coordinate ingestion from PIM/CMS/Builder.io/GA4 Courier API OAuth2 (token)

Available SDKs

Ecommerce Search provides generated SDK clients so you don't need to call the REST APIs directly.

C# SDKs

NuGet Package Interface / Factory Purpose
Bizzkit.Sdk.Search ISearchClient / SearchClientFactory Search queries (unauthenticated)
Bizzkit.Sdk.Search.Preview ISearchClient / SearchClientFactory Preview API features
Bizzkit.Sdk.EcommerceSearch ISearchAdministrationClient / SearchAdministrationClientFactory Admin operations (OAuth2)
Bizzkit.Sdk.EcommerceSearch.Courier ICourierClient / CourierClientFactory Courier ingestion (OAuth2)

npm Package

The @bizzkit/ecommerce-search npm package (from ecommercesearch/frontend-search-client/) provides a standalone TypeScript client for building storefront search UIs. It exports:

  • Client — Search Host client
  • PreviewClient — Preview Search Host client
  • Admin / PreviewAdmin — Admin API types

Authentication

  • Search Host — Can be called without authentication (anonymous) for public storefronts. Optionally, a JWT authenticationToken signed with a SearchSigningKey can be passed in the request body to unlock restricted features (e.g., authenticated filters, debug explanations).
  • Admin API & Courier API — Require OAuth2 bearer tokens. The C# SDKs handle token management automatically via the factory pattern (SearchAdministrationClientFactory, CourierClientFactory).

The Unified Search Request

The unified search is the central concept of the Search Host. Rather than making separate calls for products, content, suggestions, and facets, the unified search endpoint (POST /search) returns all result types in a single response. This is the endpoint your storefront should call for virtually every search-related page.

Why "Unified"?

In a typical search UI, a single user action (typing a query, clicking a category) requires multiple types of data:

  • Products with their matching SKUs
  • Content (editorial articles, pages)
  • Suggestions (typeahead completions)
  • Did You Mean corrections (if the phrase didn't match well)
  • Facets (filter options with counts)
  • Quick search spotlights (shown when the search box is empty)

The unified search request fetches all of these in one round trip. What gets returned is controlled by the scope — each scope defines how many products, content items, suggestions, and did-you-mean alternatives to return. This means the same endpoint serves both a full search results page and a quick search dropdown — the scope configuration determines the response shape.

Request Flow

When the Search Host receives a unified search request, it goes through these steps:

  1. Scope resolution — The published scope configuration is loaded based on segmentId + scopeId. This determines default result counts, domain filters, fields to return, and scope type.
  2. Authentication — If an authenticationToken is present, it's validated and its claims are extracted as authenticated filters.
  3. Misspelling replacement — Registered misspellings in the phrase are replaced, unless forceSearch is set. The rest of the request uses the corrected phrase.
  4. Business rule matching — The request context (scope, category, phrase, targets) is evaluated against all configured business rules to find the best-fitting rule for each type (facets, relevance boost, parameter, etc.).
  5. Redirect check — For FullSearch and QuickSearch scopes, Ecommerce Search checks whether the phrase should redirect. A full search with a redirect returns the action without running the search.
  6. Parallel sub-searches — Ecommerce Search executes multiple searches in parallel against Elasticsearch:
  7. Product search (with commercial sort scoring, filters, facets)
  8. Content search (with relevance boosting)
  9. Suggestion search, or Quick Search Spotlight when the phrase is empty
  10. Did You Mean search
  11. AI related tag search
  12. Fallback — If nothing was found, Ecommerce Search searches again with the Did You Mean phrase. If no Did You Mean correction applies and the request has agenticSearch set, agentic search is used instead.
  13. Response assembly — All results are combined into a single unified response, including the next conversational filtering question if the scope has conversational filtering enabled.

Response Structure

The unified search response contains:

Response Field Description
products Matched products, each with their nested SKUs and field values
totalProducts Total product count matching the query (approximate above 3,000)
totalSkus Total SKU count (if enabled on scope via countTotalSkus)
facets Filter options with counts, ordered as configured in the matching Facets business rule
suggestions Typeahead suggestions matching the phrase
didYouMean Spelling correction alternatives
aiRelatedTags AI-generated related search phrases
content Matched editorial content items from CMS, Builder.io, or other ingested sources
totalContent Total content count matching the query
productOffset, contentOffset The offsets used for products and content, for building pagination
quickSearchSpotlights Quick search spotlight phrases (only when phrase is empty and scope has this enabled; deprecated alias popularSearches)
conversationalFiltering The next conversational filtering question and its answers, or null (only when the scope has this enabled)
originalPhrase The phrase as submitted by the caller
usedPhrase The phrase actually used for search. It differs from originalPhrase when a misspelling was replaced, Did You Mean was applied as a fallback, the first suggestion was used in quick search, or agentic search was used
explanation The business rules that matched the request, with a link to the Playground (only with authenticated search + explain enabled)
action Redirect action (e.g., redirect to a specific category page instead of showing results)

How Scope Controls the Response

The scope determines what gets returned. If a scope has numberOfSuggestions: 0, no suggestions are fetched or returned — the sub-search is skipped entirely. This is why different scopes exist for different pages:

Page Scope Type Products Content Suggestions Did You Mean
Search results FullSearch 12 5 5 3
Category browse Browse 24 0 0 0
Quick search QuickSearch 5 3 5 0
Product detail Details 1 0 0 0

Numbers are examples — they are configurable per scope. Facets are not a scope setting: which facets are returned is decided by the matching Facets business rule.

Making a Search Request

The primary search endpoint is:

POST /search

Minimal Request

Only segmentId and scopeId are required:

1
2
3
4
5
{
  "segmentId": "b2c-dk-en",
  "scopeId": "full-search",
  "phrase": "pants"
}

Full Request Example

{
  "segmentId": "b2c-dk-en",
  "scopeId": "full-search",
  "phrase": "pants",
  "numberOfProducts": 12,
  "numberOfContent": 5,
  "offsetProducts": 0,
  "sort": [
    { "key": "price", "order": "desc" }
  ],
  "filters": {
    "COLOR": { "values": ["Black"] },
    "PRICE": { "from": 100, "to": 500 }
  },
  "userId": "external-user-1",
  "targets": {
    "weather": ["sunny"]
  }
}
Field Required Description
segmentId Yes Which segment to search in (e.g., "b2c-dk-en")
scopeId Yes Which scope configuration to use (e.g., "full-search", "browse")
phrase No The search query text (max 255 chars). Omit for browse/category pages
numberOfProducts No How many products to return (max 1000, default set on scope)
numberOfContent No How many content items to return (max 1000)
offsetProducts No Number of products to skip (for pagination). offsetProducts + numberOfProducts must stay below 10,000
offsetContent No Number of content items to skip (for pagination)
sort No Sorting criteria — first element wins (default: relevance desc)
filters No Key-value filter criteria (string or range filters)
facets No Limits the number of string facet values returned, per field
userId No User ID for personalized boosting (affinity-based)
sessionId No The user's session ID. Some features, such as tracking, don't work fully without it
pinnedIds No Product/SKU IDs to pin at the top of results (max 200). A pinned product must still match the request
targets No Context values for business rule matching
authenticationToken No Signed JWT for authenticated search
forceSearch No Search for the phrase exactly as given: skips misspelling replacement, the first-suggestion substitution in quick search, and the Did You Mean and agentic search fallbacks
agenticSearch No Allows agentic search as a fallback when nothing is found (preview feature, requires enablement, and forceSearch must be false)

The preview version of the Search API also accepts audienceIds for audience affinities.

Exporting SKUs

For bulk data export (e.g., feed generation), use the SKU export endpoint:

POST /sku-export

This endpoint supports cursor-based pagination using an opaque nextPageToken. Request the first page without a token, then send the nextPageToken from the response in the next request to fetch the next page. Continue until no more pages are returned.

Don't use the export, or the search endpoints, to work out which data in Ecommerce Search is outdated. Keep track of what you have ingested in your own integration instead. See Common pitfalls.


Courier Ingestion Flow

Understanding how data gets into Ecommerce Search via the courier is important for integration planning:

Hold "Ctrl" to enable pan & zoom
graph TD
    PIM -- "Webhook (real-time)" --> Courier
    CMS -- "Webhook / Daily" --> Courier
    Builder["Builder.io"] -- "Webhook / Daily" --> Courier
    GA4 -- "Daily sync" --> Courier
    BAIA -- "Daily sync" --> Courier

    subgraph Courier["Courier"]
        CourierAPI["Courier API (on-demand / webhook triggers)"]
        CourierRunner["Courier Runner (scheduled daily sync jobs)"]
    end

    Courier -- "SDK calls (Ingest API)" --> AdminAPI["Ecommerce Search Core (Admin API)"]

How It Works

  1. Courier connects to data sources — PIM (product catalog), CMS (content pages), Builder.io (content pages), GA4 (analytics), BAIA (AI/image data).
  2. Data is transformed — The Courier maps external data models into the Ecommerce Search ingestion format.
  3. Ingested via Admin API — The Courier uses the Ecommerce Search SDK (ISearchAdministrationClientFactory) to push data into Ecommerce Search Core.
  4. Event chain triggers indexing — When product data is ingested, it triggers a chain of internal update events
  5. Elasticsearch index is updated — The Job Runner processes the rebuild messages and updates the Elasticsearch index.
  6. Search Host serves fresh data — Once indexed, the data is immediately available via the Search Host.

Why This Matters for Integrators

  • Data is eventually consistent. After a product is updated in PIM, there is a short delay (seconds to minutes) before it appears in search results, because the data must flow through the Courier → Ingest → Index pipeline.
  • You typically don't need to call the Ingest API directly. The Courier handles standard PIM/CMS data ingestion automatically. Direct Ingest API usage is only needed for custom data sources not covered by the Courier.

Performance Considerations

When integrating with Ecommerce Search, keep these principles in mind to ensure a fast and reliable search experience.

Search Host Is Read-Optimized

The Search Host is designed for high query throughput — it's the endpoint your storefront will call on every search, every category page load, and every keystroke during quick search. It has higher concurrency limits than the Admin or Courier APIs.

The Admin API has lower concurrency limits because it handles configuration and ingestion — heavier, less frequent operations.

Use Cursor-Based Pagination for Exports

The unified search is built for pages that users browse, not for retrieving large result sets. Offset-based pagination with offsetProducts gets more expensive the deeper you page, because Elasticsearch must find and skip all preceding results. For this reason, the Search Host rejects requests where offsetProducts + numberOfProducts reaches 10,000.

To retrieve more products than that, such as for feed generation, use the SKU export endpoint and its cursor-based nextPageToken. A cursor stays fast no matter how many pages you fetch.

Approach Use for Limit
Offset (offsetProducts) Search and category pages Below 10,000 products in total
Cursor (nextPageToken) Exports and bulk retrieval None

Use Bulk Operations for Ingestion

If you're pushing data into Ecommerce Search via the Admin API, use the bulk endpoints rather than making individual calls per product or SKU. Sending 10,000 individual API calls is orders of magnitude slower (and more likely to hit rate limits) than sending batches.

Configure Scopes to Fetch Only What You Need

Scopes control which fields are returned in search results. Setting up a scope to return only the fields your UI actually needs has a direct impact on performance — less data means faster serialization, smaller payloads, and reduced Elasticsearch _source filtering overhead.

Additionally, fetching SKU data requires additional lookups beyond the base product query. If your scope doesn't need SKU-level details (e.g., a quick search dropdown that only shows product names), configure the scope to not include underlying SKUs. This avoids the extra work of resolving and returning SKU data for every product in the result set.

Scope Purpose Fields Needed Include SKUs? Why
Quick search Product name, image No Only showing quick suggestions — SKUs are unnecessary overhead
Search results page Name, price, image, color Yes (limited) Need representative SKU data for display
Category browse Name, price, image Yes (limited) Similar to search results
Product detail page All fields Yes (all) Full product information required

Takeaway: Don't use a single "fetch everything" scope for all use cases. Create purpose-built scopes that match the data requirements of each page or component.

Only Ingest What Has Changed

A common bad practice is re-sending the entire product catalog on every sync, regardless of whether anything has actually changed. This wastes bandwidth and puts unnecessary load on the Ingest API.

For products and SKUs, Ecommerce Search has its own built-in change tracking — when they are ingested, Ecommerce Search compares the incoming data against what's already stored and will not forward unchanged data to Elasticsearch for reindexing. When something has changed, Ecommerce Search uses partial updates and only updates the changed parts of the documents in Elasticsearch. However, this doesn't eliminate the cost of the ingestion call itself: the data still needs to be serialized, sent over the network, received, deserialized, and compared. At scale, this adds up. Other data types, such as content and user affinities, are not filtered this way.

Integrating solutions should therefore track their own changes and only push data that has actually been modified since the last successful ingestion. This applies to all data types: products, SKUs, content, user affinities, and item affinities. Don't query the search or export endpoints to find out what has changed; keep that record in your own integration. See Common pitfalls.

Approach Bandwidth Ingest API Load Elasticsearch Indexing
Full catalog on every sync High High Only actual product and SKU changes; other data types in full
Only changed items Minimal Minimal Only actual changes

How to implement this:

  • Use webhooks where available. PIM already provides real-time webhooks that fire only when a product changes — the Courier uses these by default. If you're building a custom integration, prefer webhooks or change feeds over full exports.
  • Maintain a change timestamp. Before each sync, record the current timestamp. On the next sync, only query for items modified after that timestamp.
  • Compare before sending. If your data source doesn't support change tracking, compute a hash or version of each item and only send items whose hash differs from the last ingestion.
  • Patch only the properties you own. The create-or-patch endpoints for products and SKUs only update the properties that are set in the request, and leave properties that are null unchanged. A secondary source, such as an ERP that provides commercial parameters, can therefore patch its own properties onto existing products without sending the full product. See Product ingestion.