Shopping Assistant API
Use the Shopping Assistant API endpoint to design interactive, guided product discovery experiences tailored for your users.
This API endpoint navigates structured dialogue flows you have already created. To get started first create an assistant in the Luigi's Box app.
Luigi's Box Assistant can learn from user interactions to provide better recommendations. To enable learning, integrate Luigi's Box Search Analytics service with your website by following the instructions.
Endpoint
POST https://live.luigisbox.com/v1/assistant
Request
Query parameters
tracker_id |
Your site identifier within Luigi's Box. You can find this identifier in every URL in the Luigi's Box app once you are logged in. |
assistant_handle |
The unique handler of the assistant to use. |
user_id |
The unique identifier of the end-user. If it matches the user ID collected in analytics, it can drive personalization of the assistant results. |
Request body parameters
assistant_version REQUIRED integer
|
The version of the assistant. Use -1 for the latest version. |
next_question_handleoptional string
|
The handle of the next question to be presented to the user. If omitted, the API determines the next question automatically. |
price_fieldoptional string
|
The product field used for calculating price ranges. Defaults to price_amount. If you want to use a different field, specify it here. If the field does not exist or is not numeric, an error will be returned. |
stepsoptional array[object]
|
An array of previous interactions (questions and answers) in the dialogue. Each step contains the question handle and the selected option handle. |
sizeoptional integer
|
The number of product results to return. |
sortoptional string
|
Sorting criteria for the product results (e.g., price:asc, price:desc,title:asc, etc.). If not provided, the default sorting will be applied. |
contextoptional object
|
Override fields used by search. The fields available for overriding are availability_field, availability_rank_field, freshness_field, boost_field, geo_location_field, margin_field, absolute_margin_field, and discount_field. |
foptional array[string]
|
An array of OR filters to apply to the product results (e.g., category:electronics, price:1|5, etc.). |
f_mustoptional array[string]
|
An array of AND filters that must match the product results (e.g., category:electronics, price:1|5, etc.). |
neg_foptional array[string]
|
An array of OR filters to exclude product results (e.g., category:electronics, price:1|5, etc.). |
neg_f_mustoptional array[string]
|
An array of AND filters to exclude the product results (e.g., category:electronics, price:1|5, etc.). |
search_in_variantsoptional boolean
|
A boolean value indicating whether to search in product variants. If set to true, the search will include variants of products. Defaults to the search setting set in the app. |
non_collapsed_variantsoptional boolean
|
A boolean value indicating whether to return non-collapsed variants in the results. If set to true, variants will be returned as separate items in the results. Works only when search_in_variants is allowed. |
Request headers
Consider sending request header of Accept-Encoding as well with values for supported encoding methods of your HTTP client, e.g. gzip or br, gzip, deflate for multiple supported methods. Encodings make the response from the JSON API considerably smaller and thus faster to transfer.
Example request
require 'faraday'
require 'faraday_middleware'
require 'json'
connection = Faraday.new(url: 'https://live.luigisbox.com') do |conn|
conn.use FaradayMiddleware::Gzip
end
response = connection.post("/v1/assistant?tracker_id=1234-5678&assistant_handle=piano_finder&user_id=123456") do |req|
req.headers['Content-Type'] = "application/json; charset=utf-8"
req.body = '{
"assistant_version": 1,
"steps": [
{
"question_handle": "color",
"option_handles": [
"color-blue"
]
}
]
}'
end
if response.success?
puts JSON.pretty_generate(JSON.parse(response.body))
else
puts "Error, HTTP status #{response.status}"
puts response.body
end
#!/bin/bash
curl -i -XPOST --compressed\
"https://live.luigisbox.com/v1/assistant?tracker_id=1234-5678&assistant_handle=piano_finder&user_id=123456"\
-d '{
"assistant_version": 1,
"steps": [
{
"question_handle": "color",
"option_handles": [
"color-blue"
]
}
]
}'
<?php
// Using Guzzle (http://guzzle.readthedocs.io/en/latest/overview.html#installation)
require 'GuzzleHttp/autoload.php';
$client = new GuzzleHttp\Client();
$res = $client->request('POST', "https://live.luigisbox.com/v1/assistant?tracker_id=1234-5678&assistant_handle=piano_finder&user_id=123456", [
'headers' => [
'Accept-Encoding' => 'gzip, deflate',
'Content-Type' => 'application/json; charset=utf-8',
],
'body' => '{
"assistant_version": 1,
"steps": [
{
"question_handle": "color",
"option_handles": [
"color-blue"
]
}
]
}'
]);
echo $res->getStatusCode();
echo $res->getBody();
// This endpoint requires no authentication
// Example request body
{
"assistant_version": 1,
"steps": [
{
"question_handle": "color",
"option_handles": [
"color-blue"
]
}
]
}
HTTP response
The response to an assistant request is a structured JSON.
Success response (200 OK)
A successful response includes the current state of the dialogue, such as the next question, and a filtered list of products.
Response fields
assistant_handle |
The handle of the assistant being used. |
tracker_id |
Your site identifier within Luigi's Box. |
hits |
An array of product results that match the current state of the dialogue. |
important_attributes |
An array of important attributes that should be displayed for each product in the results. |
avatar_image_link |
The URL to an avatar image for the assistant, if available. |
question.title_html |
An HTML-formatted title of the current question. |
question.description_html |
An HTML-formatted description of the current question, if available. |
question.image_link |
The URL to an image related to the current question, if available. |
question.type |
The type of the question, which can be single_choice or multi_choice. |
question.handle |
The unique identifier for the current question. |
question.options[].title_html |
An HTML-formatted title of the option. |
question.options[].description_html |
A HTML-formatted description of the option, if available. |
question.options[].option_handle |
The unique identifier for the option. |
question.options[].next_question_handle |
The handle of the next question to be presented if this option is selected. |
question.options[].image_link |
The URL to an image related to the option, if available. |
question.options[].color_code |
The color code associated with the option, if applicable. |
question.options[].hits_count |
The number of products that match this option. |
question.options[].price_range |
The price range of products matching this option, formatted as "min - max". |
Example success response
{
"assistant_handle": "piano_finder",
"tracker_id": "1234-5678",
"hits": [
{
"id": "product_1",
"title": "Grand Piano",
"price_amount": 5000,
"image_link": "https://example.com/images/grand_piano.jpg",
"important_attributes": ["brand", "model"],
"updated_at": "2024-10-01T12:00:00Z"
}
],
"important_attributes": ["brand", "model"],
"avatar_image_link": "https://example.com/images/avatar.png",
"question": {
"title_html": "<strong>What type of piano are you looking for?</strong>",
"description_html": "<p>Please select one of the options below.</p>",
"image_link": "https://example.com/images/question_image.jpg",
"type": "single_choice",
"handle": "piano_type",
"options": [
{
"title_html": "<strong>Grand Piano</strong>",
"description_html": "<p>A large and elegant piano.</p>",
"option_handle": "grand_piano",
"next_question_handle": null,
"image_link": null,
"color_code": null,
"hits_count": 10,
"price_range": "$4000 - $6000"
}
]
}
}
Error Responses
The API uses standard HTTP status codes. Note that the format of the error response body can vary depending on the type of error.
Client-side errors
These errors indicate a problem with the request that was sent.
-
400 Bad Request: Indicates malformed input, such as a missing parameter or incorrect data type. The response is a structured JSON object.
{
"type": "malformed_input",
"reason": "incorrect parameters provided",
"caused_by": {
"assistant_version": ["must be an integer"]
}
}
-
404 Not Found: Indicates that the requested assistant or question does not exist.
[
"Assistant with id 'Webnar Guitars' for tracker_id 'YOUR_TRACKER_ID' not found"
]
Server-side errors
These indicate a temporary problem with the service. You should retry the request after a short delay. If the problem persists, contact support.
| Status code | Response body (text/plain) |
Reason |
|---|---|---|
408 Request Timeout |
Request timed out |
The request took too long to process. |
500 Internal Server Error |
Internal server error Request-Id: ... |
Indicates a generic server error. |
503 Service Unavailable |
Service Unavailable |
A backend service is temporarily down. Please retry after a short delay. |
Integration guide
Building a structured dialogue flow
The Assistant API is designed to create a structured dialogue-based product discovery experience. Here's how to implement a basic flow:
-
Start the structured dialogue: Make an initial request with only the
tracker_id,assistant_handle, andassistant_versionparameters. - Present options: Display the question and options returned in the response to the user.
-
Track selections: When a user selects an option, add this interaction to the
stepsarray in your next request. -
Show results: Display the products returned in the
hitsarray at each stage of the structured dialogue. -
Continue the structured dialogue: The API will automatically determine the next most relevant question based on previous answers, or you can specify the next question using
next_question_handle.
Example structured dialogue flow
const TRACKER_ID = 'YOUR_TRACKER_ID';
const ASSISTANT_HANDLE = 'Webinar Guitars';
const ASSISTANT_VERSION = -1;
const API_ENDPOINT = 'https://live.luigisbox.com/v1/assistant';
const USER_ID = 'some_user_id';
let steps = []; // This array will store the history of the structured dialogue.
// Initial API call to start the structured dialogue
async function startConversation() {
const url = `${API_ENDPOINT}?tracker_id=${TRACKER_ID}&assistant_handle=${ASSISTANT_HANDLE}&user_id=${USER_ID}`;
const payload = {
assistant_version: ASSISTANT_VERSION,
steps: [] // Sending an empty array
};
const response = await axios.post(url, payload);
renderQuestion(response.data);
}
function handleOptionClick(questionHandle, selectedOption) {
// 1. Record the answer by adding it to our state array
steps.push({
question_handle: questionHandle,
option_handles: [selectedOption.option_handle] // API expects an array
});
// 2. Get the handle for the next question from the selected option
const nextQuestionHandle = selectedOption.next_question_handle;
// 3. Call the API again with the updated steps and the next question handle
callAssistantAPI(nextQuestionHandle);
}
async function callAssistantAPI(nextQuestionHandle = null) {
const url = `${API_ENDPOINT}?tracker_id=${TRACKER_ID}&assistant_handle=${ASSISTANT_HANDLE}&user_id=${USER_ID}`;
const payload = {
assistant_version: ASSISTANT_VERSION,
steps: steps // The steps array now contains the user's history
};
// Add the handle to the payload to continue the structured dialogue flow
if (nextQuestionHandle) {
payload.next_question_handle = nextQuestionHandle;
}
const response = await axios.post(url, payload);
renderQuestion(response.data);
}
function renderQuestion(data) {
if (data.question && data.question.options.length > 0) {
// Render the question and options...
} else {
// No more questions, the structured dialogue is over.
displayCompletionMessage();
}
}
Price range display
The Assistant API automatically calculates price ranges for each option, helping users understand the price distribution of products that match each option. This is calculated using the field specified in the price_field parameter (defaults to price_amount).
Analytics and performance tracking
Once your assistant is live, you can measure its performance and understand user behavior through the Shopping Assistant Analytics dashboard in the Luigi's Box app.
How analytics are collected
Luigi's Box tracks analytics in two ways: automatically through its servers, and manually via events you set up.
What's tracked automatically:
Every API call you make is logged. This means Luigi's Box automatically tracks the entire structured dialogue flow: which questions were shown, which answers were selected, and which products were displayed in the hits array (this is the "Assistant Listing" event). This powers metrics like Activation Rate and Completion Rate.
What you must track manually:
To measure the assistant's business impact, you must manually report what users do after the products are displayed. To enable key metrics like Conversion Rate (CVR) and Click-Through Rate (CTR), you must send events when a user acts on a product shown by the assistant:
Clicks: Report aclickevent when a user clicks on a product card.Conversions: Report aconversionevent (e.g., "add to cart") when a user takes a conversion action on a product.
Key metrics you can track
By ensuring full event tracking is in place, you can unlock powerful insights in your analytics dashboard, including:
-
Activation Rate: The percentage of users who start a dialogue after seeing the the teaser (e.g., the button or link that opens the assistant).- High: The teaser is engaging and relevant; keep the style, test small variations to push higher.
- Low: The teaser isn't catching attention; refresh copy/visuals, adjust placement, or better align the teaser promise with assistant value.
-
Diagnostic tip: If
Activationis low andCVRis low, the teaser likely isn't attracting the right audience. IfActivationis high butCVRis low, the teaser may be over-promising.
-
Completion Rate: The percentage of users who reach the final recommendation step after starting a dialogue.- High: The question flow is engaging and easy to follow; keep the style, test small variations to push higher.
- Low: The question flow may be confusing or too long; consider simplifying the questions, reducing the number of steps, or improving the clarity of options.
-
Diagnostic tip: A sudden drop in
Completionwith stableActivationoften points to a new friction point in the flow.
-
Click-Through Rate (CTR): The percentage of users who click on a product after it is displayed by the assistant.- High: The products shown are relevant and appealing; keep the style, test small variations to push higher.
- Low: The products may not be relevant or appealing; consider improving product relevance, enhancing product images/descriptions, or revising the question flow to better match user intent.
-
Diagnostic tip: If
Completion Rateis high but bothCTRandCVRare low, it's a strong signal that the final product recommendations are the problem. The user trusted the flow but didn't like the results.
-
Conversion Rate (CVR): The percentage of users who add a product to their cart or purchase it after using the assistant.- High: The assistant is effectively guiding users to products they want; keep the style, test small variations to push higher.
- Low: The assistant may not be effectively matching users with products; consider revising the question flow, improving product relevance, or enhancing the user experience.
-
Diagnostic tip: If
CVRis low butCompletionis high, the recommendation step may not be persuasive or relevant enough.
-
Exit Rate per Question: See which questions cause users to abandon the dialogue, helping you identify confusing or unhelpful steps.- High: A specific question may be causing confusion or frustration; consider revising or removing it.
- Low: The questions are engaging and relevant; keep the style, test small variations to push higher.
- Diagnostic tip: A spike in exits at a single question is a strong signal to re-evaluate that step's wording, complexity, or necessity.
By monitoring these metrics in the Luigi's Box app, you can continuously refine your assistant's questions and flow to better guide users and improve performance.
Best practices
Design effective questions
Create questions that help users narrow down their choices effectively. Each question should:
- Address a specific aspect of the product selection process.
- Have options that meaningfully divide the product catalog.
- Present clear, concise option text.
Track user journeys
Analyze how users navigate through your assistant to optimize the question flow and product recommendations. Use the analytics integration to:
- Identify common paths through the assistant.
- Detect questions where users frequently abandon the process.
- Measure conversion rates from assistant interactions.
Show relevant results early
While the assistant is designed to guide users to the perfect product through a series of questions, showing relevant results early in the process can improve user satisfaction. The API returns matching products at each step, so consider:
- Displaying a selection of top matches alongside questions.
- Highlighting the diversity of available options.
- Showing how each answer changes the result set.
Ensure mobile compatibility
Design your assistant interface to work well on mobile devices, where users may prefer a guided experience over traditional filtering.