Skip to main content

Search & Discovery

The SDK wraps Glood’s headless Search v1 APIs so you can build a fully custom search experience — instant (type-ahead) search, a full results page, faceted filters, and visual (image) search — rendering everything with your own React components.
Search is a v1 headless API on its own host (https://search.glood.ai), independent of the recommendations app’s version. Registering search() pins it to v1 automatically — you can run search (v1) and recommendations (v3) on the same client.

Setup

Register the search app on your Glood client, alongside (or instead of) recommendations:
Then wrap your app in <GloodProvider> (inside Shopify’s Analytics.Provider) exactly as for recommendations — see Installation.
Add https://search.glood.ai to your CSP connectSrc, or the browser blocks every search fetch and event. See Content Security Policy.

Session bootstrap

When search() is registered, GloodProvider fires the search init call once on mount — it resolves the visitor, loads their history (browsed / cart / purchased product ids), and returns a lean feature-flag config plus the storefront token and a fresh visit_id. You don’t wire this up: useSearch and useInstantSearch automatically wait for it to settle before firing. Read the result with useSearchInit() (or useSearchInitReady() for the settled flag):
For SSR / non-React use, call the standalone fetchSearchInit(options, params?) directly.

Loading the config

The config carries feature flags, filter definitions, the shop currency/locale, and the Shopify storefront token. Fetch it once (e.g. in a layout) with useSearchConfig:
useInstantSearch runs a type-ahead query and returns products, collections, pages, articles, keyword suggestions and autocorrect. On an empty / too-short query the response carries a trending block instead. Pass { skip } to hold fetching until the input clears the minimum length:
The products, suggestions, collections and pages return values are convenience accessors. The full response — including articles, autocorrect, trending and metadata — is on data.

Full search results

useSearch runs a full hybrid (text + vector) product search with applied facets, sort and page-based pagination. It also returns attribution helpers (see below):

Sort & pagination

sort accepts relevance (default), title_asc, title_desc, price_asc, price_desc, best_selling, oldest, newest. The response pagination block gives total, page, limit, total_pages, has_next_page/has_prev_page and next_page/prev_page.

Filters & aggregations

There are two facet endpoints, exposed via the SearchApp (or the standalone functions):
Render the definitions from filters() for stable labels/order, and merge in the live aggregations counts as the query/selection changes. Pass exactly one image source — a base64 image, a data: URL, or an http(s) URL:
Images are strictly validated server-side: jpeg / png / webp only, 1 KB–5 MB, 100×100 to 4096×4096 px. Anything else returns 400.
Image search always runs against the app’s controlEndpoint (the non-edge host), because the vision/embedding pipeline it needs isn’t available on regional edges. If you point endpoint at an edge, image search stays on the control plane automatically — see Configuration → Edge vs. non-edge routing.

Server-side (SSR)

To render search results in the initial HTML, call the standalone fetchers in a Hydrogen route loader. Pass credentials explicitly — there is no browser context on the server:
Every standalone fetcher (fetchSearchConfig, fetchInstantSearch, fetchFilters, fetchFilterAggregations, fetchSearchResults, fetchImageSearch, sendSearchEvent) takes (options, params) and is isomorphic.

Events & attribution

Two kinds of events flow to the search backend:
  1. Standard Shopify events (product_viewed, search_submitted, product_added_to_cart, …) are forwarded automatically by GloodProvider once search() is registered — no wiring required. Narrow them with search({ events: ['search_submitted', 'product_added_to_cart'] }).
  2. Custom glood:search:* attribution events, which only your UI can time, are sent via the track helpers:
The helpers are returned by useSearch and also live on the SearchApp (useGloodAnalytics().getApp('search')) for SSR / non-hook use. Each takes a SearchTrack (request_id, search_term, search_type, products, filters, source, page_type). For SSR / non-React contexts, send a single event directly with sendSearchEvent(options, event).
Both kinds of events are ingested at the app’s controlEndpoint (non-edge), not endpoint. This keeps event ingestion on the control plane even when endpoint points at a regional edge — see Configuration → Edge vs. non-edge routing.

Error handling

Fetchers throw (and the hooks surface via error) a GloodApiError carrying the HTTP status and response body:

See Also