> ## 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.

# Rendering sort orders in Liquid

> Render Layers sort order dropdowns in a Shopify theme using Liquid metaobjects, scope and default-sort rules, and the Browse and Search APIs.

## Overview

Layers sort order metaobjects describe the sort options configured in your dashboard — their display name, code, and which surfaces they apply to. To render a working sort dropdown, combine the two data sources:

1. Read sort order metaobjects in Liquid to get the configured sorts and their codes.
2. Filter by `scope` (`collection` or `search`) so each surface only shows the relevant options.
3. Pass the selected `code` to the [Browse API](/api-reference/browse) or [Search API](/api-reference/search) as `sort_order_code`.

This keeps the dropdown in sync with merchandising — sorts enabled, hidden, renamed, or reordered in the Layers dashboard update on the storefront with no theme deploy.

## Prerequisites

* The Layers Shopify app installed and synced.
* Sort orders configured in the Layers dashboard with **Enable as Storefront Sort** turned on.
* A storefront access token (available via `shop.metafields.layers.embed_settings`). See [Liquid integration](/developers/liquid-integration) for full setup.

## Collection sort dropdown

<Steps>
  <Step title="Read and filter sort metaobjects in Liquid">
    Each sort metaobject exposes `name`, `code`, `scope` (an array like `['collection', 'search']`), and `order` (display priority). Filter by scope so collection pages only render collection sorts, then order by the configured `order` field.

    Also read the collection's default sort from the `layers.default_sort_order` metafield — used to pre-select the dropdown when no `sort` query param is present.

    ```liquid theme={null}
    {% assign layers_sorts = shop.metaobjects['app--278936322049--sort_order'] | sort: 'order' %}

    {% assign default_sort_code = nil %}
    {% if collection.metafields.layers.default_sort_order %}
      {% assign default_sort_code = collection.metafields.layers.default_sort_order.value.code.value %}
    {% endif %}

    {% assign active_sort_code = request.params.sort | default: default_sort_code %}

    <label for="sort-order">Sort by</label>
    <select
      id="sort-order"
      name="sort"
      data-collection="{{ collection.handle }}"
      data-default-sort="{{ default_sort_code }}"
    >
      {% for sort in layers_sorts %}
        {% assign scopes = sort.scope.value %}
        {% if scopes contains 'collection' %}
          <option
            value="{{ sort.code.value }}"
            {% if sort.code.value == active_sort_code %}selected{% endif %}
          >
            {{ sort.name.value }}
          </option>
        {% endif %}
      {% endfor %}
    </select>
    ```
  </Step>

  <Step title="Pass the selected code to the Browse API">
    When the dropdown changes, request the new page from the [Browse API](/api-reference/browse) with the selected `sort_order_code`. Omit the field to fall back to the collection's default sort order.

    ```js theme={null}
    const select = document.querySelector('#sort-order')
    const collectionHandle = select.dataset.collection

    async function loadPage(sortCode, page = 1) {
      const response = await fetch(
        `https://app.uselayers.com/storefront/v1/browse/${collectionHandle}`,
        {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            'X-Storefront-Access-Token': window.layersConfig.storefrontApiToken,
          },
          body: JSON.stringify({
            // Omit sort_order_code to use the collection's default
            ...(sortCode ? { sort_order_code: sortCode } : {}),
            pagination: { page, limit: 24 },
          }),
        }
      )

      return response.json()
    }

    select.addEventListener('change', async (event) => {
      const sortCode = event.target.value
      const data = await loadPage(sortCode)
      renderGrid(data.results)

      // Reflect the selection in the URL so it survives refresh and back navigation
      const url = new URL(window.location.href)
      url.searchParams.set('sort', sortCode)
      window.history.replaceState({}, '', url)
    })
    ```
  </Step>
</Steps>

## Search sort dropdown

The pattern is identical — filter by the `search` scope and pass `sort_order_code` to the [Search API](/api-reference/search) `execute` endpoint instead.

```liquid theme={null}
{% assign layers_sorts = shop.metaobjects['app--278936322049--sort_order'] | sort: 'order' %}

<select id="search-sort" name="sort">
  <option value="">Relevance</option>
  {% for sort in layers_sorts %}
    {% assign scopes = sort.scope.value %}
    {% if scopes contains 'search' %}
      <option value="{{ sort.code.value }}">{{ sort.name.value }}</option>
    {% endif %}
  {% endfor %}
</select>
```

```js theme={null}
const query = new URLSearchParams(window.location.search).get('q') ?? ''

await fetch(
  `https://app.uselayers.com/storefront/v1/search/${encodeURIComponent(query)}/execute`,
  {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-Storefront-Access-Token': window.layersConfig.storefrontApiToken,
    },
    body: JSON.stringify({
      sort_order_code: sortCode || undefined,
      pagination: { page: 1, limit: 24 },
    }),
  }
)
```

<Tip>
  Leave the first option blank (or label it "Relevance") on search pages. Omitting `sort_order_code` lets the Layers ranking pipeline order by relevance — usually what shoppers want for a query.
</Tip>

## Default sort orders

Default sorts are resolved on the **server** when `sort_order_code` is omitted:

| Surface    | Default source                                                                             |
| :--------- | :----------------------------------------------------------------------------------------- |
| Collection | `layers.default_sort_order` metafield on the collection, falling back to the store default |
| Search     | Relevance                                                                                  |

Read the collection's default in Liquid (as shown above) so the dropdown reflects what the API will use. Don't hard-code a default sort code in the theme — it will drift from the dashboard.

## Available fields

| Field   | Type    | Description                                                  |
| :------ | :------ | :----------------------------------------------------------- |
| `name`  | string  | Display label                                                |
| `code`  | string  | Sort order code passed as `sort_order_code`                  |
| `scope` | array   | Surfaces where the sort is available: `collection`, `search` |
| `order` | integer | Display order — lower numbers appear first                   |

## Preserving sort across navigation

To keep the active sort sticky across pagination, filtering, and back/forward navigation:

* Mirror the selection to the URL (`?sort=<code>`) on change.
* Read `request.params.sort` in Liquid on the initial render so the right option is `selected` server-side.
* Include `sort_order_code` in every subsequent API call (Browse, Facets, applied-filter refreshes) until the user changes it.

## Troubleshooting

**Sort options are missing from the dropdown.** Confirm **Enable as Storefront Sort** is turned on for the sort order in the Layers dashboard, and that the metaobject is visible under **Content → Metaobjects** in Shopify admin.

**A sort renders on the wrong surface.** Check the sort's `scope` array in the dashboard — collection-only sorts should not include `search` and vice versa.

**The default sort doesn't match the dashboard.** Verify a default is assigned on the collection (Shopify admin → **Products → Collections → \[Collection] → Metafields → `layers.default_sort_order`**) and that the referenced sort still exists in Layers.

## See also

* [Liquid integration](/developers/liquid-integration) — reading metaobjects from Liquid
* [Rendering facets in Liquid](/developers/rendering-facets-in-liquid) — companion guide for filter sidebars
* [Browse API](/api-reference/browse) — collection results with sorting
* [Search API](/api-reference/search) — product search with sorting
* [Sort Orders](/platform/sorting) — configuring sort orders in the Layers dashboard
