AACSearch / guide
Widget
Embed search, recommendations and the AI assistant on any site with one script tag from the CDN.
The widget is a set of custom elements served from the CDN. Put a script tag
and an element on the page — no build step, no framework, and a new release
reaches your site without a redeploy on your side. For a React app, use the
aacsearch-ui package instead.
The one rule: a search key, against our API
The browser talks only to the tenant API (https://api.aacsearch.com/v1)
and only with a search-scoped key:
- A search key can search, recommend, send events and use the visitor-facing AI
operations. It cannot write documents or read configuration — anything else
answers
403— so the worst a key copied out of your page can do is search. Keys and scopes lists what it reaches. - A full key never goes in a page. It would give every visitor the right to change or delete your catalogue.
- The browser never calls the search engine directly. Tenant isolation, key restrictions, quotas, search rules and analytics are all applied by the API, so a request that skips it skips every one of them.
Two ways to get a search key:
| Key | Where it comes from | When to use it |
|---|---|---|
| Search key | Organization → Settings → API keys in the console, scope search. Optional restrictions: allowed collections, allowed origins, a forced filter_by, allowed fields, a per-key rate limit. | A public storefront — the simplest option. |
Browser key (nssk_…) | Minted by your server with createBrowserKey (POST /browser-keys) from a full key. Search scope, narrowed to the collections and origins you pass, expires by itself (at most seven days). | Pages rendered per visitor, or when you want every copied key to expire. |
const { key, expires_at } = await client.browserKeys.createBrowserKey({
expires_in_seconds: 86400,
allowed_collections: ["products"],
allowed_origins: ["https://shop.example.com"],
});
// render `key` into the page as the widget's api-keyRevoking or rotating the parent full key invalidates every browser key derived from it.
Search: aac-search.js
The lightweight widget — autocomplete and a full results page in one element, rendered in a shadow root so the store's CSS cannot restyle it.
<script type="module" src="https://cdn.aacsearch.com/aac-search.js"></script>
<aac-search
api-url="https://api.aacsearch.com/v1"
api-key="SEARCH_KEY"
collection="products"
query-by="name,brand"
facet-by="brand,category"
fields='{"title":"name","subtitle":"brand","price":"price","url":"url","image":"image"}'
locale="ru"
currency="RUB"
></aac-search>A missing required attribute is named on the page instead of failing silently.
Prop
Type
A recommendations block from the same bundle:
<aacsearch-recommendations
api-url="https://api.aacsearch.com/v1"
api-key="SEARCH_KEY"
collection="products"
model-id="similar"
object-id="42"
k="6"
title="Similar products"
></aacsearch-recommendations>model-id is required; object-ids (the cart), exclude-ids, filter-by,
fields, locale and currency are optional. The pre-rename tag
<nova-recommendations> keeps working.
Theming
Style the widget with CSS custom properties on the element or any ancestor — they are the one thing that crosses the shadow boundary:
aac-search {
--nova-accent: #0f766e;
--nova-radius: 12px;
--nova-font: "Inter", system-ui, sans-serif;
}Also available: --nova-surface, --nova-text, --nova-border,
--nova-hover, --nova-mark.
Search with the AI assistant: aacsearch-ui.js
Load one bundle per page: both register <aacsearch-recommendations>, and
whichever loads first owns the tag.
The full experience — search page, AI assistant, support chat and
recommendations — as custom elements. Its stylesheet is loaded automatically
from the script's own URL (override it with styles-url).
<script type="module" src="https://cdn.aacsearch.com/aacsearch-ui.js"></script>
<aacsearch-app
api-url="https://api.aacsearch.com/v1"
api-key="SEARCH_KEY"
collection="products"
query-by="name,brand"
facets="brand,category"
price-field="price"
lang="ru"
currency="RUB"
assistant-id="asst_…"
></aacsearch-app>
<aacsearch-chat
api-url="https://api.aacsearch.com/v1"
api-key="SEARCH_KEY"
collection="products"
query-by="name,brand"
assistant-id="asst_…"
></aacsearch-chat>
<aacsearch-recommendations
api-url="https://api.aacsearch.com/v1"
api-key="SEARCH_KEY"
collection="products"
query-by="name"
kind="trending"
></aacsearch-recommendations>All three elements require api-url, api-key, collection and query-by;
<aacsearch-chat> also requires assistant-id (create the assistant in the
console). Instead of separate attributes you can pass the whole configuration
as JSON in config="{…}".
| Attribute | Meaning |
|---|---|
facets, facet-labels, category-levels | Facet fields, labels, hierarchical category levels. |
price-field, rating-field, in-stock-field | Fields the product cards and range filters use. |
lang (or locale), currency | Interface language (ru and en built in) and price formatting. |
sort, hits-per-page, placeholder | Sort choices, page-size choices, search field placeholder. |
trending-model, similar-model, personal-model | Recommendation model ids for the result page blocks. |
assistant-id, assistant-title, assistant-suggestions | The support assistant and its suggestion chips. |
voice="off", voice-language | Voice input (on by default). |
vector-field, semantic-field, geo-field | Photo search, semantic fallback, geo search. |
user-id, analytics="off", analytics-tag | Personalization and analytics. |
kind, model-id, object-id, layout | On <aacsearch-recommendations>: model, for-you, recently-viewed or trending; layout="grid" instead of a carousel. |
Report conversions from cart and checkout pages, with the same connection settings the elements use:
const config = { apiUrl: "https://api.aacsearch.com/v1", apiKey: "SEARCH_KEY", collection: "products", queryBy: "name,brand" };
window.AACSearchUI.track(config, { type: "purchase", value: 12990, currency: "RUB", objects: [{ id: "42", price: 12990, quantity: 1 }] });What the widget sends
X-NOVA-API-KEY— the search key fromapi-key.X-NOVA-SESSION-ID— one id per browser tab, generated for you. It ties a visitor's searches, clicks and purchases together for analytics and A/B tests and is what the per-session AI allowance is counted against.
The assistant, voice input, photo search and the semantic fallback are paid in credits; when the wallet runs out, search keeps working and the assistant reports it is unavailable. See keys, scopes and credits.
Next
- SEO landing pages — the pages a crawler can find, next to the search box.
- Storefront UI — the React and plain-HTML packages.
A/B experiments
Split search and recommendation traffic between variants per session, measure them with events, get notified when a winner is detected, and promote or roll back the winner.
Storefront UI (aacsearch-ui)
Search page, autocomplete, ⌘K palette, support chat, voice, photo search and recommendations — in React or on any HTML page.