Skip to main content

Overview

This is the SDK equivalent of Implementing search in Liquid. The same four moving pieces apply: autocomplete, prepare, get, facets, and sort orders. Each is exposed as an SDK controller. The SDK handles request deduplication, the search_id lifecycle, abort signals, and reactive state for you. Use this version when you have already installed @commerce-blocks/sdk in your theme. For a no-dependencies version, see the Liquid + Fetch guide.

Prerequisites

  • The Layers Shopify app installed and synced.
  • The SDK installed and initialized. See the installation guide.
  • The Storefront Pixel installed so device and session identifiers are populated automatically.

Controllers used

All expose the same reactive state and subscribe() shape as the collection controller.

1. Autocomplete in the header

autocomplete() fetches suggestions and supports semantic redirects. When a typed query matches a semantic redirect, data._meta.redirect.url is populated and you should navigate the shopper directly.
The controller handles abort and deduplication internally. No manual AbortController plumbing is required.

2. Prepare the search before the results page

prepare() is a first-class method on sdk.search(). Call it the moment a shopper commits to a search. The SDK kicks off the request, caches the resulting search_id against the query, and get() automatically reuses it on the next page. Option A - Prepare on submit. Best when you can intercept the form submit so prepare keeps running during navigation.
Option B - Prepare on the search results page. Simpler, but loses the in-flight head start.
Do not await prepare() on the critical path. It returns a result the SDK can keep working on in the background while you render the next page.

3. Get the search results

On the search results page, get() reuses the prepared search_id automatically. You do not need to pass it unless you are sharing it across pages via the URL. The SDK falls back to standard processing if the prepare cache has expired or no prepare ran.
A simple readActiveFiltersFromUrl helper builds a filter group from URL parameters. Replace the attribute names with the codes configured in your Layers dashboard:
Controller options merge across calls, so subsequent interactions only pass what is changing:

4. Render facet and sort controls at runtime

In v3, sort orders and facets are not configured at SDK init. Fetch them at runtime with sdk.sortOrders() and sdk.facets().
You can also request filtered facet counts by passing the active filterGroup:
The end-to-end timeline:
1

Header submit

Shopper hits enter. Create a search controller and call search.prepare() (non-blocking), then navigate to /search?q=.... The SDK persists the resulting search_id so the next page can use it.
2

Results page render

Render the sort dropdown and empty facet groups from sdk.sortOrders() and sdk.facets(), including the active sort/filter state from the URL.
3

Get results

Page JS calls search.get({ query, sort, filterGroup, pagination, searchId }). The SDK reuses the prepared search_id automatically. The subscriber renders the grid, facets, and pagination as soon as data lands.
4

Interaction

On sort change or filter toggle, call search.get({ ... }) with just the changed fields. Mirror the state to the URL via history.replaceState.

Why the SDK over Fetch

Troubleshooting

Suggestions show but redirects do not fire. The redirect lives at data._meta.redirect.url on the autocomplete state. Make sure your subscriber checks for it before rendering the suggestion list. get() is slow on the results page. Prepare was not called, or the cache has expired. The SDK falls back to normal processing. Confirm prepare runs before navigation. Filters do not apply. Attribute codes in filterGroup must exactly match the codes configured as facets in Layers. Fetch sdk.facets() to verify the codes.

See also