Skip to content

Product Discovery

Learn how to search, filter, and sort products to help users find exactly what they're looking for.

Product Filtering

Available filtering options:

  • Category filters - categoryId, categorySlug (matches category + subcategories)
  • Price ranges - minPrice, maxPrice (prices in cents)
  • Text search - name, producer, origin, search (full-text)
  • Boolean flags - isSeasonal, isVqa, isKosher, isBuyable
  • Numeric ranges - minAlcoholPercent, maxAlcoholPercent, minVolumeMl, maxVolumeMl

Combine multiple filters for more specific searches.

Filter by Category

Using Category ID

Use case: User selects a category from a dropdown or navigation menu.

graphql
query ProductsByCategory($categoryId: String!) {
  products(
    filters: {
      categoryId: $categoryId
      maxPrice: 5000
    }
    pagination: { first: 20 }
  ) {
    edges {
      node {
        sku
        name
        priceInCents
        producerName
        origin
      }
    }
    pageInfo {
      hasNextPage
      endCursor
    }
    totalCount
  }
}

Variables:

json
{
  "categoryId": "123"
}

Using Category Slug

Use case: Building SEO-friendly URLs like /wine/red-wine.

graphql
query WineProducts {
  products(
    filters: {
      categorySlug: "wine/red-wine"
      maxPrice: 5000
    }
    pagination: { first: 20 }
  ) {
    edges {
      node {
        sku
        name
        priceInCents
        producerName
        thumbnailUrl
      }
    }
    pageInfo {
      hasNextPage
      endCursor
    }
    totalCount
  }
}

Category Matching

Both categoryId and categorySlug match the specified category plus all its subcategories. For example, filtering by "wine" will return red wines, white wines, sparkling wines, etc.

To search for categories by name, see the Categories & Collections guide.

Filter by Price

Use case: User sets a price range slider or selects "Under $20" filter.

Find products under $20:

graphql
query AffordableProducts {
  products(
    filters: {
      categorySlug: "wine"
      maxPrice: 2000
    }
    pagination: { first: 20 }
  ) {
    edges {
      node {
        sku
        name
        priceInCents
        producerName
        origin
        unitVolumeMl
        thumbnailUrl
      }
    }
    pageInfo {
      hasNextPage
      endCursor
    }
    totalCount
  }
}

Prices in Cents

All prices are in cents (not dollars). To filter for products under $20, use maxPrice: 2000. To display prices, divide by 100: priceInCents / 100.

Filter by Producer

Use case: User searches for products from their favorite winery or brewery.

graphql
query ProducerProducts($producer: String!, $minPrice: Int!, $maxPrice: Int!) {
  products(
    filters: {
      producer: $producer
      minPrice: $minPrice
      maxPrice: $maxPrice
    }
    pagination: { first: 30 }
  ) {
    edges {
      node {
        sku
        name
        priceInCents
        unitVolumeMl
        alcoholPercent
        thumbnailUrl
      }
    }
    pageInfo {
      hasNextPage
      endCursor
    }
    totalCount
  }
}

Variables:

json
{
  "producer": "Jackson-Triggs",
  "minPrice": 1000,
  "maxPrice": 3000
}

Filter by Characteristics

Use case: Show only seasonal VQA wines during holiday promotions.

graphql
query SeasonalVQAWines {
  products(
    filters: {
      categorySlug: "wine"
      isSeasonal: true
      isVqa: true
    }
    pagination: { first: 20 }
  ) {
    edges {
      node {
        sku
        name
        priceInCents
        producerName
        origin
        unitVolumeMl
        alcoholPercent
        thumbnailUrl
      }
    }
    pageInfo {
      hasNextPage
      endCursor
    }
    totalCount
  }
}

Boolean Filters

Combine boolean filters to create specific product collections:

  • isSeasonal: true - Limited-time seasonal products
  • isVqa: true - VQA (Vintners Quality Alliance) certified wines
  • isKosher: true - Kosher-certified products
  • isBuyable: true - Currently available for purchase

Omit a filter (or set to null) to include all values.

Combined Filters and Sorting

Use case: User searches for "French Chardonnay under $40, sorted by price".

graphql
query ComplexProductSearch {
  products(
    filters: {
      name: "Chardonnay"
      origin: "France"
      minPrice: 1500
      maxPrice: 4000
      isVqa: false
    }
    pagination: { first: 15 }
    sortBy: PRICE
    sortDirection: ASC
  ) {
    edges {
      node {
        sku
        name
        priceInCents
        producerName
        origin
        unitVolumeMl
        alcoholPercent
      }
    }
    pageInfo {
      hasNextPage
      endCursor
    }
    totalCount
  }
}

Sorting Products

Available sort fields:

  • NAME - Alphabetical by product name
  • PRICE - By price (combine with ASC for low-to-high, DESC for high-to-low)
  • ALCOHOL_PERCENT - By alcohol content
  • VOLUME - By bottle/package size
  • PRICE_PER_ALCOHOL_ML - Best value for alcohol content
  • SELL_RANK_MONTHLY / SELL_RANK_YEARLY - By popularity
  • UPDATED_AT - Recently updated products

Use sortDirection: ASC (ascending) or DESC (descending).

Pagination

Use case: Load more products as user scrolls ("infinite scroll").

graphql
query ProductsPage($after: String) {
  products(
    filters: { categorySlug: "wine" }
    pagination: { 
      first: 25
      after: $after
    }
    sortBy: NAME
  ) {
    edges {
      node {
        sku
        name
        priceInCents
      }
      cursor
    }
    pageInfo {
      hasNextPage
      endCursor
    }
    totalCount
  }
}

To load the next page, pass pageInfo.endCursor as the after parameter:

json
{
  "after": "cursor-value-from-previous-response"
}

Pagination Best Practices

  • Product lists: 20-50 items per page
  • Search results: 15-25 items per page
  • Infinite scroll: 25-30 items per load
  • Performance: Request only the fields you need to reduce response size
  • Cursor-based: Always use pageInfo.endCursor and after for consistent results

The API uses Relay-style cursor-based pagination for reliable, consistent paging even when the dataset changes.

Next Steps