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
- Override core field behavior such as stemming, tokenization, and sorting on built-in fields like
name,description, andsku - Control tokenization at the collection or per-field level using token separators and symbols to index
List Available Searchable Fields
To see what fields are currently searchable:
curl https://useast.api.elasticpath.com/v2/pcm/catalogs/searchable-fields \
-H "Authorization: Bearer $ACCESS_TOKEN"
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 for tokenization (default: en) |
stem | Enable word stemming on this field. String fields only. Default: false. See Stemming |
token_separators | Characters that split text into tokens for this field, overriding the collection-level setting. See Customizing Tokenization |
symbols_to_index | Special characters preserved in tokens for this field, overriding the collection-level setting. See Customizing Tokenization |
Override Core Product Fields
Core product fields such as name, description, and sku are always indexed. Use core_field_overrides to change how individual core fields are indexed — for example, to enable stemming on descriptions, split SKUs on hyphens, or make name sortable:
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": "description",
"stem": true
},
{
"name": "name",
"stem": true,
"sortable": true
},
{
"name": "sku",
"token_separators": ["-"],
"sortable": true
}
]
}
}
}'
Each override supports stem, sortable, token_separators, and symbols_to_index, but not every setting is available on every core field:
| Setting | Supported core fields |
|---|---|
stem | name, description, meta.search.nodes.name |
sortable | name, sku |
token_separators | All string fields |
symbols_to_index | All string fields |
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 running. This improves search recall for descriptive text fields where shoppers may use different word forms than those found in product data.
For example, with stemming enabled on name, 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 only contains the base form walk.
Enable stemming per field by setting stem: true on entries in fields (custom fields) or core_field_overrides (core fields):
{
"data": {
"type": "catalog_search_indexable_fields",
"attributes": {
"fields": [
{ "name": "shopper_attributes.material", "stem": true }
],
"core_field_overrides": [
{ "name": "name", "stem": true },
{ "name": "description", "stem": true }
]
}
}
}
Notes:
- Stemming uses the Snowball stemmer
- Only valid for string-typed fields
- Defaults to
false
Customizing Tokenization
By default, text is split into tokens on whitespace and newlines, and special characters are stripped during indexing and searching. Two settings let you change this behavior.
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 e.g. S24+ vs S24.
Each element in token_separators and symbols_to_index must be a single character.
Collection-Level vs Field-Level
Both settings can be applied at two scopes:
- Collection-level: Set
token_separatorsorsymbols_to_indexat the top level of the indexable fields attributes to apply across all indexed fields. - Field-level: Set the same properties on an individual entry in
fieldsorcore_field_overridesto apply only to that field, overriding the collection-level setting. An empty array at the field level defers to the collection-level setting.
{
"data": {
"type": "catalog_search_indexable_fields",
"attributes": {
"token_separators": ["-"],
"symbols_to_index": ["+"],
"core_field_overrides": [
{ "name": "sku", "token_separators": ["/"] }
]
}
}
}
In this example, all fields split tokens on - and preserve +, except sku, which splits on / instead.
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:
10:5:3behaves the same as100:50:30
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 promote or demote products based on conditions:
{
"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)
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
Stemming and Tokenization
- Stem descriptive text: Enable stemming on fields like
nameanddescriptionwhere shoppers use varied word forms; it adds no value for identifiers like SKUs - Split compound identifiers: Use
token_separatorson fields likeskuso part numbers likeAB-123match 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 - Prefer collection-level settings: Prefer setting
token_separatorsandsymbols_to_indexat the collection level, and use per-field overrides only for exceptions
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