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:<GloodProvider> (inside Shopify’s Analytics.Provider) exactly as
for recommendations — see Installation.
Session bootstrap
Whensearch() 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):
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) withuseSearchConfig:
Instant (type-ahead) search
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 theSearchApp (or the standalone functions):
filters() for stable labels/order, and merge in the live
aggregations counts as the query/selection changes.
Image (visual) search
Pass exactly one image source — a base64 image, adata: 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:fetchSearchConfig, fetchInstantSearch, fetchFilters,
fetchFilterAggregations, fetchSearchResults, fetchImageSearch, sendSearchEvent) takes
(options, params) and is isomorphic.
Events & attribution
Two kinds of events flow to the search backend:- Standard Shopify events (
product_viewed,search_submitted,product_added_to_cart, …) are forwarded automatically byGloodProvideroncesearch()is registered — no wiring required. Narrow them withsearch({ events: ['search_submitted', 'product_added_to_cart'] }). - 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 viaerror) a GloodApiError carrying the HTTP status
and response body:
See Also
- Search API Reference — full signatures, parameters, returns
- Search Example — complete working route
- Event System — how events are transmitted
- Content Security Policy — required CSP entries