# Initialize Source: https://docs.hibonsai.com/project/api-reference/mcp-server/initialize Initialize the MCP connection ## `initialize` Initialize the MCP connection. ## Parameters The MCP protocol version. Use `"2025-03-26"` for the current version. Client capabilities object. Can be empty `{}` if no specific capabilities are required. Information about the client application. Name of the client application. Version of the client application. ## Request ```json theme={null} { "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "protocolVersion": "2025-03-26", "capabilities": {}, "clientInfo": { "name": "client-name", "version": "1.0.0" } } } ``` ## Response ```json theme={null} { "jsonrpc": "2.0", "id": 1, "result": { "protocolVersion": "2025-03-26", "capabilities": {}, "serverInfo": { "name": "bonsai-mcp", "version": "1.0.0" } } } ``` # MCP Source: https://docs.hibonsai.com/project/api-reference/mcp-server/main-endpoint GET and POST methods for the MCP endpoint ## GET /mcp ```http theme={null} GET /mcp ``` Server-Sent Events (SSE) initialization. ## POST /mcp ```http theme={null} POST /mcp ``` JSON-RPC message handling. # Messages Source: https://docs.hibonsai.com/project/api-reference/mcp-server/messages-endpoint GET and POST methods for the MCP messages endpoint ## GET /mcp/messages ```http theme={null} GET /mcp/messages ``` Session initialization for message stream handling. ## POST /mcp/messages ```http theme={null} POST /mcp/messages ``` Session-based MCP JSON-RPC message handling. # MCP Server Overview Source: https://docs.hibonsai.com/project/api-reference/mcp-server/overview Model Context Protocol reference for ChatGPT Apps SDK integration ## Overview The Model Context Protocol (MCP) server enables integration with ChatGPT Apps SDK, allowing ChatGPT to search your product catalog and interact with your offerings. ## Base URL ```http theme={null} https://api.hibonsai.com/mcp ``` ## Protocol Version The MCP server implements protocol version: `2025-03-26` ## Authentication MCP requests require authentication via API key in the `X-API-Key` header: ```http theme={null} X-API-Key: YOUR_API_KEY_HERE ``` Keep API keys server-side only. Do not expose keys in browser client code. ## Endpoints ### Main MCP Endpoint ```http theme={null} GET /mcp ``` Server-Sent Events (SSE) initialization. ```http theme={null} POST /mcp ``` JSON-RPC message handling. ### Messages Endpoint ```http theme={null} GET /mcp/messages ``` Session initialization for message stream handling. ```http theme={null} POST /mcp/messages ``` Session-based MCP JSON-RPC message handling. ### Organization-Specific Endpoint ```http theme={null} GET /mcp/org/{organization_id}/ ``` Organization-specific MCP endpoint that uses the organization ID from the URL path. ```http theme={null} POST /mcp/org/{organization_id}/ ``` `GET /mcp` and `POST /mcp`. `GET /mcp/messages` and `POST /mcp/messages`. `GET /mcp/org/{organization_id}/` and `POST /mcp/org/{organization_id}/`. ## JSON-RPC Methods The MCP server implements the following JSON-RPC 2.0 methods: Initialize the MCP connection. List available tools. Execute a tool. List available resources. Read a resource by URI. ## Available Tools The MCP server provides the following tools: Search for products and offerings using natural language queries. **Input:** * `question` (string, required): The search query or question **Output:** * Returns search results with products and structured content for widget rendering List all available offerings without a search query. **Input:** None **Output:** * Returns all available products Get a booking link for services or appointments. **Input:** * `offering_id` (string, required): The ID of the offering **Output:** * Returns booking URL Get a direct link to a product. **Input:** * `product_id` (string, required): The product ID **Output:** * Returns product URL Initiate express checkout for a single product. **Input:** * `product_id` (string, required): The product ID **Output:** * Returns checkout information ## CORS Support The MCP server supports CORS (Cross-Origin Resource Sharing) with the following headers: * `Access-Control-Allow-Origin: *` * `Access-Control-Allow-Methods: GET, POST, OPTIONS` * `Access-Control-Allow-Headers: Content-Type, Accept, MCP-Protocol-Version, X-API-Key, Origin` ## Error Handling MCP endpoints return JSON-RPC 2.0 error objects: ```json theme={null} { "jsonrpc": "2.0", "id": 1, "error": { "code": -32603, "message": "Internal error", "data": {} } } ``` **Common JSON-RPC error codes:** * `-32700`: Parse error * `-32600`: Invalid Request * `-32601`: Method not found * `-32602`: Invalid params * `-32603`: Internal error * `-32000` to `-32099`: Server-defined errors ## Rate Limiting API requests are rate limited per organization. If you exceed your rate limit, you'll receive a `429 Too Many Requests` response. Rate limits are configured per customer account. Contact your Customer Success Manager (CSM) for information about your account's rate limits. ## Support For API support, integration assistance, or to request additional features, contact your Customer Success Manager. # List Resources Source: https://docs.hibonsai.com/project/api-reference/mcp-server/resources-list List available resources ## `resources/list` List available resources such as widgets and UI components. Resources use URIs with the format `ui://widget/{widget-name}.html`. Use the `resources/read` method to retrieve the actual content of a resource. ## Request ```json theme={null} { "jsonrpc": "2.0", "id": 4, "method": "resources/list", "params": {} } ``` ## Response ```json theme={null} { "jsonrpc": "2.0", "id": 4, "result": { "resources": [ { "uri": "ui://widget/kitchen-sink-lite.html", "name": "Kitchen Sink Lite Widget", "description": "Demo widget for testing ChatGPT Apps SDK capabilities", "mimeType": "text/html+skybridge" }, { "uri": "ui://widget/shop-widget.html", "name": "Shop Widget", "description": "Flexible widget for displaying shop offerings with configurable UI", "mimeType": "text/html+skybridge" } ] } } ``` # Read Resources Source: https://docs.hibonsai.com/project/api-reference/mcp-server/resources-read Read a resource by URI ## `resources/read` Read a resource by URI. ## Parameters URI of the resource to read. Use the format `ui://widget/{widget-name}.html` for widget resources. Available URIs can be retrieved using `resources/list`. ## Request ```json theme={null} { "jsonrpc": "2.0", "id": 5, "method": "resources/read", "params": { "uri": "ui://widget/shop-widget.html" } } ``` ## Response Returns the resource content (HTML for widgets). # Call Tool Source: https://docs.hibonsai.com/project/api-reference/mcp-server/tools-call Execute a tool ## `tools/call` Execute a tool. This endpoint requires authentication. Ensure you have initialized the MCP connection before calling this method. ## Parameters Name of the tool to execute. Use `tools/list` to retrieve available tool names. Arguments to pass to the tool. The structure depends on the tool's `inputSchema`. For `search_offerings`, pass a `question` string containing the search query. ## Request ```json theme={null} { "jsonrpc": "2.0", "id": 3, "method": "tools/call", "params": { "name": "search_offerings", "arguments": { "question": "What humidifiers do you have?" } } } ``` ## Response ```json theme={null} { "jsonrpc": "2.0", "id": 3, "result": { "content": [ { "type": "text", "text": "Found 5 offerings for: What humidifiers do you have?" } ], "structuredContent": { "view": "search_results", "data": { "products": [...], "search_query": "What humidifiers do you have?", "count": 5 } } } } ``` The `view` field in `structuredContent` specifies the UI view type for rendering the results. The `data` object contains the actual search results and metadata. # Tools List Source: https://docs.hibonsai.com/project/api-reference/mcp-server/tools-list List available tools ## `tools/list` List available tools. This endpoint requires authentication. Ensure you have initialized the MCP connection before calling this method. ## Request ```json theme={null} { "jsonrpc": "2.0", "id": 2, "method": "tools/list", "params": {} } ``` ## Response ```json theme={null} { "jsonrpc": "2.0", "id": 2, "result": { "tools": [ { "name": "search_offerings", "description": "Search the available offerings, services, and products", "inputSchema": { "type": "object", "properties": { "question": { "type": "string", "description": "The search query or question about offerings to explore" } }, "required": ["question"] } } ] } } ``` # Overview Source: https://docs.hibonsai.com/project/api-reference/overview Entry point for Bonsai REST API and MCP server references REST API endpoints for search, organizations, hits, and AI landing pages. Model Context Protocol (MCP) server (for example, ChatGPT Apps SDK) # AI Landing Page Source: https://docs.hibonsai.com/project/api-reference/rest-api/ai-landing GET https://api.hibonsai.com/rest/org/ai/{organization_id}/ Retrieve AI-optimized landing page content for an organization ## Endpoint `GET /rest/org/ai/{organization_id}/` ## Path Parameters Organization identifier. ## Query Parameters Force regeneration of cached content when `true`. ```bash cURL theme={null} curl -X GET "https://api.hibonsai.com/rest/org/ai/{organization_id}/" \ -H "X-API-Key: YOUR_API_KEY_HERE" ``` ## Response Returns markdown-formatted content optimized for AI consumption. # Hits Source: https://docs.hibonsai.com/project/api-reference/rest-api/hits POST https://api.hibonsai.com/rest/hits/ Track search hits and user interaction events ## Endpoint `POST /rest/hits/` ## Request Body Parameters Organization UUID associated with the event. ISO 8601 event timestamp. Event classification (for example, `search`). HTTP method of the request (for example, `GET`, `POST`). Request path (for example, `/search`). Full URL of the request including query parameters. User agent string from the request header. IP address of the client making the request. Bot detection score between 0 and 1. Higher values indicate greater likelihood of bot traffic. Whether the request is from a verified bot (for example, search engine crawlers). Request headers object. Cloudflare-specific metadata object. ```bash cURL theme={null} curl -X POST "https://api.hibonsai.com/rest/hits/" \ -H "X-API-Key: YOUR_API_KEY_HERE" \ -H "Content-Type: application/json" \ -d '{"organization":"organization-uuid","eventDate":"2024-01-01T00:00:00Z","classification":"search"}' ``` ```json Request body theme={null} { "organization": "organization-uuid", "eventDate": "2024-01-01T00:00:00Z", "method": "GET", "path": "/search", "url": "https://example.com/search?q=query", "userAgent": "Mozilla/5.0...", "classification": "search", "clientIp": "192.168.1.1", "botScore": 0.95, "verifiedBot": false, "headers": {}, "cf": {} } ``` ## Response Returns the created hit record with `id`, `createdAt`, and `updatedAt` fields. # REST API Overview Source: https://docs.hibonsai.com/project/api-reference/rest-api/overview Complete REST API endpoint reference for search, organizations, hits, and AI landing pages ## Overview The Bonsai REST API provides endpoints for search, analytics tracking, and AI-generated landing content. ## Authentication Include your API key in the `X-API-Key` header: ```http theme={null} X-API-Key: YOUR_API_KEY_HERE ``` Keep API keys server-side only. Do not expose keys in browser client code. For the API playground "Try it" input, enter your API key in the bearer token field. ## Base URL ```http theme={null} https://api.hibonsai.com/rest/ ``` ## Endpoint Directory Enhanced search endpoint recommended for new integrations. Original search endpoint for product and context queries. Track search and interaction events. Retrieve AI-generated landing content for an organization. ## Search Versions Both search versions support the same core query pattern. Use v3 for new implementations. | Version | Path | Use case | | ------- | ------------------ | ----------------------------------------------------------- | | v3 | `/rest/search/v3/` | Recommended default for new integrations | | v2 | `/rest/search/v2/` | Existing integrations on the original search implementation | ## Error Handling REST endpoints return standard HTTP status codes with JSON error bodies: ```json theme={null} { "error": "Error message", "details": {} } ``` **Common HTTP status codes:** * `200 OK`: Request succeeded * `400 Bad Request`: Invalid parameters or malformed request * `401 Unauthorized`: Missing or invalid API key * `404 Not Found`: Resource not found * `429 Too Many Requests`: Rate limit exceeded * `500 Internal Server Error`: Server error ## Rate Limiting API requests are rate limited per organization. If you exceed your rate limit, you'll receive a `429 Too Many Requests` response. Rate limits are configured per customer account. Contact your Customer Success Manager (CSM) for information about your account's rate limits. ## Support For API support, integration assistance, or feature requests, contact your Customer Success Manager. # Search v2 Source: https://docs.hibonsai.com/project/api-reference/rest-api/search-v2 GET https://api.hibonsai.com/rest/search/v2/ Search products and contexts using the v2 endpoint ## Endpoint `GET /rest/search/v2/` `GET /rest/search/v2/{shop_id}/` ## Query Parameters Search query string. Filter to one or more shops. Return only products when `true`. Skip LLM scoring when `true`. ```bash cURL theme={null} curl -X GET "https://api.hibonsai.com/rest/search/v2/?q=humidifier" \ -H "X-API-Key: YOUR_API_KEY_HERE" ``` ```bash cURL (multiple shops) theme={null} curl -X GET "https://api.hibonsai.com/rest/search/v2/?q=humidifier&shop_id=shop-1&shop_id=shop-2" \ -H "X-API-Key: YOUR_API_KEY_HERE" ``` ```json Response theme={null} { "results": [ { "id": "product-uuid", "type": "product", "name": "Product Name", "description": "Product description", "image": "https://example.com/image.jpg", "images": ["https://example.com/image1.jpg"], "slug": "product-slug", "publicUrl": "https://example.com/products/product-slug", "publishedAt": "2024-01-01T00:00:00Z", "vendor": "Vendor Name", "tags": ["tag1", "tag2"], "productType": "Product Type", "price": "99.99", "compareAtPrice": "129.99" }, { "id": "context-uuid", "type": "context", "name": "Shop Context Name", "description": "Context description", "image": null, "images": [], "slug": null, "publicUrl": "https://example.com/context", "publishedAt": "2024-01-01T00:00:00Z", "vendor": null, "tags": [], "productType": null, "price": null, "compareAtPrice": null } ], "count": 2 } ``` ## Response Fields | Field | Type | Description | | -------------------------- | ------------ | --------------------------------------- | | `results` | array | Array of search results | | `results[].id` | string | Unique identifier (UUID) | | `results[].type` | string | Result type: `"product"` or `"context"` | | `results[].name` | string | Product or context name | | `results[].description` | string | Description text | | `results[].image` | string\|null | Primary image URL | | `results[].images` | array | Array of image URLs | | `results[].slug` | string\|null | URL-friendly identifier | | `results[].publicUrl` | string\|null | Public URL to the product/context | | `results[].publishedAt` | string\|null | ISO 8601 timestamp | | `results[].vendor` | string\|null | Vendor name | | `results[].tags` | array | Array of tag strings | | `results[].productType` | string\|null | Product type/category | | `results[].price` | string\|null | Price as string | | `results[].compareAtPrice` | string\|null | Compare at price (original price) | # Search v3 Source: https://docs.hibonsai.com/project/api-reference/rest-api/search-v3 GET https://api.hibonsai.com/rest/search/v3/ Search products and contexts using the v3 endpoint ## Endpoint `GET /rest/search/v3/` `GET /rest/search/v3/{shop_id}/` ## Query Parameters Search query string. Filter to one or more shops. Return only products when `true`. Skip LLM scoring when `true`. ```bash cURL theme={null} curl -X GET "https://api.hibonsai.com/rest/search/v3/?q=humidifier" \ -H "X-API-Key: YOUR_API_KEY_HERE" ``` ## Response Response format is similar to Search v2 and may include additional fields. # Configuration Source: https://docs.hibonsai.com/project/docs/bonsai-concierge/config Configuration reference for the Bonsai Concierge chat web components ## How configuration works The Concierge has two configuration sources: 1. **HTML attributes** you set on the tag — everything listed on this page. 2. **Runtime configuration from the Bonsai dashboard** — brand colors, fetched per-tenant at load time using your `api-key` and applied automatically as CSS custom properties. ### Precedence For any given value, the component resolves in this order: 1. Inline CSS custom property set on the tag's `style` attribute 2. Dashboard configuration for this `api-key` 3. Built-in default Inline styles are re-applied after the dashboard response arrives, so a value you pin on the tag is never overwritten by a later dashboard change. HTML attributes listed below have no dashboard equivalent — they are read only from the DOM. ## Components | Tag | Purpose | | --------------------------- | ----------------------------------------------------------------------------------------------------------------------- | | `` | Floating launcher button plus the chat panel it opens. The usual embed. | | `` | Opens the chat panel immediately on page load, with no launcher button. | | `` | A scrolling strip of AI-generated questions about the product in context. Clicking one opens the chat on that question. | **`` opens on load — it does not render in place.** It is not an inline chat you can position in your layout; it is the same overlay panel, opened automatically. Use it only where you want the conversation to start unprompted. For a launcher the shopper chooses to press, use ``. `` additionally requires `external-id` (or `sku`) and renders nothing if the product has no generated questions. ## Required attributes Your Bonsai API key. Required on every component. Used to fetch runtime configuration and to authenticate the conversation. ```html theme={null} ``` ## Connection | Attribute | Required | Default | Notes | | ---------- | -------- | ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | | `api-key` | Yes | — | Your Bonsai API key | | `base-url` | No | `https://agent.hibonsai.com` | Agent API base URL. When omitted, it is derived from the origin of the loaded `bonsai-agent` script, falling back to the default | Only set this if you are pointing an embed at a non-production environment. In normal installations, leave it off — the component infers it from the script tag it was loaded from. ## Launcher appearance These apply to `` only. | Attribute | Required | Default | Notes | | ------------------------ | -------- | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | | `label` | No | `"Ask"` | Visible text on the launcher. Also used as its accessible name unless `launcher-aria-label` is set | | `launcher-compact-label` | No | derived from `label` | Shorter text used on phones 380px and narrower. See below | | `launcher-variant` | No | `pill` | `pill` (rounded, floating) or `tab` (flush against the viewport edge). `edge-tab` is accepted as a synonym for `tab` | | `launcher-content` | No | `text` | `text`, `text-icon`, or `icon` | | `launcher-side` | No | `right` | `left` or `right` | | `launcher-icon` | No | `sparkles` | Built-in glyph: `sparkles`, `chat`, or `mark` (the Bonsai mark) | | `launcher-icon-url` | No | — | URL of your own icon image. Falls back to the built-in `launcher-icon` if the image fails to load | | `launcher-aria-label` | No | — | Explicit accessible name. Required in practice when `launcher-content="icon"`, since there is no visible text | | `icon-only` | No | `false` | **Legacy.** Boolean equivalent to `launcher-content="icon"`, and its glyph defaults to `chat` rather than `sparkles`. Prefer `launcher-content` | **An unrecognized value falls back to the default rather than erroring.** `launcher-variant="rounded"` renders a pill; `launcher-icon="star"` renders the sparkles glyph. Values are matched case-insensitively and trimmed, so `" TAB "` resolves to `tab`. On phones 380px and narrower the launcher shrinks to a compact tab and shows this text instead of `label`. If you do not set it: 1. `label` is reused when it is 10 characters or shorter 2. Otherwise it falls back to `"Ask AI"` So `label="Ask"` needs nothing, and `label="Ask us anything"` renders `Ask AI` on a small phone unless you supply something better. ```html theme={null} ``` Keep it to roughly 10 characters — the compact tab is narrow, and longer text is truncated with an ellipsis rather than wrapped. See [Responsive behavior](/project/docs/bonsai-concierge/styling#responsive-behavior). When `launcher-content` is `text` or `text-icon`, this is only honored if it contains **both** the visible label and the compact label — otherwise the rendered text is used as the accessible name instead, so that a shopper using voice control can always say what they see. ```html theme={null} ``` ## Launcher position | Attribute | Required | Default | Notes | | --------------- | -------- | ------- | ---------------------------------------------------------------------------------------------------------------- | | `bubble-bottom` | No | `20px` | Distance from the bottom of the viewport | | `bubble-right` | No | `20px` | Distance from the right edge. Applies when `launcher-side="right"` | | `bubble-left` | No | `20px` | Distance from the left edge. Applies when `launcher-side="left"` | | `bubble-top` | No | `50%` | Vertical position. Applies to the `tab` variant, which is centered on the edge rather than sitting at the bottom | Each of these sets the corresponding CSS custom property, so anything valid in CSS works — `82px`, `4rem`, `calc(20px + env(safe-area-inset-bottom))`. **These do not apply on phones 380px and narrower.** At that width every launcher becomes a compact tab pinned to the side of the viewport and centered vertically, so `bubble-bottom`, `bubble-right`, `bubble-left`, and `bubble-top` are all ignored. To move it there, set `--bonsai-agent-bubble-compact-top` — see [Responsive behavior](/project/docs/bonsai-concierge/styling#responsive-behavior). ## Panel content These apply to `` and ``. | Attribute | Required | Default | Notes | | ---------------------- | -------- | ------- | ------------------------------------------------------------------ | | `title` | No | — | Heading shown in the panel header | | `header-icon-url` | No | — | Logo shown in the panel header. **Not** used for the launcher icon | | `header-layout` | No | — | Header arrangement | | `welcome-title` | No | — | Heading of the opening message | | `welcome-message` | No | — | Body of the opening message | | `placeholder` | No | — | Composer input placeholder | | `assistant-label` | No | — | Name shown against assistant replies | | `disclaimer-statement` | No | — | Fine print shown beneath the composer | | `theme` | No | `light` | `light` or `dark`. Any other value resolves to `light` | ## Behavior | Attribute | Required | Default | Notes | | ----------------------- | -------- | ------- | -------------------------------------------------------------------------------------------------------------- | | `auto-open` | No | `false` | Boolean. Opens the panel immediately on page load | | `idle-open` | No | — | Number of seconds of shopper inactivity after which the panel opens by itself. Omit to never auto-open on idle | | `mobile-expanded` | No | `false` | Boolean. On phone-sized viewports, present the panel as a full-height sheet | | `clear-on-close` | No | `false` | Boolean. Discard the conversation when the panel is closed, so the next open starts fresh | | `disable-input` | No | `false` | Boolean. Render the conversation read-only | | `disable-search-refine` | No | `false` | Boolean. Stop the Concierge from reacting to on-site search queries | | `handoff` | No | `false` | Boolean. Enable the support handoff affordance — see [Events & API](/project/docs/bonsai-concierge/events) | | `external-id` | No | — | Identifier for the product or entity in context on this page | | `sku` | No | — | Alias for `external-id`, read only when `external-id` is absent | The timer resets on any pointer move, pointer press, key press, scroll, or touch, and pauses while the tab is hidden — so a shopper who leaves a tab open in the background does not return to an opened panel. It fires at most once, and never while the panel is already open. ```html theme={null} ``` Set this on product pages so the conversation knows which product the shopper is looking at. ```html theme={null} ``` ## Sales call-to-action An optional promotional row rendered inside the panel after a set number of exchanges. | Attribute | Required | Default | Notes | | ----------------- | -------- | ------- | ------------------------------------------------------------------------------------------- | | `sales-cta` | No | — | The call-to-action text | | `sales-cta-href` | No | — | Destination URL | | `sales-cta-label` | No | — | Text on the action button | | `sales-cta-after` | No | `5` | Number of messages before it appears. A non-numeric or non-positive value falls back to `5` | ## Boolean attributes Every attribute marked Boolean above is **presence-based**, following the HTML convention. The attribute being present enables it, whatever its value: ```html theme={null} ``` `handoff="false"` **enables** handoff. This trips people up — if you are toggling one of these from a template, omit the attribute rather than setting it to a falsy string. # Events & API Source: https://docs.hibonsai.com/project/docs/bonsai-concierge/events Events you can dispatch and listen for, and the window.BonsaiAgent global ## How the Concierge is controlled The Concierge renders in a closed shadow DOM, so you never reach into it directly. Instead it listens for events on `window` and dispatches events back the same way. **Events are dispatched on `window`, not on the `` element.** Attach listeners with `window.addEventListener(...)`. A listener bound to the element itself will never fire. ## Events you dispatch ### `bonsai:open-chat` Opens the chat panel, reusing the configuration on your `` tag. This is the recommended way to open the Concierge from your own UI. ```js theme={null} window.dispatchEvent(new CustomEvent("bonsai:open-chat")); ``` Optionally seed the conversation with an opening question: ```js theme={null} window.dispatchEvent( new CustomEvent("bonsai:open-chat", { detail: { query: "Do you carry this in stock?" }, }) ); ``` | Detail field | Type | Notes | | ------------ | ------ | --------------------------------------------------------------------------- | | `query` | string | Opening question to send on the shopper's behalf | | `source` | string | Label recorded against the conversation for analytics. Defaults to `bubble` | This event is ignored if no `` is present on the page, since that tag is what supplies the API key and panel configuration. ### `bonsai:search` Tells the Concierge that a shopper ran an on-site search, so it can offer to refine the results conversationally. The Bonsai search components dispatch this for you; dispatch it yourself only if you are wiring up a search experience the Concierge does not already know about. Set `disable-search-refine` on the tag to make the Concierge ignore this event entirely. ### `bonsai:agent-reset-search` Clears the remembered search state, so the next `bonsai:search` is treated as a fresh query rather than a repeat. ## Events you listen for ### `bonsai:support-handoff` Fires when the conversation reaches a point where a human should take over. Use it to open your own support widget, route to a contact form, or record the escalation. ```js theme={null} window.addEventListener("bonsai:support-handoff", (event) => { const { reason, sessionId, messageId } = event.detail; console.log("Escalating to support", reason, sessionId); // Open your own support channel here }); ``` | Detail field | Type | Notes | | ------------ | ------ | ---------------------------------------------------------------- | | `reason` | string | What triggered it — see below | | `sessionId` | string | The conversation this relates to. Absent when `reason` is `user` | | `messageId` | string | The message that triggered it. Absent when `reason` is `user` | | `url` | string | Destination URL. Present only when `reason` is `support-card` | | `label` | string | Link text. Present only when `reason` is `support-card` | | `reason` | Meaning | | -------------- | ----------------------------------------------------------------------------- | | `auto` | The assistant determined on its own that the conversation should be escalated | | `user` | The shopper pressed the Customer Care Team button in the panel header | | `support-card` | The shopper clicked a support link the assistant offered in a reply | **Requires the `handoff` attribute.** Without it the header button and the support cards are not rendered, and the automatic escalation does not run, so this event never fires. An `auto` handoff fires **once per message** — the component records which messages have already escalated, so reloading the page or reopening the panel does not re-fire it for the same reply. ## The `window.BonsaiAgent` global Loading the script exposes two functions: ```js theme={null} window.BonsaiAgent.openChat(options); // Open with an explicit configuration window.BonsaiAgent.closeChat(); // Close the panel ``` **`openChat` requires a configuration object** — it does not read your `` tag. At minimum it needs `apiKey` and `externalId`: ```js theme={null} window.BonsaiAgent.openChat({ apiKey: "API-KEY", externalId: "" }); ``` Prefer dispatching `bonsai:open-chat` instead. It reuses the configuration already on your tag, so your API key stays in one place and every entry point behaves identically. `closeChat()` takes no arguments and is safe to call when the panel is already closed. The global is assigned asynchronously just after the script loads. If you call it from an inline script in the same tick, guard for it: ```js theme={null} if (window.BonsaiAgent) window.BonsaiAgent.closeChat(); ``` # Bonsai Concierge Source: https://docs.hibonsai.com/project/docs/bonsai-concierge/integration Self-serve guide for integrating the Bonsai Concierge chat web component into your website ## Getting Started Before getting started, ensure that you've had a chance to review the [Quickstart prerequisites](/project/docs/quickstart#prerequisites). The Concierge is a conversational shopping assistant. It adds a floating launcher button to your storefront; opening it slides in a chat panel where shoppers can ask questions in natural language and get answers grounded in your catalog. If you want a search box or a full search results page rather than a conversation,
use the [Bonsai Search Bar](/project/docs/bonsai-searchbar/integration) or [Bonsai Search](/project/docs/bonsai-search/integration) instead.
## Quick Installation Use this minimal 2-step setup to render the Concierge on your website. **Theming is managed in the Bonsai dashboard.** When the component loads, it fetches your tenant's brand colors using your `api-key` and applies them automatically. You can override any value per-embed with CSS custom properties set inline on the element — see [Advanced Styling](/project/docs/bonsai-concierge/styling). Add the Concierge ` ``` The `-latest` alias always serves the current release. To pin a specific version instead, replace `latest` with the version number — for example `bonsai-agent-0.27.0.js`. Add `` anywhere in the ``. The launcher positions itself as a fixed overlay, so its position in the DOM does not matter. Only `api-key` is required. ```html theme={null} ``` Click the launcher and ask something a shopper would ask. Not working? Check the [Troubleshooting](/project/docs/troubleshooting) guide for common issues. ## Placement on your site The Concierge is designed to be present on every page, not just a search page. Add the tag once in your theme layout so shoppers can open it from anywhere. The launcher is fixed to the bottom-right corner by default. If it collides with an existing element — a cookie banner, a live-chat widget, a sticky add-to-cart bar — move it rather than hiding it: ```html theme={null} ``` ## Choosing a launcher style The launcher has three independent settings: its shape (`launcher-variant`), what it shows (`launcher-content`), and which side it anchors to (`launcher-side`). ```html theme={null} ``` **On phones 380px and narrower these settings give way to a compact tab.** Whatever variant and position you choose, the launcher pins to the side of the viewport at that width and shows its icon plus a short label. If your `label` is longer than 10 characters, set `launcher-compact-label` — otherwise it falls back to `Ask AI`. Set `launcher-icon-url` to use your own glyph instead of the built-in sparkles. See [Responsive behavior](/project/docs/bonsai-concierge/styling#responsive-behavior). ## Opening the chat from your own UI To open the Concierge from an existing button, a nav link, or an empty-search-results state, dispatch a `bonsai:open-chat` event on `window`. It reuses the configuration already on your `` tag, so you do not repeat your API key: ```html theme={null} ``` You can seed the conversation with a question by passing it in the event detail: ```html theme={null} ``` This requires a `` on the page — it is what supplies the configuration. See [Events & API](/project/docs/bonsai-concierge/events) for the full surface. ## Next Steps Full attribute reference and default values for the Concierge component. CSS variable reference, launcher tokens, and responsive behavior. The `window.BonsaiAgent` global and the support handoff event. Common integration issues and how to resolve them. # Advanced Styling Source: https://docs.hibonsai.com/project/docs/bonsai-concierge/styling CSS variables, launcher tokens, and responsive behavior for the Bonsai Concierge **Where styling lives.** The Concierge renders in a closed shadow DOM, so your page's CSS cannot reach inside it and its styles cannot leak out. Everything is customized through CSS custom properties, set two ways: 1. **From the Bonsai dashboard** (preferred) — your brand colors are fetched per-tenant at load time and applied automatically. 2. **Inline on the element** — set any variable in the tag's `style` attribute to override it for that embed. Because the shadow root is closed, an inline `style` on the tag is the only way page-side CSS can reach the component. A stylesheet rule like `bonsai-chat-bubble { --bonsai-agent-brand: red }` will **not** take effect. ## Setting variables ```html theme={null} ``` Inline values are re-applied after the dashboard response arrives, so anything you pin here survives a later dashboard change. ## Color reference | Variable | Default | Purpose | | ------------------------- | --------------------- | -------------------------------------------------------------------------------------- | | `--bonsai-agent-brand` | `#0a5b3b` | Brand color. Drives the accent, launcher, and header unless those are set individually | | `--bonsai-agent-brand-fg` | `#ffffff` | Text and icons drawn on top of the brand color | | `--bonsai-agent-accent` | brand | Accent for interactive details | | `--bonsai-agent-bg` | `#ffffff` | Panel background | | `--bonsai-agent-canvas` | `#fafafa` | Conversation area background | | `--bonsai-agent-fg` | `#303030` | Primary text | | `--bonsai-agent-muted` | `#9ca3af` | Secondary text | | `--bonsai-agent-border` | `#e5e7eb` | Borders and dividers | | `--bonsai-agent-surface` | `#f5f5f5` | Raised surfaces | | `--bonsai-agent-hover-bg` | `rgba(0, 0, 0, 0.04)` | Hover background | ### Header | Variable | Default | Purpose | | -------------------------------- | ------------------------------ | ----------------------- | | `--bonsai-agent-header-bg` | brand | Header background | | `--bonsai-agent-header-fg` | brand foreground | Header text and icons | | `--bonsai-agent-header-hover-bg` | `rgba(255, 255, 255, 0.14)` | Header control hover | | `--bonsai-agent-header-close-bg` | `#ffffff` | Close button background | | `--bonsai-agent-header-close-fg` | brand | Close button glyph | | `--bonsai-agent-title-font` | inherits `--bonsai-agent-font` | Header title typeface | ### Conversation | Variable | Default | Purpose | | ------------------------------ | --------------- | -------------------------- | | `--bonsai-agent-welcome-bg` | surface | Opening message background | | `--bonsai-agent-welcome-fg` | foreground | Opening message text | | `--bonsai-agent-card-bg` | surface | Product card background | | `--bonsai-agent-card-fg` | foreground | Product card text | | `--bonsai-agent-input-bg` | `#f5f5f5` | Composer background | | `--bonsai-agent-input-fg` | foreground | Composer text | | `--bonsai-agent-suggestion-fg` | foreground | Suggested question text | | `--bonsai-agent-chip-bg` | card background | Suggestion chip background | | `--bonsai-agent-chip-fg` | accent | Suggestion chip text | | `--bonsai-agent-chip-border` | accent | Suggestion chip border | ### Panel and shape | Variable | Default | Purpose | | ------------------------------------ | --------------------------------- | ---------------------------------- | | `--bonsai-agent-panel-width` | `400px` | Panel width on desktop | | `--bonsai-agent-radius` | `12px` | Corner radius throughout the panel | | `--bonsai-agent-font` | system UI stack | Typeface throughout | | `--bonsai-agent-shadow` | `0 6px 24px rgba(0, 0, 0, 0.18)` | Default shadow | | `--bonsai-agent-panel-shadow` | `-8px 0 32px rgba(0, 0, 0, 0.16)` | Panel shadow on desktop | | `--bonsai-agent-mobile-panel-shadow` | `0 -8px 32px rgba(0, 0, 0, 0.18)` | Panel shadow on phones | ## Launcher reference The launcher has its own token set, so you can restyle the button without touching the panel. | Variable | Default | Purpose | | ---------------------------------------- | --------------------------------------------------- | ----------------------------------------------------------- | | `--bonsai-agent-bubble-bg` | brand | Launcher background | | `--bonsai-agent-bubble-fg` | brand foreground | Launcher text and icon | | `--bonsai-agent-bubble-font-size` | `15px` | Label size | | `--bonsai-agent-bubble-font-weight` | `600` | Label weight | | `--bonsai-agent-bubble-padding` | `14px 22px` pill, `14px 12px` tab | Inner spacing | | `--bonsai-agent-bubble-radius` | `999px` pill, `10px` on the outer corners for a tab | Corner radius | | `--bonsai-agent-bubble-gap` | `8px` | Space between icon and label | | `--bonsai-agent-bubble-icon-size` | `24px` | Icon size | | `--bonsai-agent-bubble-icon-color` | `currentColor` | Icon color | | `--bonsai-agent-bubble-icon-radius` | inherits the launcher radius | Icon corner radius | | `--bonsai-agent-bubble-min-height` | `44px` | Minimum touch target height | | `--bonsai-agent-bubble-min-width` | `44px` | Minimum touch target width | | `--bonsai-agent-bubble-icon-button-size` | `56px` | Size of the square button in icon-only mode | | `--bonsai-agent-bubble-border` | `none` | Launcher border | | `--bonsai-agent-bubble-shadow` | inherits `--bonsai-agent-shadow` | Launcher shadow | | `--bonsai-agent-bubble-focus-offset` | `3px` | Focus ring offset | | `--bonsai-agent-bubble-opposite-margin` | `8px` | Clearance kept from the opposite viewport edge | | `--bonsai-agent-bubble-bottom` | `20px` | Distance from the bottom. Also settable via `bubble-bottom` | | `--bonsai-agent-bubble-right` | `20px` pill, `0` tab | Distance from the right. Also settable via `bubble-right` | | `--bonsai-agent-bubble-left` | `20px` pill, `0` tab | Distance from the left. Also settable via `bubble-left` | | `--bonsai-agent-bubble-top` | `50%` | Vertical position of a tab. Also settable via `bubble-top` | **Minimum sizes are accessibility floors, not suggestions.** `--bonsai-agent-bubble-min-height` and `--bonsai-agent-bubble-min-width` default to 44px because that is the smallest reliably tappable target. A design that specifies a shorter button will render at 44px unless you lower these explicitly — and lowering them makes the launcher harder to hit on a phone. ## Responsive behavior The launcher adapts to the viewport at two breakpoints. Both apply automatically — there is nothing to enable. | Viewport | Launcher | | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------ | | 380px and narrower | Becomes a **compact tab**: pinned flush to the side of the viewport, centered vertically, showing the icon plus `launcher-compact-label` at 14px | | 381px to 640px | A left-side launcher stays visible while the panel is open, rather than hiding behind it | | 641px to 767px | Unchanged | | 768px to 1024px | Label grows to 16px and the minimum height to 48px | | 1025px and wider | Unchanged | 380px is the threshold so that an iPhone SE (375px wide) goes compact while an iPhone 12 through 16 (390px) keeps its full launcher. ### The compact tab At 380px and narrower, every launcher — pill or tab, on either side — renders the same way: * **Position** is forced to the viewport edge and vertically centered. `bubble-bottom`, `bubble-right`, `bubble-left`, and `bubble-top` no longer apply; the compact tab uses `--bonsai-agent-bubble-compact-top` instead. * **Shape** is a tab with its outer corners rounded 8px, whichever `launcher-variant` you set. * **Text** is `launcher-compact-label`, not `label`. An icon-only launcher is unaffected, but it also stops being a 56px square and becomes the same compact tab. * **The icon is always shown**, including when `launcher-content="text"`. * **It hides itself while the panel is open**, since at that width the panel covers the screen. It never shrinks below 44px in either dimension — `--bonsai-agent-bubble-min-height` and `--bonsai-agent-bubble-min-width` still apply. | Variable | Default | Purpose | | ----------------------------------------- | -------------------------- | ------------------------------------ | | `--bonsai-agent-bubble-compact-top` | `50%` | Vertical position of the compact tab | | `--bonsai-agent-bubble-compact-padding` | `8px` | Inner spacing | | `--bonsai-agent-bubble-compact-gap` | `6px` | Space between icon and compact label | | `--bonsai-agent-bubble-compact-font-size` | `14px` | Compact label size | | `--bonsai-agent-bubble-compact-radius` | `8px` on the outer corners | Corner radius | | `--bonsai-agent-bubble-compact-icon-size` | `14px` | Icon size | ### Pin the compact twin, not just the base variable On tablets, a value you pin on the tag wins — the tier only adjusts variables you have not set. The 380px tier is different: it reads its **own** variables, so pinning the base one has no effect there. ```html theme={null} ``` The same pairing applies to padding, gap, radius, and icon size. Switching to the compact label and showing the icon are not variable overrides — they change which elements are visible — so they apply whatever you have pinned. ### Which icon the compact tab shows 1. `launcher-icon-url`, if set 2. Otherwise the built-in glyph named by `launcher-icon` — `sparkles` (the default), `chat`, or `mark` (the Bonsai mark) The default glyph is unbranded, so a text-only launcher does not put the Bonsai mark on your storefront. Set `launcher-icon-url` to use your own. **`header-icon-url` is not reused here.** It supplies the logo inside the opened panel only — set `launcher-icon-url` explicitly even if it points at the same file. ```html theme={null} ``` If `launcher-icon-url` points at an image that fails to load, the component falls back to the built-in glyph rather than rendering an empty button. ## Dark mode Set `theme="dark"` to use the dark palette. It adjusts the background, foreground, muted, border, surface, input, card, and hover variables; brand and launcher colors are unchanged, since those are yours. ```html theme={null} ``` Any value other than `dark` resolves to the light palette. The component does not follow the operating system setting on its own — to do that, set the attribute from your own theme switcher. # Configuration Source: https://docs.hibonsai.com/project/docs/bonsai-search/config Configuration reference for the Bonsai Search web component ## How configuration works Starting with SDK v3.2, the `` component has two configuration sources: 1. **HTML attributes** you set on the tag — the commonly used ones are listed below, with the rest under *Additional attributes*. 2. **Runtime configuration from the Settings API** — theming (colors, layout, max width, alignment), default labels, default placeholder, default suggestions, and feature toggles (markdown, price rendering, autocomplete, etc.). These are fetched per-tenant by the component at load time from `/rest/search-component-config/` using your `api-key`, and they are applied automatically. **Where theming lives now.** Colors, borders, alignment, and width are **not** HTML attributes anymore. They are either returned by the Settings API (preferred — managed per tenant from the Bonsai dashboard) or overridden locally via CSS custom properties on the host element. See [Advanced Styling](/project/docs/bonsai-search/styling) for the full CSS variable list. ### Precedence For any given value, the component resolves in this order: 1. HTML attribute on the tag (if set) 2. Settings API response for this `api-key` (if provided) 3. Built-in default So you can leave the tag minimal (just `api-key`) and let the dashboard drive the rest, or override a specific value on the tag when you need to. **Colours are the exception.** Under `theme="dark"` (or `theme="auto"` on a dark-preference machine) 21 colour and shadow variables are fixed by the theme and cannot be overridden by page CSS or by the Settings API. See [Dark theme](/project/docs/bonsai-search/styling#dark-theme). ## Attributes The most commonly used attributes on ``: | Attribute | Required | Default | Notes | | ------------------------------ | -------- | --------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | | `api-key` | Yes | — | Required for all requests and for fetching runtime config | | `base-url` | No | `https://api.hibonsai.com` | API origin. The **path** is supplied by your organization's configured search version, not by this value — see below | | `disable-search-path-override` | No | — | Boolean attribute — pins the path in `base-url` instead of taking your organization's configured search version | | `placeholder` | No | `"Describe what you're looking for..."` | Input placeholder. Overrides Settings API `content.placeholder` | | `suggestions` | No | `[]` | JSON array string. Overrides Settings API `content.suggestions` | | `max-results` | No | `50` | Max results rendered. Overrides Settings API `behavior.max_results` | | `timeout-ms` | No | `30000` | Request timeout (ms) | | `render-price` | No | `false` | Boolean attribute — presence enables prices. Overrides Settings API `behavior.render_price` | | `render-price-with-title` | No | `true` | Whether price is rendered alongside the title | | `markdown` | No | `false` | Boolean attribute — enables markdown rendering in AI summaries | | `theme` | No | `light` | `light`, `dark`, or `auto`. Overrides Settings API `behavior.theme` | | `image-object-fit` | No | `cover` | `cover` or `contain`. Sets the `--bonsai-image-object-fit` CSS variable | | `featured-items-label` | No | `"Featured Items"` | Header for recommendations. Overrides Settings API `labels.featured_items_label` | | `more-items-label` | No | `"More Items"` | Header when recommendations exist. Overrides Settings API `labels.more_items_label` | | `items-label` | No | `"Items"` | Header when no recommendations. Overrides Settings API `labels.items_label` | | `hide-products` | No | `false` | Boolean attribute — hides product results (AI summary only) | | `on-price` | No | — | Name of a global function used to format prices before rendering. See [`on-price`](#on-price) | Legacy colour attributes (`brand-color`, `text-color`, `input-bg`, `card-bg`, …) were removed in v3.2.0 and are ignored. Use CSS custom properties or the Settings API instead — see [Advanced Styling](/project/docs/bonsai-search/styling). ### Additional attributes Less common, but read by the component: | Attribute | Default | Notes | | -------------------------------------------------------------------------------- | ---------------------------------- | -------------------------------------------------------------------- | | `autocomplete` | Settings API | Enable the autocomplete dropdown. `autocomplete="false"` disables it | | `filters` | Settings API | Fetch catalog filters and render the filter panel | | `pre-search-mode` | `filters-only` when filters are on | Pre-query behaviour: `none`, `filters-only`, or `browse` | | `filter-fields` | Settings API | JSON array or comma-separated allowlist of filter dimensions to show | | `initial-filters` | — | JSON filter object applied on first render | | `sync-filters-to-url` | follows `filters` | Read/write `filters` and `browse` URL params | | `enable-sort` | Settings API | Show the sort control | | `default-sort` | `relevance` | Initial sort key | | `hide-missing-images` | Settings API | Drop results with no usable image instead of showing a placeholder | | `missing-image-url` | — | Image to show instead of the "Image unavailable" placeholder | | `hide-description` | Settings API | Hide the card description line | | `secondary-image-on-hover` | — | Boolean attribute — swap to the alternate product image on hover | | `skip-scoring` | `false` | Skip LLM relevancy scoring | | `ctr` / `client-ctr` | `false` / `true` | Click-through tracking | | `disable-agent-handoff` | — | Boolean attribute — ignore Concierge handoff events | | `market` · `country` · `currency` · `market-root` · `cookie-domain` | — | Multi-market and cookie scoping | | `on-filter-panel-render` · `on-filter-group-render` · `on-filter-control-render` | — | Names of global functions that replace the default filter rendering | ## Required Attributes Your Bonsai API key. Required for the search component to function and to fetch runtime configuration from the Settings API. ```html theme={null} ``` ## API Configuration The API origin. Optional — omit it and the component uses the production origin. The Settings API URL is derived from this value automatically. ```html theme={null} ``` **The path is not yours to choose.** Whatever path you write here is replaced at load time by the search version configured for your organization (`api.search_path` in the Settings API response), so `.../rest/search/v3/` on the tag does not mean v3 is what gets called. Set the origin only, or pin it deliberately: ```html theme={null} ``` Boolean attribute. Keeps the path you wrote in `base-url` instead of adopting your organization's configured search version. Use it when an embed must stay on one specific version regardless of dashboard changes. Requests are rejected unless the page's origin is allowed for your organization. Three things are allowed automatically: the Bonsai dashboard, any `https://*.shopifypreview.com` preview, and — **on non-production environments only** — `http://localhost:3000`, `http://localhost:3001` and the matching `127.0.0.1` ports. **Everything else, including every localhost port you develop against production, has to be registered per organization.** Send your CSM the full list of origins you need — production, staging, preview, and the local port you work on — before you start. A page whose origin is not on that list fails the CORS preflight, and the component reports `Failed to fetch`. Pages opened directly from disk (`file://`) send an origin of `null` and are never allowed; serve your test page over HTTP instead. ## User Experience The placeholder text displayed in the search input field. If omitted, the value from the Settings API is used; otherwise the built-in default. ```html theme={null} ``` A JSON array of suggested search queries that appear below the search input. If omitted, the Settings API `content.suggestions` list is used. ```html theme={null} ``` The suggestions attribute must be a valid JSON array string. Use single quotes around the attribute value and double quotes for the array items. The maximum number of search results to display. ```html theme={null} ``` The request timeout in milliseconds. ```html theme={null} ``` ## Display Options Boolean attribute that enables price display in search results. Presence of the attribute is sufficient to enable it. ```html theme={null} ``` Controls whether the price is displayed alongside the product title. ```html theme={null} ``` Boolean attribute that enables markdown rendering in AI summaries and content. ```html theme={null} ``` Color theme for the component. Options: `light`, `dark`, or `auto` (follows the user's system preference). ```html theme={null} ``` Sets the `--bonsai-image-object-fit` CSS variable. Options: `cover` or `contain`. ```html theme={null} ``` Boolean attribute — when present, product results are hidden and only the AI summary is shown. Useful for conversational integrations. ```html theme={null} ``` ## Results Section Labels The heading text displayed above AI-recommended products. ```html theme={null} ``` The heading text displayed above additional results when AI recommendations are present. ```html theme={null} ``` The heading text displayed above results when there are no AI recommendations. ```html theme={null} ``` ## Callbacks Name of a globally-accessible function used to format prices before they are rendered. The function receives `(result, price, parent)` and must return the string to display. ```html theme={null} ``` ## Styling All visual customization (colors, borders, alignment, max width, hover states) is done via either: * The **Settings API** — preferred. Configure per-tenant in the Bonsai dashboard; the component picks up the values automatically. * **CSS custom properties** on the host element — to override per-embed. See [Advanced Styling](/project/docs/bonsai-search/styling) for the full list of CSS variables and override examples. # Events Source: https://docs.hibonsai.com/project/docs/bonsai-search/events Event reference and payload examples for the Bonsai Search web component All events bubble and are composed, allowing you to listen on parent elements for convenient event delegation. ### Reference Table | Event | When it fires | Payload | | --------- | ------------------------------------------------ | ------------------------------------------------------------ | | `search` | After the user submits a query (Enter or button) | `{ query }` | | `results` | When initial results are received and rendered | `{ results }` | | `ai` | When AI-scored results/recommendations arrive | `{ success, recommendations, results, count, maxRelevance }` | | `error` | When a network or parsing error occurs | `{ error }` | ### Examples Fields trimmed for brevity. ```json theme={null} { "query": "What is your return policy?" } ``` ```json theme={null} { "results": [ { "id": "product_123", "name": "Product Name", "publicUrl": "https://example.com/products/product-name", "price": "$42.00" } ] } ``` ```json theme={null} { "success": true, "count": 5, "maxRelevance": 0.92, "recommendations": [ { "text": "Best for small spaces", "productIds": ["product_123"], "relevancyScore": 0.91, "reasoning": "Compact footprint and quiet operation" } ], "results": [ { "id": "product_123", "name": "Product Name", "publicUrl": "https://example.com/products/product-name" } ] } ``` ```json theme={null} { "error": "Request timed out" } ``` # Examples Source: https://docs.hibonsai.com/project/docs/bonsai-search/examples Expanded integration walkthroughs, templates, and troubleshooting for Bonsai Search **Styling note.** In SDK v3.2+, per-tenant theming is delivered by the Settings API — page CSS and CSS custom properties on the host element override those defaults when you need to customize per-embed. Legacy color attributes (`brand-color`, `text-color`, `input-bg`, etc.) are ignored. All `` examples are listed below from minimal setup to full-page templates. This minimal example includes required attributes, event listeners, and a small CSS override. ```html theme={null} ``` This example wraps the component in a container with custom CSS for layout and theming. Colors are set via CSS custom properties on the host element. ```html theme={null}
```
```html theme={null} ``` ```html theme={null} Bonsai Search
```
A black page with a dark palette of your own. `theme="light"` selects the palette the CSS below is allowed to replace — [Dark theme](/project/docs/bonsai-search/styling#dark-theme) explains why, and what happens if you reach for `theme="dark"` instead. ```html theme={null} Bonsai Search
```
## Next * For issue resolution, see [Troubleshooting](/project/docs/troubleshooting). * For release/version notes, see [Changelog](/project/docs/changelog). # Bonsai Search Source: https://docs.hibonsai.com/project/docs/bonsai-search/integration Self-serve guide for integrating Bonsai AI Search into your website ## Getting Started Before getting started, ensure that you've had a chance to review the [Quickstart prerequisites](/project/docs/quickstart#prerequisites). Once you have your API key, you can integrate Bonsai AI search into any website in just a few minutes using our web component. If you only need the redirecting search bar (not the full results UI), use the
[Bonsai Search Bar Web Component](/project/docs/bonsai-searchbar/integration) instead.
## Quick Installation Use this minimal 2-step setup to render Bonsai Search on your website. **Theming is managed in the Bonsai dashboard.** When the component loads, it fetches your tenant's theme and behavior settings from the Settings API using your `api-key` and applies them automatically. You can also override values per-embed via CSS custom properties on the `` element — see [Advanced Styling](/project/docs/bonsai-search/styling). Building a **dark** embed? Read [Dark theme](/project/docs/bonsai-search/styling#dark-theme) first. `theme="dark"` fixes 21 colour variables that neither the dashboard nor your page CSS can change, and the supported way to control a dark embed is to set `theme="light"` and supply the palette yourself — not to drop the attribute, which adopts the dashboard theme. Add the Bonsai Search ` ``` Add the `` web component where you want search to appear. Only `api-key` is required — the component fetches its placeholder text, suggestion chips and API path from the Settings API using your `api-key`. ```html theme={null} ``` **Important:** Replace `API-KEY` with your actual API key provided by your CSM. **Most content and behavior come from the Settings API.** Placeholder text, suggestions, result count, price rendering, markdown rendering, the API path and theming are configured per-tenant in the Bonsai dashboard and returned by `/rest/search-component-config/` when the component loads, so a tag carrying only `api-key` is a complete install. If you need to override a specific value for a single embed you can still pass the corresponding attribute — it takes precedence over the Settings API response — but prefer the dashboard so every embed stays in sync. Not working? Check the [Troubleshooting](/project/docs/troubleshooting) guide for common issues. ## Pairing with the search bar A common layout puts a [``](/project/docs/bonsai-searchbar/integration) in the site header and the full `` on a dedicated results page. The two are wired by a URL parameter: 1. The search bar navigates to `` `${search-path}?q=${query}` `` on submit — `/ai-search?q=day+pass` by default. 2. `` on that page reads `q` on load, prefills the input and runs the search. So the only thing to keep in sync is that the search bar's `search-path` points at the page hosting ``. Nothing else is required on either tag. One script tag covers both: either bundle registers **both** `` and ``, so there is no need to load two. Using React? [React & Next.js](/project/docs/react) walks the whole install — script placement, the TypeScript declaration, the palette, and the results route. ## Next Steps Customize your component to match your site's layout and design. For expanded installation guides and pre-styled templates see [Examples](/project/docs/bonsai-search/examples). Full attribute reference and default values. CSS variables, shadow parts, and themes. Event lifecycle reference. Expanded integration templates. # Advanced Styling Source: https://docs.hibonsai.com/project/docs/bonsai-search/styling Styling, themes, CSS variables, and parts reference for the Bonsai Search web component **Where styling lives as of SDK v3.2+.** Colors, borders, layout, and shadows are driven by **CSS custom properties** — not by HTML attributes. These variables can be set two ways: 1. **From the Settings API** (preferred) — theming is configured per-tenant in the Bonsai dashboard and injected into the component's shadow DOM automatically at load time. 2. **From your page's CSS** — set any variable **on the `` element itself** to customize per-embed. Page CSS wins over the Settings API because Settings-API variables are injected at `:host` low specificity. **Target the element, not an ancestor.** The SDK declares its defaults on `:host` — a direct declaration on the component — so a value that merely *inherits* down from `:root` or a wrapper `
` loses to it. `bonsai-search { --bonsai-text-color: … }` works; `:root { --bonsai-text-color: … }` does not. **`theme="dark"` overrides both of the above.** The dark palette is declared on an element inside the component's shadow root, so it beats page CSS, inline `style=""`, and the Settings API alike — 21 colour and shadow variables are silently discarded. Read [Dark theme](#dark-theme) before styling a dark embed. Legacy HTML attributes like `brand-color`, `text-color`, `input-bg`, `card-bg`, etc. are no longer supported — use the variables on this page instead. ## Outer Container If you want to customize the layout and positioning, wrap the component in a container and add custom CSS. ```html theme={null}
```
## CSS Variables The web component uses a closed shadow root, but CSS custom properties still pass through. You can set any `--bonsai-*` variables directly on the `` element if you prefer CSS-only customization. ```html theme={null} ``` ### Reference Table Defaults shown are for the light theme. The dark theme automatically overrides color and shadow variables. | Variable | Default | Purpose | | --------------------------------- | -------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | | `--bonsai-brand-color` | `#0a5b3b` | Accent color for focus, buttons, and highlights | | `--bonsai-text-color` | `#303030` | Primary text | | `--bonsai-suggestions-text-color` | `#303030` | Suggestions text | | `--bonsai-input-text-color` | `#303030` | Input text + icon | | `--bonsai-results-text-color` | `#303030` | Summary + section headers | | `--bonsai-card-text-color` | `#303030` | Result card text | | `--bonsai-muted-color` | `#9ca3af` | Secondary text | | `--bonsai-input-bg` | `#f5f5f5` | Input + dropdown background | | `--bonsai-card-bg` | `transparent` | Result card background | | `--bonsai-canvas-color` | `#fafafa` | Page/canvas background **Declared but not consumed by the SDK — setting it currently has no effect.** | | `--bonsai-surface-color` | `#ffffff` | Surface background | | `--bonsai-border-color` | `rgba(0, 0, 0, 0.06)` | Default border | | `--bonsai-border-color-hover` | `rgba(0, 0, 0, 0.12)` | Hover border | | `--bonsai-hover-bg` | `rgba(0, 0, 0, 0.04)` | Hover background | | `--bonsai-suggestions-hover-bg` | `rgba(0, 0, 0, 0.04)` | Suggestions hover | | `--bonsai-error-bg` | `rgba(220, 53, 69, 0.1)` | Error background | | `--bonsai-error-color` | `#c82333` | Error text | | `--bonsai-space-1` | `0.25rem` | Spacing token | | `--bonsai-space-2` | `0.5rem` | Spacing token | | `--bonsai-space-3` | `0.75rem` | Spacing token | | `--bonsai-space-4` | `1rem` | Spacing token | | `--bonsai-space-5` | `1.25rem` | Spacing token | | `--bonsai-space-6` | `1.5rem` | Spacing token | | `--bonsai-font-heading` | `system-ui, -apple-system, sans-serif` | Heading font | | `--bonsai-font-body` | `system-ui, -apple-system, sans-serif` | Body font | | `--bonsai-font-mono` | `ui-monospace, monospace` | Mono font | | `--bonsai-font-size-xs` | `0.75rem` | Text size | | `--bonsai-font-size-sm` | `0.875rem` | Text size | | `--bonsai-font-size-base` | `1rem` | Text size | | `--bonsai-font-size-lg` | `1.125rem` | Text size | | `--bonsai-font-size-xl` | `1.25rem` | Text size | | `--bonsai-radius-none` | `0` | Radius token **Declared but not consumed by the SDK — setting it currently has no effect.** | | `--bonsai-radius-sm` | `0.25rem` | Radius token **Declared but not consumed by the SDK — setting it currently has no effect.** | | `--bonsai-radius-md` | `0.375rem` | Radius token | | `--bonsai-radius-lg` | `0.5rem` | Radius token | | `--bonsai-radius-xl` | `0.75rem` | Radius token **Declared but not consumed by the SDK — setting it currently has no effect.** | | `--bonsai-radius-full` | `9999px` | Full radius | | `--bonsai-duration-fast` | `150ms` | Animation timing | | `--bonsai-duration-base` | `200ms` | Animation timing | | `--bonsai-duration-slow` | `300ms` | Animation timing | | `--bonsai-easing` | `cubic-bezier(0, 0, 0.2, 1)` | Animation easing | | `--bonsai-shadow-sm` | `0 1px 2px 0 rgb(0 0 0 / 0.05)` | Shadow token **Declared but not consumed by the SDK — setting it currently has no effect.** | | `--bonsai-shadow-md` | `0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)` | Shadow token **Declared but not consumed by the SDK — setting it currently has no effect.** | | `--bonsai-shadow-lg` | `0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)` | Shadow token | | `--bonsai-search-min-height` | `3.5rem` | Search bar height **Declared but not consumed by the SDK — setting it currently has no effect.** | | `--bonsai-search-max-width` | `42rem` | Max container width | | `--bonsai-icon-size` | `1.25rem` | Icon size **Declared but not consumed by the SDK — setting it currently has no effect.** | | `--bonsai-icon-size-sm` | `1rem` | Small icon size | | `--bonsai-results-columns` | `3` | Results grid columns | | `--bonsai-image-object-fit` | `cover` | Image sizing mode | #### Color Accent color used for focus states, buttons, and highlights throughout the component. Primary text color for main content. Text color for input field and search icon. Text color for suggestion items. Text color for AI summary and section headers. Text color for result card content. Secondary text color for less prominent content. Background color for input field and dropdown areas. Background color for result cards. Defaults to `transparent`, so cards sit directly on your page background unless you set a surface. Background color for the main canvas area. **Declared but not consumed by the SDK — setting it currently has no effect.** Background color for elevated surfaces. Default border color. Border color on hover state. Background color for hover states. Background color when hovering over suggestion items. Background color for error states. Text color for error messages. #### Spacing Smallest spacing unit (4px). Extra small spacing unit (8px). Small spacing unit (12px). Base spacing unit (16px). Medium spacing unit (20px). Large spacing unit (24px). #### Typography Font family for headings and section titles. Font family for body text. Font family for monospace text. Extra small font size (12px). Small font size (14px). Base font size (16px). Large font size (18px). Extra large font size (20px). #### Border Radius No border radius. **Declared but not consumed by the SDK — setting it currently has no effect.** Small border radius (4px). **Declared but not consumed by the SDK — setting it currently has no effect.** Medium border radius (6px). Large border radius (8px). Extra large border radius (12px). **Declared but not consumed by the SDK — setting it currently has no effect.** Full border radius for pill-shaped elements. #### Animation Fast animation duration for quick transitions. Base animation duration for standard transitions. Slow animation duration for emphasized transitions. Easing function for smooth animations. #### Shadow Small shadow for subtle elevation. **Declared but not consumed by the SDK — setting it currently has no effect.** Medium shadow for moderate elevation. **Declared but not consumed by the SDK — setting it currently has no effect.** Large shadow for prominent elevation. #### Layout Minimum height for the search bar (56px). **Declared but not consumed by the SDK — setting it currently has no effect.** Maximum width for the search container (672px). Standard icon size (20px). **Declared but not consumed by the SDK — setting it currently has no effect.** Small icon size (16px). Number of columns in the results grid layout. CSS object-fit value for product images. Options: `cover` or `contain`. ## Dark theme **`theme="dark"` cannot be re-coloured.** Its palette is declared on an element inside the component's shadow root, so page CSS, inline `style=""`, `!important`, and Settings-API colours are all outranked. The 21 variables below are discarded whenever `theme` resolves to `dark` — including `theme="auto"` on a visitor whose system prefers dark. ### The 21 variables `theme="dark"` takes over | Variable | Dark value | | --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | | `--bonsai-text-color` | `#e5e7eb` | | `--bonsai-results-text-color` | `#e5e7eb` | | `--bonsai-card-text-color` | `#e5e7eb` | | `--bonsai-suggestions-text-color` | `#303030` | | `--bonsai-input-text-color` | `#303030` | | `--bonsai-muted-color` | `#a1a1aa` | | `--bonsai-input-bg` | `#ffffff` | | `--bonsai-card-bg` | `transparent` | | `--bonsai-canvas-color` | `#0f1115` **Declared but not consumed by the SDK — setting it currently has no effect.** | | `--bonsai-surface-color` | `#181a20` | | `--bonsai-border-color` | `rgba(255, 255, 255, 0.08)` | | `--bonsai-border-color-hover` | `rgba(255, 255, 255, 0.14)` | | `--bonsai-hover-bg` | `rgba(255, 255, 255, 0.06)` | | `--bonsai-suggestions-hover-bg` | `rgba(0, 0, 0, 0.04)` | | `--bonsai-error-bg` | `rgba(248, 113, 113, 0.15)` | | `--bonsai-error-color` | `#fca5a5` | | `--bonsai-skeleton-base` | `rgba(255, 255, 255, 0.04)` | | `--bonsai-skeleton-highlight` | `rgba(255, 255, 255, 0.08)` | | `--bonsai-shadow-sm` | `0 1px 2px 0 rgb(0 0 0 / 0.5)` **Declared but not consumed by the SDK — setting it currently has no effect.** | | `--bonsai-shadow-md` | `0 4px 6px -1px rgb(0 0 0 / 0.55), 0 2px 4px -2px rgb(0 0 0 / 0.5)` **Declared but not consumed by the SDK — setting it currently has no effect.** | | `--bonsai-shadow-lg` | `0 10px 15px -3px rgb(0 0 0 / 0.6), 0 4px 6px -4px rgb(0 0 0 / 0.55)` | Everything else — `--bonsai-brand-color`, the fonts, spacing, radii, `--bonsai-search-max-width`, `--bonsai-image-object-fit`, `--bonsai-content-padding`, `--bonsai-card-radius`, `--bonsai-image-radius` — is untouched by the theme and can be set normally. ### How to build a dark embed you control **Set `theme="light"` and supply the dark palette yourself.** On the light theme nothing inside the shadow root re-declares these variables, so every value on the element takes effect. The block below is the built-in dark palette, copied out so you can edit it. A component with `theme="light"` and this CSS looks the same as `theme="dark"` — the difference is that these lines now work. Start from this block, which reproduces the built-in dark palette exactly, and change the values you want: ```html theme={null} ``` Copy the **whole** block, not only the lines you want to change. `theme="light"` puts the component on the light palette, so any variable you leave out falls back to a light default — an invisible `rgba(0, 0, 0, 0.06)` border on a black page, for example. ### Following the system preference `theme="auto"` is subject to the same restriction, so drive it from your own media query instead: ```css theme={null} bonsai-search { --bonsai-text-color: #303030; --bonsai-card-text-color: #303030; /* ...the rest of your light palette... */ } @media (prefers-color-scheme: dark) { bonsai-search { --bonsai-text-color: #e5e7eb; --bonsai-card-text-color: #e5e7eb; /* ...the rest of the dark block above... */ } } ``` ### If you must keep `theme="dark"` Use [Shadow Parts](#shadow-parts). `::part()` rules are written from your page against elements the component exposes, and they set properties directly rather than through an inherited variable, so they are not affected: ```css theme={null} bonsai-search::part(result-card) { background: #f4f3f1; } bonsai-search::part(result-title), bonsai-search::part(result-caption), bonsai-search::part(result-price) { color: #111111; } ``` Recolour the caption and price alongside the title. They inherit `--bonsai-card-text-color`, which under `theme="dark"` stays light — on a light card the caption renders near-invisible at its 0.7 opacity. ## Shadow Parts The web component uses a closed shadow root, but it exposes stable `part` hooks for external styling. This lets you style specific inner elements with `::part(...)` from outside the component. `::part(...)` is supported in modern evergreen browsers. For older browsers, prefer CSS variables or wrapper styling. **Example (full part customization):** ```html theme={null} ``` ### Reference Table | Group | Part | Description | | ----------- | ------------------------ | --------------------------------- | | Search | `search-wrapper` | Outer wrapper | | Search | `search-bar` | Input container | | Search | `search-icon` | Left icon | | Search | `search-input` | Input field | | Search | `search-actions` | Action button container | | Search | `submit-button` | Submit action | | Search | `loading-state` | Loading pill | | Search | `loading-text` | Loading text | | Search | `loading-text-inner` | Emphasized loading text | | Search | `spinner` | Loading spinner | | Suggestions | `suggestions` | Suggestions container | | Suggestions | `suggestion-item` | Suggestion row | | Suggestions | `suggestion-text` | Suggestion text | | Suggestions | `suggestion-icon` | Suggestion leading icon | | Suggestions | `suggestion-image` | Suggestion thumbnail | | Suggestions | `suggestion-match` | Matched substring in a suggestion | | Footer | `powered-by` | Powered by footer | | Footer | `powered-by-link` | Powered by link | | Footer | `powered-by-dot` | Powered by separator | | Results | `results` | Results container | | Results | `results-section` | Results section | | Results | `results-header` | Results header | | Results | `results-grid` | Results grid | | Results | `summary` | AI summary container | | Results | `summary-text` | AI summary text | | Cards | `result-card` | Result card | | Cards | `result-image-wrapper` | Result image wrapper | | Cards | `result-image` | Result image | | Cards | `result-image-alternate` | Secondary image shown on hover | | Cards | `result-content` | Result content | | Cards | `result-title` | Result title | | Cards | `result-price-container` | Price wrapper | | Cards | `result-price` | Price | | Cards | `result-compare-at` | Compare-at price | | Cards | `result-caption` | Description | | States | `empty-state` | Empty state | | States | `error` | Error state | | Layout | `outer-container` | Component outer container | | Layout | `inner-container` | Component inner container | | Layout | `content` | Content region | | Results | `also-like` | "You may also like" section | | Results | `also-like-header` | "You may also like" header | | Sort | `sort` | Sort control wrapper | | Sort | `sort-select` | Sort `