Predictive search

As-you-type search suggestions: the /search/suggest endpoint, its response shape, and how to build the dropdown.

Predictive search#

Themes get as-you-type search suggestions from one JSON endpoint. It reads the same channel-scoped index as the search page — every word in the query must match, the last one matches as a prefix, and the store's synonyms apply — so the dropdown and the results page never disagree.

The endpoint#

http
GET /search/suggest?q=<query>

Same-origin, no token, GET only. Queries under 2 characters return empty groups. When the merchant has search disabled the endpoint returns 404 — hide the search UI when the search page itself is off.

Response#

json
{
  "query": "vanta",
  "groups": [
    {
      "type": "product",
      "total": 5,
      "items": [
        {
          "title": "Vantage Aero 11 Tablet",
          "url": "/products/vantage-aero-11-tablet",
          "image": "https://…/….w160.webp"
        }
      ]
    }
  ],
  "search_url": "/search?q=vanta"
}

Groups arrive in the store's enabled result-type order (product, collection, category, page, policy, blog_post, blog_category, vendor, brand), each capped at 5 items with the group's true total alongside. Every url is permalink-correct for the storefront — render it as-is, never rebuild routes client-side. image is present only when the resource has one: a small cached CDN variant sized for a dropdown row. search_url is the full results page for the query — use it for a "see all results" row.

Building the dropdown#

Debounce input (200–300ms) and drop out-of-order responses — keep a request sequence number and ignore any response older than the latest. Render titles as text nodes, not injected HTML. Close on Escape and on clicks outside the panel. On small screens let the field take the full header row while open.

The LINEN skeleton's header ships this wired end to end — an icon-triggered field in pill headers, or suggestions under the always-visible field — so themes forked from it inherit predictive search without writing any of the above. Headless storefronts use the searchSuggest GraphQL query, which returns the same grouped shape.