Skip to content

Search Products

About

Search the catalog by keyword. Pass a query argument to the products field:

graphql
products(query: "shirt", first: 10)

A product matches when the keyword appears anywhere in its name or its SKU. Partial words count — searching cott returns every product whose name contains Cotton.

This is the same field that powers List Products. Results come back in the same shape as a listing, so both screens render with the same code, and filtering, sorting, and pagination work identically. Use it to:

  • Implement product search over the catalog
  • Build auto-complete and suggestion interfaces
  • Narrow a search further by category, type, price range, or attribute
  • Order search results by title, price, or date

The sections below cover what matters on a search screen. List Products carries the full argument reference.

Arguments

ArgumentTypeDescription
queryStringSearch term. Matched as a partial string against the product name and SKU. Descriptions and attribute values are not searched.
firstIntNumber of results per page. Default: 30
afterStringCursor for pagination. Returns results after this cursor.
lastIntNumber of results for backward pagination. Default: 30
beforeStringCursor for backward pagination.
sortKeyStringSort results by: ID, TITLE (alias NAME), PRICE, CREATED_AT, UPDATED_AT. Case-insensitive. Default: ID
reverseBooleanReverse sort order. Default: false
filterStringJSON-encoded filter string. Accepts type, sku, category_id, price_from, price_to, new, featured, and any filterable attribute code (e.g. "{\"category_id\": \"22\"}").

Possible Returns

FieldTypeDescription
edges[ProductEdge]Search result edges containing product nodes and pagination cursors.
edges.nodeProductThe matched product, carrying the same fields as any catalog listing row.
edges.cursorStringPagination cursor for this result.
pageInfoProductPageInfo!Pagination metadata.
pageInfo.hasNextPageBooleanWhether more results follow the current page.
pageInfo.hasPreviousPageBooleanWhether results precede the current page.
pageInfo.startCursorStringCursor of the first result on the page.
pageInfo.endCursorStringCursor of the last result on the page.
totalCountInt!Total matching products across all pages.

A search accepts the same filter argument as the listing, so a keyword and a category or attribute selection combine into one request:

graphql
query searchInCategory($query: String, $filter: String) {
  products(query: $query, filter: $filter, first: 10) {
    totalCount
    edges {
      node {
        _id
        sku
        name
        formattedPrice
      }
    }
  }
}
json
{
  "query": "shirt",
  "filter": "{\"type\": \"configurable\", \"color\": \"3\"}"
}

The keyword and every filter key intersect — each one narrows the result further. The complete key list, the escaping rules, and the price-range caveats are on List Products.

Ordering Search Results

Search results are not ranked by relevance. Every match is returned in the order given by sortKey, and omitting it falls back to product ID — effectively arbitrary for a shopper. A search screen should therefore always set an explicit order, most often TITLE ascending or PRICE ascending.

The available sort keys, their reverse combinations, and the reason PRICE orders on minimumPrice rather than price are documented on List Products.

REST API Equivalents

Use CaseREST EndpointGraphQL Equivalent
Keyword search/api/shop/products?query=shirt&per_page=10products(query: "shirt", first: 10)
New Products/api/shop/products?new=1&sort=created_at-desc&per_page=10products(filter: "{\"new\": \"1\"}", sortKey: "CREATED_AT", reverse: true, first: 10)
Featured Products/api/shop/products?featured=1&sort=created_at-desc&per_page=12products(filter: "{\"featured\": \"1\"}", sortKey: "CREATED_AT", reverse: true, first: 12)
Popular by Brand/api/shop/products?brand=25&sort=created_at-desc&per_page=12products(filter: "{\"brand\": \"25\"}", sortKey: "CREATED_AT", reverse: true, first: 12)
All (Price Desc)/api/shop/products?sort=price-desc&per_page=12products(sortKey: "PRICE", reverse: true, first: 12)

Released under the MIT License.