Introduction
One query across your whole project - products, pages, blocks, forms, orders and more, grouped by entity type.
π― What does this module do?β
The Search module wraps the public cross-entity search endpoint. You pass a text query and get back every record whose name or attribute value matches it, from 18 entity types at once, grouped per type and annotated with how each record matched.
Use it to power a global "search everything" box - the kind that shows a few products, a couple of pages and a matching form in one dropdown - and then drill down into a single type when the user asks for more.
This is keyword search: it matches on the literal text of titles, identifiers, urls and attribute values. For meaning-based search (a query like "warm jacket for winter" matching a product named "Insulated parka"), use the semantic search of the individual modules - see Vector search vs global search below.
π Quickstartβ
Initialize the module from defineOneEntry:
const { Search } = defineOneEntry( "your-project-url", { "token": "your-app-token" });
Search everything, then walk the groups:
// Search every entity type for "winter".
const result = await Search.globalSearch('winter');
console.log(result.query); // "winter"
result.groups.forEach((group) => {
console.log(group.type, group.items.length, group.hasMore);
group.items.forEach((item) => {
console.log(item.id, item.title, item.matchKind, item.fragment);
});
});
β¨ Key Conceptsβ
Groupsβ
The response is not a flat list. It is { query, groups }, where every group holds the records of one entity type:
{
query: "winter",
groups: [
{ type: "products", items: [ /* β¦ */ ], hasMore: false },
{ type: "pages", items: [ /* β¦ */ ], hasMore: false }
]
}
hasMore tells you whether more records of that type exist beyond the returned page - the cue to offer a "show all products" link that re-runs the query in drilldown mode.
Match contextβ
Every item carries the context of how it matched, so you can render a meaningful result row instead of a bare title:
| Field | What it tells you |
|---|---|
matchKind | Ranking kind of the match: exact, title, attributeName or attributeValue |
matchedField | The concrete field that matched: id, title, identifier, url, attributeName, attributeValue, importId, nodeName |
matchedAttribute | The attribute the match happened in (when the match came from an attribute) |
fragment | Plain-text context around the match, with no markup - highlight it yourself |
langCode | Language of the matched value, so you can label cross-language hits |
parent | The owning record for entities that have no page of their own (a slide β its block, an order β its storage) |
Entity typesβ
types narrows the search. Pass any of these, and the SDK sends them comma-separated:
products, pages, blocks, slides, templates, discounts, user_groups, users, admins, menus, forms, attributes_sets, attributes, orders, workflows, events, subscriptions, collections.
Omit types to search all of them.
Drilldown modeβ
offset and limit switch the endpoint into drilldown mode - paging through one entity type instead of previewing all of them.
β οΈ They are accepted only together with exactly one accessible type in
types. Any other combination answers 400 - Drilldown mode (limit/offset) requires exactly one accessible type intypes.
The SDK does not default them: omit both and every group comes back in full.
// Overview: every type, every group complete.
const overview = await Search.globalSearch('winter');
// Drilldown: page 1 of the products only.
const products = await Search.globalSearch('winter', ['products'], 'visible', 0, 20);
Visibilityβ
visibility filters the searched records: 'all' (default), 'visible' or 'hidden'.
π What You Need to Knowβ
idis a number for most types, a string for workflows and attributes -number | string, so don't assume numeric ids when building keys or urls.titleis optional: records with no name of their own (orders, users without a login) come back without it. Fall back toidentifierorsubtitle.subtitlecarries the secondary line the type happens to have - a page url, an order storage, a node name.attributeSetIdis present only fortype: "attributes", pointing at the set the attribute belongs to.- Only records the current caller may see are returned; the search respects the same access rules as the rest of the API.
π Quick Reference Tableβ
| Method | Description |
|---|---|
| globalSearch() | Search names and attribute values across all entity types |
Vector search vs global searchβ
Both find records from a text query, but they answer different questions:
| globalSearch | getβ¦ByVectorSearch | |
|---|---|---|
| Matches on | The literal text of titles, identifiers, urls and attribute values | Meaning - a semantic (vector) similarity |
| Scope | 18 entity types in one call | One module per call |
| Returns | { query, groups[] } - grouped by type | { items, total } - a flat container |
| Typical use | A global search box / command palette | "Find me something like this" over one entity |
The semantic counterparts live in the modules themselves: products, pages, users, orders, discounts, admins and form data.
β Common Questions (FAQ)β
Why is my offset / limit answered with a 400?β
Because they only work in drilldown mode. Pass exactly one accessible entity type in types alongside them, or drop them entirely.
How do I highlight the match in the UI?β
Use fragment - it is the plain-text context around the match, deliberately free of markup, so you can highlight the query in it yourself without sanitizing anything.
An item has no title. Is that a bug?β
No. Orders and users without a login have no own name, so title is simply absent. Render identifier, subtitle or a type-specific label instead.
Can I search hidden records?β
Pass visibility: 'hidden' (or 'all') - subject to the access rules that apply to the caller.
π Best Practicesβ
- Debounce the query in a search-as-you-type box: every keystroke is a request.
- Show the overview call first (no
offset/limit), then switch to drilldown when the user picks a type - that is exactly whathasMoreis for. - Narrow
typesto what your UI can actually render; searching 18 types to display 2 is wasted work. - Treat
idasnumber | stringwhen building links and React keys.
π Related Documentationβ
- Products Module - Semantic product search and the product catalog
- Pages Module - Pages returned in the
pagesgroup - Filters Module - Curated filter trees for faceted navigation