Overview
Spree provides powerful search, filtering, and sorting capabilities for products and other resources. The Store API supports:- Full-text search across product names, SKUs, and searchable custom fields
- Attribute-based filtering (price range, availability, stock status)
- Category and taxon filtering
- Faceted search with filter counts
- Flexible sorting options (including sortable product custom fields via
sort=cf_{namespace}_{key})
Product Search
Use thesearch parameter for full-text search across product fields:
Filtering Products
By Price Range
By Availability
By Category
By Tags
Sorting
Product Filters (Faceted Search)
Get available filter options for building a faceted search UI. Returns an array of typed filter objects (price range, availability, option types, categories) with counts, plus sort and pagination metadata:Filtering Other Resources
The Store API uses query parameters prefixed withq[] for filtering any resource collection. Common filter predicates:
Equality Predicates
String Predicates
Comparison Predicates
NULL Predicates
Only attributes explicitly allowed by each resource can be used for filtering. Attempting to filter on unsupported fields will be silently ignored.
Making a field filterable
A resource’s filters come from its model’s allowlists, and nowhere else. Spree generates its API reference and SDK types from them, so the Querying reference lists what core declares. Filters your app adds take effect in the API immediately; to use them from TypeScript, declare them as shown below, since the published SDK types are generated from core alone.server/config/initializers/spree.rb
search filter (q[search]=term) by naming the attributes it matches, partially and case-insensitively. Attributes of associated records are named with the association as a prefix:
server/app/models/spree/brand_decorator.rb
search is offered to the Store and Seller APIs only when each attribute it matches is one that API may filter on. The API reference describes it from the attributes.
Declare the type of a scope’s argument: 'boolean' for a scope taking none (q[featured]=true), or 'text', 'id', 'decimal', 'integer', 'date' or 'datetime' for one value. A list of kinds (%w[decimal decimal]) means several arguments in order, and { list: 'id' } means any number of them. A scope declared without a type is published as taking one text value.
Every entry is a filter any caller of that API can run. Keep back-office fields out of the Store API with private_ransackable_attributes, and add associations the storefront may filter through to storefront_ransackable_associations.
Using your own filters from TypeScript
The SDKs type eachlist() call with the filters Spree itself declares. A filter your app adds works in the API at once, but TypeScript rejects it until it is declared, because the published types cannot know about it. There are three ways to use it.
Generate the declarations (recommended). This reads your app’s filters, the ones Spree declares and the ones you added, and writes a declaration file into each app in your project, for the SDK that app uses. Run it from the project root:
- Spree CLI
- Without CLI
src/types/spree-filters.d.ts into each app that exists:
Run it again after you add or change a filter, and commit the generated files with the app code that uses them. For an app outside this layout, write one file for the SDK it uses:
spree filters types --api store --out path/to/spree-filters.d.ts. After that, every list() call accepts and autocompletes your filters and sort fields, and a misspelled one is still a compile error.
Send it unchecked. Filters inside q are sent as given, without type checking or autocomplete:
ProductFilterExtensions, OrderFilterExtensions, …) that is part of its filter type, and TypeScript merges your declaration into it. The file must contain an import or export; without one, it replaces the SDK’s types instead of adding to them:
src/types/spree.d.ts
erp_id_eq, erp_id_in for a list) or a scope by its name. Type amounts as decimal strings, counts as numbers and flags as booleans.
Pagination
All list endpoints support pagination:Search Providers
Spree uses a pluggable search provider architecture. The default provider uses SQL (ILIKE + Ransack). For production catalogs with 1,000+ products, we recommend installing thespree_meilisearch gem and switching to Meilisearch for typo tolerance, relevance ranking, and faster faceted search.
server/config/initializers/spree.rb
q[search], filter params, and sort options work with any provider.
See Build a Custom Search Provider for architecture details and how to build custom providers.
Related Documentation
- Products — Product catalog and listing
- Store SDK Products —
client.products.list()options and methods - Querying — Store API filtering, sorting, and pagination reference
- Admin API querying — Admin API filtering, sorting, and pagination reference
- Build a Custom Search Provider — Step-by-step guide
- Meilisearch Integration — Setup guide

