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.
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
theandaat 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:
- Automatic indexing: All future catalog releases are automatically indexed when published
- Extended publishing: The publish process includes an indexing step that makes products searchable
- Search availability: Once indexed, products are searchable via the Search API
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:
- The catalog release is processed and stored (shows as 99% complete)
- An indexing job is created to make products searchable
- 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
- The release is marked as
PUBLISHEDwhen 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, andsymbols_to_index - Enable sorting and faceting on built-in fields like
name,sku,created_at, andupdated_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" }
}
]
}
| Attribute | Meaning |
|---|---|
type | Field data type: string, int32, int64, float, bool, or date. |
searchable | When 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. |
filterable | When true, the field can be used in filter expressions (filter_by), profile filters, boost conditions, and related filter syntax. |
facetable | Optional. When true, the field can be used for faceting. Defaults to false. |
sortable | Optional. When true, the field can be used for sorting. Defaults to true for numeric fields, otherwise false. |
locale | The 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.
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:
| Option | Description |
|---|---|
name | The 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>) |
facetable | Enable faceting (aggregated counts) on this field. Default: false |
sortable | Enable sorting by this field. Default: true for numeric fields, false otherwise |
locale | Language 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:
| Setting | Supported core fields |
|---|---|
sortable | name, sku, created_at, updated_at |
facetable | tags, 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.
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 indescription(weight 5) - Weights are relative: what matters is the proportion between them, not their absolute size, so
6:4:2behaves the same as3:2:1 - Each weight is a whole number between
0and15.
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:
| Type | Description | Best For |
|---|---|---|
max_score (default) | Uses highest score from any matching field | General product search |
max_weight | Uses score from highest-weighted matching field | When field importance matters more than match quality |
sum_score | Sums weighted scores from all matching fields | Rewarding 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.
Shopper search
For shopper endpoints — POST /pcm/catalog/search and POST /pcm/catalog/multi-search — profiles are chosen in this order:
| Priority | Source | Behavior |
|---|---|---|
| 1 | Catalog rule search_profile_slug | If 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. |
| 2 | search_profile query parameter | Used 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. |
| 3 | Tenant default profile | The profile marked as default for your store or organization. |
| 4 | Built-in default | A 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.
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.
Admin search
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:
search_profilequery parameter (same blank/invalid rules as shopper search)- Tenant default profile
- Built-in default (
SYSTEMS_DEFAULT_PROFILEinEP-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:
| Response | Header value |
|---|---|
| 2xx | Slug 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 errors | Header 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_slugon 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-Profileon 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 attribute | Controls |
|---|---|
catalog_id | Which catalog release the shopper searches |
pricebook_ids | Which price books apply (price segmentation) |
search_profile_slug | Which 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
- Create a search profile (for example slug
reseller-clothing) with a default filter such asmeta.search.nodes.name:=Clothingto limit searchable products to a hierarchy branch. - Create or update a catalog rule for the reseller account and set
attributes.search_profile_slugtoreseller-clothing, alongside anypricebook_idsfor that tier. - 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.
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
Basic Search
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"
Multi-Search
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
- Create or configure the search profile (filters, field weights, boosts as needed).
- Set
search_profile_slugon the matching catalog rule (Commerce Manager picker or Catalog Rules API). - Keep the storefront on shopper search with normal context headers — do not hard-code per-segment
search_profilequery parameters as the primary routing mechanism.
Verify
- Search as two shoppers (segmented vs default).
- Confirm different result counts and/or ranking when assortment or weights differ.
- Confirm response header
EP-Search-Profilematches the expected profile slug (orSYSTEMS_DEFAULT_PROFILEfor the built-in default).
Learn more
- How a search profile is chosen
- Segment audiences via catalog rules
- Price Segmentation — product assortment
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
- Start with core fields: Always include
name,description, andsku - Add category fields: Include
meta.search.nodes.namefor category-based discovery - Limit field count: Focus on 3-5 key fields to maintain relevance
- Test incrementally: Start with small weight differences and adjust based on results
Indexable Fields
- Index selectively: Only index fields that users will search or filter by
- Enable faceting wisely: Facetable fields increase index size
- Consider sorting needs: Enable sorting only for fields you'll sort by
Text Processing
- Configure it once for the index: Set
stem,token_separators, andsymbols_to_indexat the top level so the whole index is tokenized the same way as incoming queries - 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
- Split compound identifiers: Add characters like
-totoken_separatorsso part numbers likeAB-123also match searches for123 - Preserve meaningful symbols only: Add characters to
symbols_to_indexonly when they carry meaning (for example,+inGalaxy S24+); preserving too many symbols reduces match flexibility
Performance
- Use specific filters: More specific filters improve query performance
- Limit facet values: Use
max_facet_valuesto limit facet result counts - Paginate results: Use
pageandper_pagefor large result sets
A/B Testing
Search profiles enable A/B testing without code changes:
- Create variant profiles with different field weights or boost rules
- Route traffic to different profiles (catalog rules per segment, or the
search_profilequery parameter when no rule slug applies) - Measure conversion rates and revenue per search
- Iterate based on results