Custom headless storefronts
Products and categories
Faceted and textual search

Faceted and Textual Search with the GraphQL Storefront API

Faceted search is a method of helping shoppers navigate a store's product inventory by categorizing products into various categories, brands, product features, and more. Textual search is a method of retrieving products based on product fields, for example, product name and description. BigCommerce's GraphQL Storefront API lets merchants on headless storefronts use faceted and textual search powered by results from our back-end search engine. These built-in capabilities also allow Stencil developers to take advantage of our search engine.

The GraphQL Storefront API's faceted and textual search lets you create the following features:

  • Load category pages with no selections, including both the facets and products relevant to the search results
  • Load category pages with facet selections for specific facets
  • Load featured products from specific categories
  • Quickly search products by using search terms (textual search)
  • Sort products alphabetically, from newest to oldest, and more

You can access these features by querying the SearchProducts field. Note that you can query facets, filter by rating, or filter by "in-stock" only if the merchant is on a Pro or Enterprise plan. A merchant must enable product filtering (opens in a new tab) for facets to be returned. In addition, only facets that a merchant marks as visible in their Product Filtering settings will be returned.

This page walks you through how to filter and query products and facets to display on your storefront. See the GraphQL Storefront Playground for full schema documentation.

Filter products and facets

To use faceted and textual search, specify a filter in the argument for SearchProducts. For faceted search, you can filter by price, rating, among other features and attributes of products. For textual search, use the searchTerm field.

Filters for products and facets
...
  searchProducts(
  filters: {
    searchTerm: "Sample"
    price:{
      minPrice:11,
      maxPrice:200
    },
    rating:{
      minRating:3,
      maxRating:5
    },
    categoryEntityId:24,
    searchSubCategories:false,
    categoryEntityIds:[23],
    brandEntityIds:[35],
    productAttributes:[
      {
        attribute:"Color",
        values:["Black"]
      }
    ],
    isFreeShipping:true,
    isFeatured:true,
    isInStock:true
  }
  ... 
)
...

These filters affect both the products and facets that are returned. For example, filtering by rating returns only products within the specified rating range and only facets that have products within the rating range.

See the GraphQL Storefront playground for descriptions of each filter.

Get products

To get products, specify products as a field in searchProducts. Here is an example request that returns the first two products with a rating between three and five:

Example
query {
  site {
    search {
      searchProducts(
        filters: {
          rating:{
             minRating:3,
             maxRating:5
           }
        }
      ) {
        products(first: 2) {
          edges {
            node {
              entityId
              name
              prices {
                price {
                  value
                }
              }
            }
          }
        }
      }
    }
  }
}

You can sort the products that are returned using the sort field. Here is an example query that searches for products using a search term and sorts the returned products in alphabetical order:

Example
query {
  site {
    search {
      searchProducts(
        filters: {
          searchTerm: "Sample"
        }
        sort: A_TO_Z
      ) {
        products(first: 2) {
          edges {
            node {
              entityId
              name
              prices {
                price {
                  value
                }
              }
            }
          }
        }
      }
    }
  }
}

The sort affects only the list of products returned. A merchant's product filtering settings (opens in a new tab) determine how facets are sorted.

If you sort by price, the products sort by either their salePrice or basePrice if sortPrice doesn't exist.

For a list of product fields that searchTerm searches, see the Store Search Product Fields (opens in a new tab) article.

Search and filtering with product attributes

You can also search and filter to include only products that have a specific product attribute.

  • Product attributes are based on product variants and custom fields.
  • For products to be filtered by a variant or custom field filter, the specific variant or custom field filter must be enabled.

Example

This GraphQL query is searching for products using a filter on a product attribute—specifically, filtering by the attribute Card Size with a value of Poker. It is also retrieving:

  • The matching products, including their entityId, name, and customFields.
  • The available filter options (facets) that can be used for further refinement, such as Category, Price, and Card Size.
Example Product Attributes
query GetFacets {
  site {
    search {
      searchProducts(
        filters:
        {
          productAttributes: [{
            attribute: "Card Size",
            values: ["Poker"]
          }]
        }
      ) {
        products {
          collectionInfo{
            totalItems
          }
          edges {
            node {
              entityId
              name
              customFields{
                edges{
                  node{
                    name
                    value
                  }
                }
              }
            }
          }
        }
        filters{
          edges{
            node{
              name
              isCollapsedByDefault
            }
          }
        }
      }
    }
  }
}

Get facets

To get facets, specify filters as a field in searchProducts. Here is an example request that returns the specified facets that have products with a rating between three and five:

Example
query {
  site {
    search {
      searchProducts(
        filters: {
           rating:{
             minRating:3,
             maxRating:5
           }
        }
      ) {
         filters {
           edges {
             node {
               __typename
               name
               isCollapsedByDefault
               ... on CategorySearchFilter {
                 name
                 displayProductCount
                 isCollapsedByDefault
                 categories {
                   edges {
                     node {
                       entityId
                       isSelected
                       productCount
                       subCategories {
                         edges {
                           node {
                             entityId
                             name
                           }
                         }
                       }
                     }
                   }
                 }
               }
               ... on OtherSearchFilter {
                 name
                 displayProductCount
                 isCollapsedByDefault
                 freeShipping {
                   isSelected
                   productCount
                 }
                 isInStock {
                   isSelected
                   productCount
                 }
                 isFeatured {
                   isSelected
                   productCount
                 }
               }
             }
           }
         }
      }
    }
  }
}

Note: The only facet query that works differently is ProductAttributeSearchFilter. To query names and information inside this filter, you must also query for the name one level above that node. If you do not format the query this way, the nodes will return empty.

For a complete list of facets, see the GraphQL Storefront playground.

Category-Based Product Filtering

In a product search, you can use AND and OR logic to control how multiple filters are applied:

  • AND logic requires a product to match all specified criteria, narrowing the results.
  • OR logic includes products that match any of the criteria, broadening the results.

These behaviors determine how flexible or strict your search is when using categoryIdsFilter. This is specifically useful when constructing Product Landing Pages (PLPs) or expecting a different filtering behavior.

Comparison Summary:

AspectAND LogicOR Logic
Match CriteriaProduct must be in all specified categoriesProduct can be in any one of the specified categories
Result SizeUsually smaller, since fewer products belong to multiple categoriesUsually larger, since many products belong to at least one category
Use Case ExampleFind products that appear in both "Sale" and "New Arrivals" categoriesFind products that appear in either "Accessories", "Shoes", or "Bags"

AND Logic Example

This example filters products to only those that appear in both of the specified categories:

Filter Logic

  • categoryIdsFilter: Defines the filter on product categories.
  • matchBehavior: AND: Means products that belong to both category 1172 and category 250 will match the query.
  • entityIds: [1172, 250]: These are the category IDs being filtered on. Only products that are in both category 1172 and category 250 will be included in the results.
Example AND Logic
query AND_Categories {
  site {
    search {
      searchProducts(
        filters:{
          categoryIdsFilter:{
            matchBehavior: AND,
            entityIds: [1172, 250]
          }
        }
      ) {
        products {
          edges {
            node {
              entityId
              name
              categories{
                edges{
                  node{
                    entityId
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

OR Logic Example

This example filters products to only those that appear in either of the specified categories:

Filter Logic

  • categoryIdsFilter: Defines the filter on product categories.
  • matchBehavior: OR: Means products that belong to either category 1172 or 250 will match the query.
  • entityIds: [1172, 250]: These are the category IDs being filtered on.
Example OR
query OR_Categories {
  site {
    search {
      searchProducts(
        filters:{
          categoryIdsFilter:{
            matchBehavior: OR,
            entityIds: [1172, 250]
          }
        }
      ) {
        products {
          edges {
            node {
              entityId
              name
              categories{
                edges{
                  node{
                    entityId
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

Put it all together: get products and facets

To get both products and facets, specify both products and filters fields in searchProducts.

Example
query {
  site {
    search {
      searchProducts(
        filters: {
          searchTerm: "Sample"
           rating:{
             minRating:3,
             maxRating:5
           }
        }
        sort: A_TO_Z
      ) {
        products(first: 2) {
          edges {
            node {
              entityId
              name
              prices {
                price {
                  value
                }
              }
            }
          }
        }
         filters {
           edges {
             node {
               __typename
               name
               isCollapsedByDefault
               ... on CategorySearchFilter {
                 name
                 displayProductCount
                 isCollapsedByDefault
                 categories {
                   edges {
                     node {
                       entityId
                       isSelected
                       productCount
                       subCategories {
                         edges {
                           node {
                             entityId
                             name
                           }
                         }
                       }
                     }
                   }
                 }
               }
               ... on OtherSearchFilter {
                 name
                 displayProductCount
                 isCollapsedByDefault
                 freeShipping {
                   isSelected
                   productCount
                 }
                 isInStock {
                   isSelected
                   productCount
                 }
                 isFeatured {
                   isSelected
                   productCount
                 }
               }
             }
           }
         }
      }
    }
  }
}

If a merchant has not enabled product filtering, you will receive an empty array for the returned facets, though products will still be returned:

Example
{
  "data": {
    "site": {
      "search": {
        "searchProducts": {
          "products": {
            "edges": [
              {
                "node": {
                  "entityId": 93,
                  "name": "[Sample] 1 L Le Parfait Jar",
                  "prices": {
                    "price": {
                      "value": 7
                    }
                  }
                }
              },
              {
                "node": {
                  "entityId": 80,
                  "name": "[Sample] Orbit Terrarium - Large",
                  "prices": {
                    "price": {
                      "value": 109
                    }
                  }
                }
              }
            ]
          },
          "filters": {
            "edges": []
          }
        }
      }
    }
  }
}

Limitations & Recommendations

LimitationRecommendation
Textual search input is limited to 255 characters.If you're accepting user input for search (e.g., via a search bar), you should:
  • Enforce or truncate the input to 255 characters.
  • Optionally notify users if their input is too long.
When you query for the category facet, only top-level (root) categories are returned in the facets by default, even if you are performing a product search that includes subcategories via search-subcategories=true.If you need subcategory-level filtering in the UI (e.g., in a sidebar filter), you typically need to:
  • Query the category tree separately (via the Catalog API or Storefront API site.categories).
  • Build your own custom filtering UI that maps products to subcategories manually.
  • Apply subcategory filters on the query directly, rather than relying on the facet metadata.

Resources

Did you find what you were looking for?