Skip to main content

Setting Up Catalog Search

Catalog Search provides fast, relevant product search capabilities for your storefront. This guide walks you through enabling and configuring search for your catalogs using the API.

tip

You can also configure Catalog Search using Commerce Manager. See Catalog Search in Commerce Manager for step-by-step instructions.

Overview

The Catalog Search service provides:

  • Full-text search across product names, descriptions, SKUs, and custom fields
  • Faceted navigation for filtering by categories, attributes, and price ranges
  • Relevance ranking with customizable search profiles
  • Multi-language support with locale-aware search
  • Price filtering with automatic currency and price book support
  • Configurable text processing with stemming, token separators, and symbols (special characters) to index
  • Typo tolerance that forgives spelling mistakes and supports search-as-you-type
  • Synonyms so different words for the same product find each other
  • Stopwords that ignore low-value words like the and a at query time

Prerequisites

Before setting up catalog search, ensure you have:

  • Catalog Search enabled for your store or organization (contact Customer Success to enable this feature)
  • Search enabled for the catalogs you want to be searchable (see Enabling Catalog Search)
  • A published catalog with products, hierarchies, and price books configured
  • API credentials with appropriate permissions

What Happens When Search is Enabled

When you enable search for a catalog:

  1. Automatic indexing: All future catalog releases are automatically indexed when published
  2. Extended publishing: The publish process includes an indexing step that makes products searchable
  3. Search availability: Once indexed, products are searchable via the Search API
note

Existing releases are not automatically indexed. You must publish a new release after enabling search for products to become searchable.

Understanding the Indexing Process

When you publish a catalog release, the following occurs:

  1. The catalog release is processed and stored (shows as 99% complete)
  2. An indexing job is created to make products searchable
  3. Products are transformed and indexed with their:
    • Names and descriptions (per locale)
    • SKUs and other identifiers
    • Category/hierarchy associations
    • Prices from all configured price books
    • Custom indexable fields
  4. The release is marked as PUBLISHED when indexing completes

Configuring Indexable Fields

By default, catalog search indexes standard product fields with default settings. Indexable fields let you extend and fine-tune the search schema:

  • Add custom fields to the index from product extension templates or custom (shopper and admin) attributes
  • Control text processing for the whole index with stem, token_separators, and symbols_to_index
  • Enable sorting and faceting on built-in fields like name, sku, created_at, and updated_at

List Indexed Fields

Use Indexed Fields to discover every field currently in the search index for your tenant — text, numeric, boolean, and date — and which uses each field supports:

curl https://useast.api.elasticpath.com/v2/pcm/catalogs/search/indexed-fields \
-H "Authorization: Bearer $ACCESS_TOKEN"

Example response (abbreviated):

{
"data": [
{
"id": "name",
"type": "catalog_search_indexed_field",
"attributes": {
"name": "name",
"type": "string",
"searchable": true,
"filterable": true
},
"meta": { "owner": "store" }
},
{
"id": "created_at",
"type": "catalog_search_indexed_field",
"attributes": {
"name": "created_at",
"type": "date",
"searchable": false,
"filterable": true
},
"meta": { "owner": "store" }
},
{
"id": "base_product",
"type": "catalog_search_indexed_field",
"attributes": {
"name": "base_product",
"type": "bool",
"searchable": false,
"filterable": true
},
"meta": { "owner": "store" }
}
]
}
AttributeMeaning
typeField data type: string, int32, int64, float, bool, or date.
searchableWhen true, the field can be used as a full-text query field on a search profile (fields / query_by). Only text (string) fields are searchable.
filterableWhen true, the field can be used in filter expressions (filter_by), profile filters, boost conditions, and related filter syntax.
facetableOptional. When true, the field can be used for faceting. Defaults to false.
sortableOptional. When true, the field can be used for sorting. Defaults to true for numeric fields, otherwise false.
localeThe language a text field is indexed with, as an ISO 639-1 code (for example en, ja). Defaults to en, which also broadly supports most European languages.

Use this endpoint when building search profiles, filters, facets, sorts, or search rules. After you add or change indexable fields, reindex, then list indexed fields again to confirm the schema.

Deprecated: Searchable Fields

GET /pcm/catalogs/searchable-fields is deprecated. It returns only text fields usable as query fields (the searchable: true subset of Indexed Fields) and does not include numeric, boolean, or date fields needed for filtering and sorting. Prefer GET /pcm/catalogs/search/indexed-fields.

Add Custom Indexable Fields

To make custom product attributes searchable, create indexable fields:

curl -X POST https://useast.api.elasticpath.com/v2/pcm/catalogs/indexable-fields \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"data": {
"type": "catalog_search_indexable_fields",
"attributes": {
"fields": [
{
"name": "shopper_attributes.color",
"facetable": true,
"sortable": false
},
{
"name": "extensions.products(clothing).brand",
"facetable": true,
"sortable": true
},
{
"name": "extensions.products(specifications).rating",
"facetable": true,
"sortable": true
}
]
}
}
}'

Field options:

OptionDescription
nameThe field path in your product extensions (must match pattern extensions.products(<template>).<field>) or admin/shopper attributes (must match pattern admin_attributes.<field> or shopper_attributes.<field>)
facetableEnable faceting (aggregated counts) on this field. Default: false
sortableEnable sorting by this field. Default: true for numeric fields, false otherwise
localeLanguage used to tokenize this field, as an ISO 639-1 code. Default: en. Omitting locale is identical to setting en. Values that are not ISO 639-1 — such as en-US — are rejected with a 400

Override Core Product Fields

Core product fields such as name, description, and sku are always indexed. Use core_field_overrides to enable sorting or faceting on them — for example, to make name and sku sortable, or created_at facetable:

curl -X POST https://useast.api.elasticpath.com/v2/pcm/catalogs/indexable-fields \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"data": {
"type": "catalog_search_indexable_fields",
"attributes": {
"core_field_overrides": [
{
"name": "name",
"sortable": true
},
{
"name": "sku",
"sortable": true
},
{
"name": "created_at",
"facetable": true
}
]
}
}
}'

Not every setting is available on every core field:

SettingSupported core fields
sortablename, sku, created_at, updated_at
facetabletags, created_at, updated_at, node fields

Text Processing

Stemming, token separators, and symbols to index control how text is broken into tokens and matched. All three are set once at the top level of the indexable fields attributes, where they apply to every text field in the index:

{
"data": {
"type": "catalog_search_indexable_fields",
"attributes": {
"stem": true,
"token_separators": ["-"],
"symbols_to_index": ["+"]
}
}
}

Configuring them for the whole index is what keeps matching consistent. A search query is tokenized once per request, and those tokens are then matched against every field being searched — so text processing that is uniform across the index is text processing you can reason about.

Stemming

Stemming reduces words to their root form at both index and query time, so a search for running also matches products containing run, runs, or runner. This improves recall wherever shoppers use different word forms from those in your product data.

For example, a search for walked matches a product named Walk and Talk Tours — both walked and Walk reduce to the stem walk. Without stemming, an inflected query like walked does not match a product that contains only the base form walk.

Stemming is on by default for every text field in the index, custom and built-in alike. Set stem: false to turn it off if your catalog needs exact word matching:

{
"data": {
"type": "catalog_search_indexable_fields",
"attributes": {
"stem": false
}
}
}

Notes:

  • Stemming uses the Snowball stemmer, which supports many languages. A text field is stemmed for the language given by its locale
  • It applies to text fields only — numeric, boolean, and date fields are never stemmed

Token Separators

token_separators specifies additional characters that split text into separate tokens. This is useful for hyphenated text, part numbers, or other compound formats.

For example, take a product containing the text water-proof. By default, it is tokenized as waterproof, so a search for water proof does not match. With token_separators: ["-"], the text is tokenized as water and proof, so searches for both water-proof and water proof match.

Symbols (Special characters) to Index

symbols_to_index specifies special characters that should be preserved within tokens rather than stripped. This is useful when products contain meaningful symbols.

For example, with default settings the + in S24+ is stripped, so S24+ is indexed as S24 and loses precision. With symbols_to_index: ["+"], S24+ is preserved as a distinct token and matches precisely. Only index special characters if they add value and are actually a differentiating factor, for example S24+ versus S24.

Each element in token_separators and symbols_to_index must be a single character.

caution

After adding or modifying indexable fields, you must reindex your catalog releases for the changes to take effect. See Reindexing.

Setting Up Search Profiles

Search profiles control how search queries are executed. They define which fields to search, their relative importance, and business rules for filtering and boosting results.

Create a Search Profile

curl -X POST https://useast.api.elasticpath.com/v2/pcm/catalogs/search-profiles \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"data": {
"type": "catalog_search_profile",
"attributes": {
"slug": "default-search",
"description": "Default search profile for storefront",
"fields": [
{ "name": "name", "weight": 10 },
{ "name": "description", "weight": 5 },
{ "name": "sku", "weight": 8 },
{ "name": "meta.search.nodes.name", "weight": 3 }
],
"text_match_type": "max_score"
}
}
}'

Understanding Field Weights

Field weights control the relative importance of each field when ranking search results:

  • Higher weights mean matches in that field contribute more to relevance
  • A product with "laptop" in the name (weight 10) ranks higher than one with "laptop" only in description (weight 5)
  • Weights are relative: what matters is the proportion between them, not their absolute size, so 6:4:2 behaves the same as 3:2:1
  • Each weight is a whole number between 0 and 15.

Weights do more than order results. The highest-weighted field also decides how the shopper's search text is interpreted — how it is split into words, whether it is stemmed, and which language's synonyms apply. Changing which field carries the top weight can therefore change which synonyms expand a search. See Localization Support in Using Synonyms.

Text Match Types

The text_match_type determines how scores from multiple fields are combined:

TypeDescriptionBest For
max_score (default)Uses highest score from any matching fieldGeneral product search
max_weightUses score from highest-weighted matching fieldWhen field importance matters more than match quality
sum_scoreSums weighted scores from all matching fieldsRewarding multi-field matches

Typo Tolerance and Partial Word Matching

Search profiles also control how forgiving search is towards imperfect queries — how many spelling mistakes are corrected (typo_tolerance), whether a partially typed last word matches, how compound words like waterproof and water proof match each other, and more. These settings can be tuned per profile and per field, for example to keep SKU matching exact while product names stay forgiving.

See Handling Typos for all available settings with working examples.

Attaching Synonyms

A search profile can reference one or more synonym sets. Synonyms let different words for the same product — couch and sofa, or sneakers and trainers — find each other.

{
"synonym_sets": ["3fa85f64-5717-4562-b3fc-2c963f66afa6"]
}

See Using Synonyms for how to create synonym sets, attach them to profiles, and tune their behavior. To ignore low-value words like the and a, see Using Stopwords.

Adding Filters

Profile filters are automatically applied to all searches using that profile:

{
"filters": [
"status:=live && visibility:=public"
]
}

Multiple filters are combined with OR logic, then ANDed with user filters:

Final Filter = (Profile Filter 1 || Profile Filter 2) && User Filter

Adding Boost Rules

Boost rules on a search profile promote or demote products on every search that uses the profile:

{
"boosts": [
{
"condition": "extensions.products(Details).is_featured:=true",
"weight": 100
},
{
"condition": "extensions.products(Details).on_sale:=true",
"weight": 50
},
{
"condition": "extensions.products(Details).stock_status:=out_of_stock",
"weight": -100
}
]
}
  • Positive weights: Push products to the top
  • Negative weights: Push products to the bottom (bury)

Attaching Search Rule Groups

For query-triggered merchandising — boost, bury, pin, hide, rewrite, or filter only when a shopper query or browse listing matches — create rule groups and attach them with rule_groups:

{
"rule_groups": ["550e8400-e29b-41d4-a716-446655440000"]
}

A non-empty rule_groups array activates the query-time rules engine for that profile. See Using Search Rules for triggers, actions, ordering, and full API examples.

Set a Default Search Profile

Make a profile the default for all searches:

curl -X POST https://useast.api.elasticpath.com/v2/pcm/catalogs/search-profiles/{profile_id}/default \
-H "Authorization: Bearer $ACCESS_TOKEN"

How a search profile is chosen

When a shopper searches your store, Catalog Search resolves one search profile for the request. That profile controls field weights, default filters, sorting, typo tolerance, synonym sets, and related search behavior.

Resolution depends on which search endpoint you call.

For shopper endpoints — POST /pcm/catalog/search and POST /pcm/catalog/multi-search — profiles are chosen in this order:

PrioritySourceBehavior
1Catalog rule search_profile_slugIf the matched catalog rule carries a non-blank slug and that slug resolves to a profile in your tenant, that profile is used. Any search_profile query parameter on the request is ignored.
2search_profile query parameterUsed when the catalog rule has no slug, a blank/whitespace-only slug, or a slug that no longer resolves. A blank or whitespace-only value is treated as omitted. An invalid non-blank slug returns 400 with detail Search profile '{slug}' not found.
3Tenant default profileThe profile marked as default for your store or organization.
4Built-in defaultA system profile used when no named profile applies. The response header EP-Search-Profile is set to the reserved sentinel SYSTEMS_DEFAULT_PROFILE.

Catalog Search reads search_profile_slug from the same shopper-context resolution that selects catalog, release, and price books. You do not pass the rule slug on the search request itself.

note

Invalid or stale rule slugs do not fail the search. If a catalog rule references a profile that was deleted or is out of scope, Catalog Search logs a structured warning and falls through to the query parameter, tenant default, and built-in default — in that order. Catalog rule saves are never blocked because a profile is missing or invalid.

For admin endpoints — POST /pcm/catalogs/{catalog_id}/releases/{release_id}/search and …/multi-search — catalog rule profiles are not applied. You are already targeting an explicit catalog release.

Resolution order:

  1. search_profile query parameter (same blank/invalid rules as shopper search)
  2. Tenant default profile
  3. Built-in default (SYSTEMS_DEFAULT_PROFILE in EP-Search-Profile)

Use admin search to preview a specific release with a chosen profile. Use shopper search to validate segment behavior end to end.

EP-Search-Profile response header

Successful and some error responses include EP-Search-Profile so you can see which profile was applied or attempted:

ResponseHeader value
2xxSlug of the profile actually used. Built-in default → SYSTEMS_DEFAULT_PROFILE.
400 (profile resolution ran)Slug that was attempted — for example an invalid search_profile query value, or the resolved slug when a later validation step failed.
Other errorsHeader omitted when the request fails before profile resolution (for example a malformed search body).

SYSTEMS_DEFAULT_PROFILE is reserved. You cannot create a tenant profile with that slug.

Storefront guidance

  • Preferred pattern for segments: attach search_profile_slug on the catalog rule that already targets the segment (account, customer, channel, or context tag). The storefront sends shopper context headers as today; search picks up the profile automatically after login or context change.
  • Query parameter: use for A/B tests, explicit overrides when no rule slug applies, or tooling — not as the primary way to route B2B or reseller segments.
  • Observability: read EP-Search-Profile on search responses to confirm which profile ran in production or staging.

Segment audiences via catalog rules

Catalog rules already route which catalog and which prices apply to a shopper. You can also attach an optional search_profile_slug on the same rule so search behavior follows the same segmentation — field weights, filters, boosts, and related settings — without hard-coding profile slugs in your storefront.

What you can segment

Catalog rule attributeControls
catalog_idWhich catalog release the shopper searches
pricebook_idsWhich price books apply (price segmentation)
search_profile_slugWhich products appear in search and how they rank

All three are optional on a rule except catalog_id. A common B2B pattern is one rule per reseller account: same catalog, reseller price books, and a search profile whose default filter limits assortment (for example to an approved category or brand list).

Example: reseller assortment

  1. Create a search profile (for example slug reseller-clothing) with a default filter such as meta.search.nodes.name:=Clothing to limit searchable products to a hierarchy branch.
  2. Create or update a catalog rule for the reseller account and set attributes.search_profile_slug to reseller-clothing, alongside any pricebook_ids for that tier.
  3. When the reseller logs in, shopper search uses that profile automatically. Unauthenticated or other shoppers without a matching rule keep the default profile and see the full assortment.

Verify by comparing search result counts and checking EP-Search-Profile on the response.

Hierarchy navigation caveat

Filtering search to one hierarchy node does not hide other nodes in category navigation when products are cross-listed under multiple nodes. Those other nodes may still appear, but they only show products that also match the search profile filter. Total searchable products and facet counts reflect the filtered assortment.

Configure in Commerce Manager

When editing a catalog rule in Commerce Manager, use the search profile picker to attach a slug. The picker is scope-aware:

  • Organization rules — organization-owned profiles
  • Store rules — store-owned and organization-owned profiles

Profile validity is checked at search time, not when the rule is saved. That keeps catalog rule maintenance (including automatic release_id updates on publish) independent of search profile lifecycle.

For a full walkthrough that combines price segmentation with assortment filtering, see Price Segmentation.

Using the Search API

Perform a shopper search:

curl "https://useast.api.elasticpath.com/v2/pcm/catalog/search?q=laptop" \
-H "Authorization: Bearer $ACCESS_TOKEN"

Search with Filters

Filter results by category, price, or custom attributes:

curl "https://useast.api.elasticpath.com/v2/pcm/catalog/search?q=laptop&filter_by=meta.search.nodes.name:=Electronics%20%26%26%20price.float_price:[500..2000]" \
-H "Authorization: Bearer $ACCESS_TOKEN"

Search with Facets

Get aggregated counts for filtering UI:

curl "https://useast.api.elasticpath.com/v2/pcm/catalog/search?q=laptop&facet_by=meta.search.nodes.name,extensions.products(Details).brand" \
-H "Authorization: Bearer $ACCESS_TOKEN"

Execute multiple searches in a single request:

curl -X POST https://useast.api.elasticpath.com/v2/pcm/catalog/multi-search \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"searches": [
{
"q": "laptop",
"filter_by": "meta.search.nodes.name:=Electronics",
"per_page": 10
},
{
"q": "laptop",
"filter_by": "meta.search.nodes.name:=Accessories",
"per_page": 5
}
]
}'

Using a Specific Search Profile

Pass search_profile to select a profile when no valid catalog rule search_profile_slug applies (for example A/B tests or tooling). On shopper search, a valid rule slug takes precedence and this query parameter is ignored — see How a search profile is chosen.

curl "https://useast.api.elasticpath.com/v2/pcm/catalog/search?q=laptop&search_profile=b2b-wholesale" \
-H "Authorization: Bearer $ACCESS_TOKEN"

Check the EP-Search-Profile response header to confirm which profile was applied.

Shopper segments via catalog rules

When different accounts, customers, or channels need different search behavior (assortment filters, ranking, or boosts), attach a search profile on the catalog rule for that segment — the same rule that already selects catalog and price books.

Do this

  1. Create or configure the search profile (filters, field weights, boosts as needed).
  2. Set search_profile_slug on the matching catalog rule (Commerce Manager picker or Catalog Rules API).
  3. Keep the storefront on shopper search with normal context headers — do not hard-code per-segment search_profile query parameters as the primary routing mechanism.

Verify

  1. Search as two shoppers (segmented vs default).
  2. Confirm different result counts and/or ranking when assortment or weights differ.
  3. Confirm response header EP-Search-Profile matches the expected profile slug (or SYSTEMS_DEFAULT_PROFILE for the built-in default).

Learn more

Filter, Facet, and Sort Reference

For comprehensive documentation on filtering, faceting, and sorting search results, see:

Reindexing Catalog Releases

If you modify indexable fields or need to rebuild indexes, you can trigger reindexing:

Reindex All Releases

curl -X POST https://useast.api.elasticpath.com/v2/pcm/catalogs/reindex-releases \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"data": {
"force_reindex": true
}
}'

Check Index Status

View which indexes are out of sync:

curl "https://useast.api.elasticpath.com/v2/pcm/catalogs/search-indexes?out_of_sync=true" \
-H "Authorization: Bearer $ACCESS_TOKEN"

Best Practices

Search Profile Design

  1. Start with core fields: Always include name, description, and sku
  2. Add category fields: Include meta.search.nodes.name for category-based discovery
  3. Limit field count: Focus on 3-5 key fields to maintain relevance
  4. Test incrementally: Start with small weight differences and adjust based on results

Indexable Fields

  1. Index selectively: Only index fields that users will search or filter by
  2. Enable faceting wisely: Facetable fields increase index size
  3. Consider sorting needs: Enable sorting only for fields you'll sort by

Text Processing

  1. Configure it once for the index: Set stem, token_separators, and symbols_to_index at the top level so the whole index is tokenized the same way as incoming queries
  2. Leave stemming on unless you need exact matching: It is on by default and improves recall wherever shoppers use varied word forms; turn it off only if your catalog depends on exact word matching
  3. Split compound identifiers: Add characters like - to token_separators so part numbers like AB-123 also match searches for 123
  4. Preserve meaningful symbols only: Add characters to symbols_to_index only when they carry meaning (for example, + in Galaxy S24+); preserving too many symbols reduces match flexibility

Performance

  1. Use specific filters: More specific filters improve query performance
  2. Limit facet values: Use max_facet_values to limit facet result counts
  3. Paginate results: Use page and per_page for large result sets

A/B Testing

Search profiles enable A/B testing without code changes:

  1. Create variant profiles with different field weights or boost rules
  2. Route traffic to different profiles (catalog rules per segment, or the search_profile query parameter when no rule slug applies)
  3. Measure conversion rates and revenue per search
  4. Iterate based on results
Ask External AI