> ## Documentation Index
> Fetch the complete documentation index at: https://docs.uselayers.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Browse API: Browse Collection Page

> Browse API endpoint to fetch, filter, sort, and paginate merchandised collection pages in your catalog with facets, pins, and personalization applied.

## Authorization

<ParamField header="X-Storefront-Access-Token" type="string" required>
  Token-based authentication header in the form of `<YOUR_LAYERS_TOKEN>`.
</ParamField>

## Headers

<ParamField header="Content-Type" type="string" default="application/json" required />

<ParamField header="Accept" type="string" default="application/json" required />

## Path parameters

<ParamField path="collection_handle" type="string" required>
  The handle of the collection you wish to browse.
</ParamField>

## Body

<ParamField body="sort_order_code" type="string" description="The sort order for the results">
  Code of the sort order. If omitted, the collection's default sort order will be used (configured via the Layers dashboard or the `layers.default_sort_order` metafield on the collection).
</ParamField>

<ParamField body="dynamicLinking" type="object" description="Pin products to specific positions on the first page.">
  Dynamic Linking allows you to promote specific products to the top of the first page of results. This feature takes priority over merchandising rules and sort orders.

  <Note>
    If the Layers tracking pixel is installed, this parameter is **automatically injected** when customers arrive with a `utm_products` URL parameter (e.g., `?utm_products=summer-dress-blue_classic-tee-white_beach-hat`). See [Dynamic Linking for ads](/help/merchandising/dynamic-linking) for details.
  </Note>

  <Expandable title="Properties">
    <ParamField body="products" type="array" required>
      Array of product identifiers (handles or IDs) in the order you want them to appear. The first item will be position 1, second item position 2, etc.

      * **Handles**: String values (e.g., `"summer-dress-blue"`)
      * **IDs**: Numeric values (e.g., `8234567890123`)
      * **Mixed**: You can combine both handles and IDs in the same array

      **Behavior:**

      * Only applies on the first page of results (page 1)
      * Non-existent or unavailable products are silently skipped
      * Subsequent products shift up to fill any gaps
      * Takes priority over merchandising rules and sort orders

      **Example:**

      ```json theme={null}
      {
        "dynamicLinking": {
          "products": ["summer-dress-blue", 8234567890123, "classic-tee-white"]
        }
      }
      ```
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="defaultSelectedOptions" type="array" description="Default variant selection preferences when no filters are applied.">
  Specify which product variants should be selected by default in the `first_or_matched_variant` field. This is useful for scenarios like defaulting to a specific birthstone option in a jewelry collection.

  <Expandable title="Properties">
    <ParamField body="optionCode" type="string" required>
      The product option code to match (e.g., `"birthstone"`, `"color"`). Option codes are automatically normalized (e.g., `"Birth Stone"` becomes `"birth_stone"`).
    </ParamField>

    <ParamField body="value" type="string" required>
      The option value to match (e.g., `"February"`, `"Blue"`).
    </ParamField>
  </Expandable>

  **Behavior:**

  * Uses **OR logic** - selects the first variant matching ANY of the specified option values
  * Falls back to the first variant by position if no match is found
  * **Automatically skipped** when any option or variant filters are applied (filters take precedence)
  * Only affects the `first_or_matched_variant` field in the response
  * **Works with [Variant Breakouts](/platform/variant-breakouts)** - product tiles respect your default selected options, and variant tiles respect non-breakout default selected options (preferring variants that match your preferences within each breakout group, with fallback to position ordering)

  **Example:**

  ```json theme={null}
  {
    "defaultSelectedOptions": [
      {
        "optionCode": "birthstone",
        "value": "February"
      }
    ]
  }
  ```

  **Multiple options example (OR logic):**

  ```json theme={null}
  {
    "defaultSelectedOptions": [
      {
        "optionCode": "birthstone",
        "value": "February"
      },
      {
        "optionCode": "birthstone",
        "value": "March"
      }
    ]
  }
  ```

  This will select variants with either February OR March birthstone, preferring the first match found.
</ParamField>

<ParamField body="attributes" type="string[]" description="Product attributes to include in the response.">
  Product attributes to include in the response. By default, all attributes are included. Available attributes include: `id`, `title`, `handle`, `body_html`, `vendor`, `product_type`, `tags`, `images`, `available`, `created_at`, `updated_at`, `published_at`, `price_range`, `options`, `original_options`, `metafields`, `named_tags`, `calculated`, `category`, `featured_media`, `is_gift_card`, `has_variants_that_require_components`, `combined_listing_parent_product_id`, `combined_listing_role`, `first_or_matched_variant`, and `variants`. See the <a href="/developers/product-schema/api-attributes">Product Schema</a> for detailed descriptions, including <a href="/developers/product-schema/api-attributes#selecting-nested-fields">nested field selection</a> for slicing arrays and filtering collections (for example, <code>images\[:2].src</code>, <code>variants\[sku=ABC].price</code>, <code>metafields\[namespace=custom]</code>).
</ParamField>

<ParamField body="filter_group" type="object" description="A group of filter conditions using various operators.">
  Refer to our dedicated [Filter Expressions](/engine/filtering) guide to learn more about filter expressions.
</ParamField>

<ParamField body="pagination" type="Pagination Object" description="Specifies the page number and limit for pagination.">
  <Expandable title="pagination">
    <ParamField body="page" type="int" min="1" max="100">
      The current page of results to fetch.
    </ParamField>

    <ParamField body="limit" type="int" min="1" max="100">
      The max results to fetch per page
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="facets" type="string[]" description="List of facets to include in the response.">
  Facets to be included. Accepts both exact facet codes (e.g., `"vendor"`, `"options.Size"`) and wildcard patterns (e.g., `"options.*"`, `"metafields.product.*"`).

  Wildcard patterns expand to all matching attribute codes. For example, `"options.*"` expands to all option facets like `"options.Size"` and `"options.Color"`. Wildcards must match at least one attribute code to be valid.

  **Examples:**

  ```json theme={null}
  // Exact facet codes
  "facets": ["vendor", "options.Size", "options.Color"]

  // Wildcard pattern
  "facets": ["options.*"]

  // Mixed exact and wildcard
  "facets": ["vendor", "options.*", "metafields.product.*"]
  ```
</ParamField>

<ParamField body="retrieveFacetCount" type="boolean" description="Retrieve facet count.">
  If the count of each facet value should be calculated
</ParamField>

<ParamField body="includeFacetRanges" type="boolean" descriptive="Return min/max range for facets with a numeric value.">
  If you want a min/max range for numeric facets such as price.
</ParamField>

<ParamField body="discountEntitlements" type="array" description="Array of discount entitlement objects for applying dynamic discounts to products.">
  Apply discounts to products, variants, or collections. When provided, price-based sorting and filtering will use discounted prices. See the [Discount Entitlements](/shopify-integration/discount-entitlements) guide for detailed usage.

  <Expandable title="Discount Entitlement Object">
    <ParamField body="entitled" type="object" required>
      Defines which products qualify for the discount.

      <Expandable title="entitled">
        <ParamField body="all" type="boolean">
          When `true`, applies discount to all products. When `false`, uses products, variants, or collections arrays.
        </ParamField>

        <ParamField body="products" type="string[]">
          Array of product IDs or handles that qualify for the discount.
        </ParamField>

        <ParamField body="variants" type="string[] | number[]">
          Array of variant IDs that qualify for the discount.
        </ParamField>

        <ParamField body="collections" type="string[]">
          Array of collection handles that qualify for the discount.
        </ParamField>
      </Expandable>
    </ParamField>

    <ParamField body="discount" type="object" required>
      Defines the discount to apply.

      <Expandable title="discount">
        <ParamField body="type" type="string" required>
          The discount type: `PERCENTAGE` or `FIXED_AMOUNT`.
        </ParamField>

        <ParamField body="value" type="number" required>
          The discount value. For `PERCENTAGE`, this must be a number between 0 and 100 (e.g., 10 for 10% off). For `FIXED_AMOUNT`, this is the currency amount.
        </ParamField>
      </Expandable>
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="identity" type="object">
  User identity information for tracking and personalization. Automatically managed by the Storefront Pixel; required for headless integrations.

  <Expandable title="Properties">
    <ParamField body="deviceId" type="string">
      Persistent browser identifier that remains constant across sessions. Used to recognize returning visitors for long-term personalization. Automatically generated and managed by the Storefront Pixel.
    </ParamField>

    <ParamField body="sessionId" type="string">
      Temporary session identifier. Typically corresponds to the Shopify session ID and expires after inactivity or when the browser is closed.
    </ParamField>

    <ParamField body="customerId" type="string">
      Shopify customer ID for authenticated users. Only present when the user is signed in to their account.
    </ParamField>

    <ParamField body="companyLocationId" type="string">
      Shopify B2B company location GID (e.g. `gid://shopify/CompanyLocation/123456789`) for the authenticated buyer. Layers resolves the catalog assigned to the company location and uses it to scope results: only products in the catalog are returned, prices come from the catalog's price list, and excluded collections return 404. Omit for retail (DTC) traffic. See [B2B catalogs](/shopify-integration/b2b-catalogs).
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="preview_id" type="string" description="UUID of a merchandising rule preview.">
  When provided, the Browse API loads the specified preview rule instead of the collection's active merchandising rule. Preview rules are temporary and expire one hour after creation.

  This parameter is automatically included when you open a preview URL from the Layers dashboard. You do not need to set it manually in production integrations.

  **Behavior:**

  * Overrides normal merchandising rule resolution for this request
  * Analytics and beacon events are not recorded for preview requests
  * Returns a `404` if the preview has expired or does not exist
</ParamField>

<ParamField body="forceHideOutOfStock" type="boolean" default="false" description="Force-hide out-of-stock products from results.">
  When set to `true`, products with no available variants are excluded from results regardless of the store-level [out-of-stock visibility](/help/configuration/configure-search-behavior#out-of-stock-product-visibility) setting. If your store has [location-based stock checking](/help/configuration/configure-search-behavior#location-based-stock-check) configured, the same location rules apply.

  This is useful when a specific browse integration or page requires strict in-stock filtering even though the store default allows out-of-stock products to appear.

  <Note>
    Store-level out-of-stock demoting (the "At the end" option) does not apply to browse results. Browse relies on the Shopify collection itself for product ordering. When you set `forceHideOutOfStock` to `true` on a browse request, out-of-stock products are hidden entirely rather than demoted.
  </Note>
</ParamField>

<ParamField body="context" type="object">
  Contextual information about the customer's session, behavior, and environment. Automatically collected by the Storefront Pixel; must be manually provided for headless integrations. See [Contextual Information](/engine/contextual-information) for implementation guidance.

  <Expandable title="Properties">
    <ParamField body="geo" type="object">
      Geographic location information for regional personalization and merchandising. Automatically determined by the platform for client-side requests based on IP address. For server-side API calls (headless integrations), you should provide this explicitly.

      <Expandable title="Properties">
        <ParamField body="country" type="string">
          Country code or name (e.g., "US", "Canada").
        </ParamField>

        <ParamField body="province" type="string">
          State or province name (e.g., "California", "Ontario").
        </ParamField>

        <ParamField body="city" type="string">
          City name (e.g., "Los Angeles", "Toronto").
        </ParamField>
      </Expandable>
    </ParamField>

    <ParamField body="productsInCart" type="array">
      Products currently in the customer's cart. Used to surface complementary products and influence relevance scoring.

      <Expandable title="Array Item Properties">
        <ParamField body="title" type="string" required>
          Product title.
        </ParamField>

        <ParamField body="price" type="number">
          Product price.
        </ParamField>

        <ParamField body="type" type="string">
          Product type or category.
        </ParamField>

        <ParamField body="productId" type="string">
          Product identifier. Accepts a numeric ID (e.g., `"8234567890123"`) or a Shopify GID (e.g., `"gid://shopify/Product/8234567890123"`).
        </ParamField>

        <ParamField body="variantId" type="string">
          Product variant identifier.
        </ParamField>

        <ParamField body="options" type="object">
          Product variant options (e.g., `{"Size": "11", "Color": "Red"}`).
        </ParamField>
      </Expandable>
    </ParamField>

    <ParamField body="productsPurchased" type="array">
      Products the customer has previously purchased. Informs recommendations and prevents over-promotion of owned items.

      <Expandable title="Array Item Properties">
        <ParamField body="title" type="string" required>
          Product title.
        </ParamField>

        <ParamField body="price" type="number">
          Product price at time of purchase.
        </ParamField>

        <ParamField body="type" type="string">
          Product type or category.
        </ParamField>

        <ParamField body="productId" type="string">
          Product identifier. Accepts a numeric ID (e.g., `"8234567890123"`) or a Shopify GID (e.g., `"gid://shopify/Product/8234567890123"`).
        </ParamField>

        <ParamField body="variantId" type="string">
          Product variant identifier.
        </ParamField>

        <ParamField body="options" type="object">
          Product variant options (e.g., `{"Size": "11", "Color": "Red"}`).
        </ParamField>
      </Expandable>
    </ParamField>

    <ParamField body="priorSearches" type="array">
      Recent search queries and their outcomes. Helps understand customer intent and refine relevance models.

      <Expandable title="Array Item Properties">
        <ParamField body="searchQuery" type="string" required>
          The search query text.
        </ParamField>

        <ParamField body="hadClick" type="boolean" required>
          Whether the customer clicked on any results from this search.
        </ParamField>

        <ParamField body="hasResults" type="boolean" required>
          Whether the search returned any results.
        </ParamField>

        <ParamField body="fromPage" type="string">
          The page the search was initiated from (e.g., the referring page URL or page type).
        </ParamField>
      </Expandable>
    </ParamField>

    <ParamField body="marketing" type="object">
      UTM parameters and marketing campaign information for attribution tracking.

      <Expandable title="Properties">
        <ParamField body="source" type="string">
          Marketing source (e.g., "google", "facebook").
        </ParamField>

        <ParamField body="medium" type="string">
          Marketing medium (e.g., "cpc", "email", "social").
        </ParamField>

        <ParamField body="campaign" type="string">
          Campaign name.
        </ParamField>

        <ParamField body="term" type="string">
          Search term or keyword.
        </ParamField>
      </Expandable>
    </ParamField>

    <ParamField body="customer" type="object">
      Aggregated customer behavior and purchase patterns for personalization.

      <Expandable title="Properties">
        <ParamField body="signedIn" type="boolean">
          Whether the customer is currently authenticated.
        </ParamField>

        <ParamField body="returning" type="boolean">
          Whether this is a returning customer.
        </ParamField>

        <ParamField body="numberOfOrders" type="integer">
          Total number of orders placed.
        </ParamField>

        <ParamField body="averageOrderValue" type="number">
          Average order value in store currency.
        </ParamField>

        <ParamField body="daysBetweenOrders" type="integer">
          Average days between orders.
        </ParamField>

        <ParamField body="daysSinceLastOrder" type="integer">
          Days since the most recent order.
        </ParamField>

        <ParamField body="daysSinceOldestOrder" type="integer">
          Days since the first order.
        </ParamField>

        <ParamField body="totalSpent" type="number">
          Total amount spent in store currency.
        </ParamField>
      </Expandable>
    </ParamField>

    <ParamField body="market" type="string">
      Explicitly set the Shopify Market for this request. Used for market-specific product availability filtering and contextual pricing. Accepts a two-letter country code (e.g., `"US"`, `"CA"`), a numeric Shopify Market ID (e.g., `"12345"`), or a Shopify Market GID (e.g., `"gid://shopify/Market/12345"`).

      When not provided, the market is automatically resolved from the `geo.country` field (or the shopper's detected country for client-side requests). If no matching market is found, the store's primary market is used as the fallback.

      **Behavior depends on the store's market application mode:**

      * **Strict** — Products are filtered to only those available in the resolved market, and market-specific pricing is applied
      * **Pricing only** — The full catalog remains visible, but variant prices are swapped to market-specific values where available
      * **Off** — Market resolution is skipped entirely; base catalog and base pricing are used for all shoppers
    </ParamField>

    <ParamField body="shoppingChannel" type="string" default="web">
      The shopping channel the customer is browsing from. Used for channel-specific merchandising, sorting, and analytics segmentation. Automatically detected from request headers when not provided (e.g., mobile app requests via Tapcart or Canvas are detected as `"app"`).

      **Accepted values:**

      * `"web"` — Standard web browser (default)
      * `"app"` — Mobile app (e.g., Tapcart, Canvas)
    </ParamField>

    <ParamField body="custom" type="object">
      Custom contextual data specific to your implementation. Structure is flexible and can contain any key-value pairs relevant to your use case.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="responseOptions" type="object" description="Per-request overrides for response behavior.">
  Per-request overrides for response behavior. Currently controls image preload hints emitted in the `Link` response header. You can disable preloads or narrow the srcset to the breakpoints your storefront uses. You cannot enable preloads when the store has them disabled.

  <Expandable title="Properties">
    <ParamField body="mediaPreloads" type="object" description="Controls Early Hints preload directives for product images.">
      Controls the `Link: rel=\"preload\"` directives generated for product images in this response. See [Early hints](/sdk/performance#early-hints-link-header-preloading) for background.

      <Expandable title="Properties">
        <ParamField body="enabled" type="boolean" default="true">
          Set to `false` to skip the `Link` header for this request. Useful for server-rendered pages that do not benefit from preload hints, or when you want to reduce response header size. Cannot enable preloads if they are disabled at the store level.
        </ParamField>

        <ParamField body="srcsetSizes" type="int[]">
          Custom responsive image widths (in pixels) to emit in `imagesrcset`. Each value must be an integer between `1` and `10000`. Overrides the store-level srcset configuration for this request only. When omitted, the store configuration or platform defaults are used.
        </ParamField>
      </Expandable>
    </ParamField>
  </Expandable>

  **Example:**

  ```json theme={null}
  {
    "responseOptions": {
      "mediaPreloads": {
        "enabled": true,
        "srcsetSizes": [320, 640, 960]
      }
    }
  }
  ```
</ParamField>

## Response

<ResponseField name="results" type="Array of Objects">
  <Expandable title="Properties">
    <ResponseField name="id" type="number">
      The unique identifier of the product.
    </ResponseField>

    <ResponseField name="title" type="string">
      The title of the product.
    </ResponseField>

    <ResponseField name="body_html" type="string">
      The HTML content describing the product.
    </ResponseField>

    <ResponseField name="vendor" type="string">
      The vendor of the product.
    </ResponseField>

    <ResponseField name="product_type" type="string">
      The type of the product.
    </ResponseField>

    <ResponseField name="created_at" type="number">
      The timestamp when the product was created.
    </ResponseField>

    <ResponseField name="handle" type="string">
      The handle of the product.
    </ResponseField>

    <ResponseField name="updated_at" type="number">
      The timestamp when the product was updated.
    </ResponseField>

    <ResponseField name="published_at" type="number">
      The timestamp when the product was published.
    </ResponseField>

    <ResponseField name="tags" type="Array of strings">
      The tags associated with the product.
    </ResponseField>

    <ResponseField name="combined_listing_parent_product_id" type="number">
      The parent product id if a child in a Combined Listing.
    </ResponseField>

    <ResponseField name="combined_listing_role" type="string">
      The role of the product if part of a Combined Listing.
    </ResponseField>

    <ResponseField name="images" type="Array of Objects">
      The images of the product.

      <Expandable title="Properties">
        <ResponseField name="alt" type="string">
          The alt text of the image.
        </ResponseField>

        <ResponseField name="src" type="string">
          The src of the image.
        </ResponseField>

        <ResponseField name="width" type="number">
          The width of the image.
        </ResponseField>

        <ResponseField name="height" type="number">
          The height of the image.
        </ResponseField>

        <ResponseField name="variant_ids" type="Array">
          The variant IDs associated with the image.
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="metafields" type="Object">
      The metafields of the product.
    </ResponseField>

    <ResponseField name="calculated" type="Object">
      The computed attributes of the product. Only includes attributes with non-null, non-empty values. Attributes that evaluate to null or an empty string are omitted.
    </ResponseField>

    <ResponseField name="category" type="Object">
      The Shopify Product Taxonomy Category of the product.

      <Expandable title="Properties">
        <ResponseField name="name" type="string">
          The name of the category leaf.
        </ResponseField>

        <ResponseField name="full_name" type="string">
          The full name of the category.
        </ResponseField>

        <ResponseField name="id" type="string">
          The ID of the category.
        </ResponseField>

        <ResponseField name="is_leaf" type="boolean">
          Is the category a root category.
        </ResponseField>

        <ResponseField name="is_root" type="boolean">
          Is the category a root category.
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="first_or_matched_variant" type="Object">
      The first available variant (depending on OOS settings) or the variant matched with a filter or search query.

      <Expandable title="Properties">
        <ResponseField name="id" type="number">
          The ID of the variant.
        </ResponseField>

        <ResponseField name="title" type="string">
          The title of the variant.
        </ResponseField>

        <ResponseField name="available" type="boolean">
          The availability of the variant.
        </ResponseField>

        <ResponseField name="sku" type="number">
          The sku of the variant.
        </ResponseField>

        <ResponseField name="price" type="string">
          The price of the variant.
        </ResponseField>

        <ResponseField name="compare_at_price" type="string">
          The compare at price of the variant.
        </ResponseField>

        <ResponseField name="metafields" type="Object">
          The metafields of the variant.
        </ResponseField>

        <ResponseField name="selected_options" type="Array of Objects">
          The selected options of the variant.

          <Expandable title="Properties">
            <ResponseField name="name" type="string">
              The name of the option.
            </ResponseField>

            <ResponseField name="value" type="string">
              The value of the option
            </ResponseField>

            <ResponseField name="option_value" type="object">
              The linked metafield of the option.
            </ResponseField>
          </Expandable>
        </ResponseField>

        <ResponseField name="position" type="number">
          The position of the variant in the product's variant list.
        </ResponseField>

        <ResponseField name="inventory_quantity" type="number">
          Total inventory quantity across all locations. Only included when the store has the **Expose Variant Inventory** setting enabled.
        </ResponseField>

        <ResponseField name="inventory_policy" type="string">
          Inventory policy for the variant: `DENY` (stop selling when out of stock) or `CONTINUE` (allow overselling). Only included when the store has the **Expose Variant Inventory** setting enabled.
        </ResponseField>

        <ResponseField name="inventory_levels" type="object">
          Object mapping location IDs to available inventory quantities (e.g., `{"1001": 5, "1002": 10}`). Returns empty object `{}` when no inventory data exists. Only included when the store has the **Expose Variant Inventory** setting enabled.
        </ResponseField>

        <ResponseField name="featured_media" type="Object">
          The featured media of the product.

          <Expandable title="Properties">
            <ResponseField name="mediaContentType" type="string">
              The type of media.
            </ResponseField>

            <ResponseField name="alt" type="string">
              The alt text of the image.
            </ResponseField>

            <ResponseField name="src" type="string">
              The src of the image.
            </ResponseField>

            <ResponseField name="width" type="number">
              The width of the image.
            </ResponseField>

            <ResponseField name="height" type="number">
              The height of the image.
            </ResponseField>
          </Expandable>
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="featured_media" type="Object">
      The featured media of the product.

      <Expandable title="Properties">
        <ResponseField name="mediaContentType" type="string">
          The type of media.
        </ResponseField>

        <ResponseField name="alt" type="string">
          The alt text of the image.
        </ResponseField>

        <ResponseField name="src" type="string">
          The src of the image.
        </ResponseField>

        <ResponseField name="width" type="number">
          The width of the image.
        </ResponseField>

        <ResponseField name="height" type="number">
          The height of the image.
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="available" type="boolean">
      The availability of the product.
    </ResponseField>

    <ResponseField name="price_range" type="Object">
      The price range of the product.

      <Expandable title="Properties">
        <ResponseField name="from" type="number">
          The starting price of the product.
        </ResponseField>

        <ResponseField name="to" type="number">
          The ending price of the product.
        </ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="totalResults" type="number">
  The total number of results. When variant breakouts are enabled, this reflects the count of tiles (both product and variant tiles) rather than just products.

  The count is scoped to the visibility of the active shopping channel. When `context.shoppingChannel` is `"web"` (the default), only products published to the online store are counted. When it is `"app"` and an [app sales channel](/help/configuration/configure-search-behavior#app-sales-channel) is configured, only products published to that channel are counted. As a result, `totalResults` always matches the number of products a shopper can actually see for that channel.
</ResponseField>

<ResponseField name="page" type="number">
  The current page number.
</ResponseField>

<ResponseField name="totalPages" type="number">
  The total number of pages. Calculated based on tile count when variant breakouts are enabled.
</ResponseField>

<ResponseField name="facets" type="object">
  If `retrieveFacetCount` is `true` then an object with keys and values of the specified attributes. When variant breakouts are enabled, facet counts reflect tile counts rather than product counts. Empty values and literal `"null"` strings are automatically excluded from facet results.
</ResponseField>

<ResponseField name="facetRanges" type="object">
  If `includeFacetRanges` is `true` then an object with keys of the facet attribute code and value is an object with min/max.
</ResponseField>

<ResponseField name="attributionToken" type="string">
  A unique request identifier (ULID) for this API call. Use this token to correlate browse requests with analytics events via the [Beacon API](/tracking-api/send-events), and to match requests to entries in the [Search Inspector](/shopify-integration/storefront-pixel#search-inspector).
</ResponseField>

<ResponseField name="_meta" type="object">
  <Expandable title="Properties">
    <ResponseField name="appliedRules" type="Array of strings">
      The merchandising rule ID's applied to the request.
    </ResponseField>

    <ResponseField name="appliedSearchRules" type="Array of strings">
      The IDs of [request transforms](/platform/request-transforms) that matched and were applied to this request. Returns an empty array when no request transforms matched. Use this to verify which request transforms are affecting a given browse request.
    </ResponseField>

    <ResponseField name="affinities" type="array of objects">
      User affinity signals derived from the session's [contextual information](/engine/contextual-information). Only present when you pass the `context` and `identity` parameters and the engine detects meaningful affinity patterns from cart contents and purchase history. The array contains both **promotion** entries (positive weights for preferred attribute values) and **demotion** entries (small negative weights for non-preferred values within the same attribute). Entries are grouped by property and sorted by weight in descending order.

      <Expandable title="Properties">
        <ResponseField name="property" type="string">
          The product attribute the affinity applies to (e.g., `"vendor"`, `"product_type"`, `"named_tags.color"`, `"options.Size"`).
        </ResponseField>

        <ResponseField name="operator" type="string">
          The comparison operator. `"eq"` for promotion entries that boost a specific value. `"not_in"` for demotion entries that slightly suppress products that don't match any detected preference for this attribute.
        </ResponseField>

        <ResponseField name="value" type="string | array of strings">
          For promotion entries (`"eq"`): the specific attribute value that was boosted (e.g., `"Nike"`, `"Running Shoes"`). For demotion entries (`"not_in"`): an array of all promoted values for this attribute, so products not matching any of them receive a small negative boost.
        </ResponseField>

        <ResponseField name="weight" type="number">
          The boost weight applied. Promotion weights range from `0` to `1.2`, where higher values indicate stronger preferences. Demotion weights are small negative values proportional to the strongest promotion in the same attribute group. Option-level attributes (e.g., `options.Size`) receive lower weights than product-level attributes (e.g., `vendor`).
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="variantBreakouts" type="array of objects">
      Array of variant breakout configurations applied to this collection. Only present when one or more variant breakouts are active for the collection. Multiple breakouts with different option codes can work simultaneously in the same collection. Each object has the structure `{optionCode: "Stone"}`.

      <Expandable title="Properties">
        <ResponseField name="optionCode" type="string">
          The product option code that determines which variants are broken out (e.g., "Stone", "Color"). Each product is broken out by the first matching option code from the array.
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="mediaPreloads" type="object">
      Echoes the image preload configuration used to build the `Link` response header for this request. Only present when image preloads are emitted. See [Early hints](/sdk/performance#early-hints-link-header-preloading).

      <Expandable title="Properties">
        <ResponseField name="srcsetSizes" type="int[]">
          The responsive image widths (in pixels) used in the `imagesrcset` of the `Link` header. Reflects the request override when provided, otherwise the store-level configuration or platform defaults.
        </ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="_workflow" type="array of objects">
  An ordered trace of processing steps the engine performed to produce results for this request. Each entry represents a stage in the browse pipeline, recorded in the order it was executed. Use this field to understand which merchandising rules, sort orders, and boosts were applied.

  This field is useful for debugging browse behavior in development and is also surfaced in the [Search Inspector](/shopify-integration/storefront-pixel#search-inspector) panel.

  <Expandable title="Properties">
    <ResponseField name="type" type="string">
      The processing step type. Possible values include:

      * `"rule-applied"` — A merchandising rule was applied. The `payload` contains the rule identifier.
      * `"affinity-boosts"` — User affinity signals from session context were applied to personalize results.
      * `"ranking-rules"` — Ranking rules influenced result ordering.

      See the [Text Search](/api-reference/search) documentation for a full list of possible step types.
    </ResponseField>

    <ResponseField name="payload" type="string | array | object">
      The data associated with this processing step. The structure varies by `type`.
    </ResponseField>
  </Expandable>
</ResponseField>

### Response headers

Every API response includes the following headers for request tracing and performance optimization:

| Header                   | Description                                                                                                                                                                                                                                                                                                                                                     |
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `x-request-id`           | A unique identifier (ULID) for the request. This matches the `attributionToken` in the response body. Use it to correlate requests across your infrastructure or when contacting support.                                                                                                                                                                       |
| `x-layers-build`         | The Layers build version that served the request.                                                                                                                                                                                                                                                                                                               |
| `X-Layers-Results-Cache` | Indicates whether the response was served from the results cache. Returns `HIT` when cached results were used, or `MISS` when results were computed fresh.                                                                                                                                                                                                      |
| `Link`                   | Contains `rel="preload"` directives for product images in the response (up to 6 items), enabling browsers and CDNs to begin fetching images before your application processes the JSON body. See [Early hints](/sdk/performance#early-hints-link-header-preloading) for configuration options. Only included when early hints are enabled (enabled by default). |

### Variant breakouts

When variant breakouts are configured, results may include both product tiles and variant tiles. Each result includes a `__typename` field to identify the tile type:

<ResponseField name="__typename" type="string">
  Identifies the type of tile in the results:

  * `"Product"` - A standard product tile
  * `"Variant"` - An individual variant tile from a product with a configured breakout option
</ResponseField>

#### Variant tile fields

Variant tiles include additional fields to identify the specific variant:

<ResponseField name="product_id" type="number">
  The parent product ID. Use this to link back to the full product or group variants from the same product.
</ResponseField>

<ResponseField name="variant_id" type="number">
  The specific variant ID. For variant tiles, this matches the `id` field.
</ResponseField>

<Note>
  For variant tiles, the `id` field contains the variant ID (not the product ID). The `title` field is formatted as `"{product title} - {option value}"` by default (e.g., "Amethyst Ring - Rose Quartz"), but this can be configured per breakout. If the breakout's "Include Option Value in Title" setting is disabled, the title will be the original product title. See the [Variant Breakouts](/platform/variant-breakouts) documentation for more details.
</Note>

<ResponseExample>
  ```json Request theme={null}
  POST /storefront/v1/browse/summer-collection

  {
    "sort_order_code": "best-sellers",
    "pagination": {
      "page": 1,
      "limit": 20
    },
    "retrieveFacetCount": true,
    "facets": ["vendor", "product_type"],
    "context": {
      "geo": {
        "country": "US",
        "province": "California"
      },
      "marketing": {
        "source": "google",
        "medium": "cpc",
        "campaign": "summer-sale"
      },
      "shoppingChannel": "web"
    },
    "identity": {
      "sessionId": "abc123",
      "deviceId": "device-uuid"
    }
  }
  ```

  ```json Response theme={null}
  {
      "results": [
          {
              "id": 7003338965178,
              "title": "SUPREME SEALLINE SEE POUCH SMALL",
              "body_html": "The Supreme Sealline See Pouch Small is a versatile and waterproof storage solution that seamlessly marries utility and style. With its clear window for easy visibility and the iconic Supreme branding, it's a sought-after accessory for those who appreciate keeping their essentials dry while making a fashion statement, whether at the beach or in the city..",
              "vendor": "SUPREME",
              "product_type": "Accessories",
              "created_at": "2022-02-05T01:22:05.000000Z",
              "handle": "supreme-pouch-44370ss18a32-sm",
              "updated_at": "2023-10-25T20:47:04.000000Z",
              "published_at": "2022-02-05T01:22:05.000000Z",
              "tags": [
                  "consignment"
              ],
              "images": [
                  {
                      "alt": "SUPREME POUCH",
                      "src": "https://cdn.shopify.com/s/files/1/0588/3677/9194/products/ss18_supreme_tnf_pouch_blk_2-l_5fb1316e-22f7-4702-9953-57f3fbdda5be.jpg?v=1644047927",
                      "width": 800,
                      "height": 534,
                      "variant_ids": []
                  }
              ],
              "metafields": {
                  "product": {
                      "alias": "SEALLINE SEE POUCH SMALL",
                      "colorway": "BLACK",
                      "styleCode": "SS18A30 BLACK",
                      "yearOfRelease": 2018,
                      "searchColor": [
                          "black"
                      ]
                  }
              },
              "available": true,
              "price_range": {
                  "from": 30,
                  "to": 30
              }
          }
      ],
      "totalResults": 1000,
      "page": 1,
      "totalPages": 20,
      "facets": {
          "vendor": {
              "ADIDAS": 30,
              "JORDAN": 336,
              "NEW BALANCE": 15,
              "NIKE": 384,
              "REEBOK": 4,
              "SUPREME": 624,
              "VANS": 32
          }
      },
      "attributionToken": "01JRVX8M3N4P5Q6R7S8T9U0V1W",
      "_meta": {
          "appliedRules": [],
          "appliedSearchRules": [],
          "affinities": [
              {
                  "property": "vendor",
                  "operator": "=",
                  "value": "SUPREME",
                  "weight": 0.74
              }
          ]
      },
      "_workflow": [
          {
              "type": "affinity-boosts",
              "payload": [
                  {
                      "property": "vendor",
                      "operator": "eq",
                      "value": "SUPREME",
                      "weight": 0.74
                  }
              ]
          }
      ]
  }
  ```
</ResponseExample>
