Shopping Assistant API
POSTShopping Assistant API
Section titled “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
Section titled “Endpoint”POST https://live.luigisbox.com/v1/assistant
Request
Section titled “Request”Query parameters
Section titled “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
Section titled “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
Section titled “Request headers”Example request
Section titled “Example request”curl -X POST "https://live.luigisbox.com/v1/assistant?tracker_id=1234-5678&assistant_handle=piano_finder&user_id=123456" \ -H "Content-Type: application/json" \ -H "Accept-Encoding: gzip, deflate" \ -d '{ "assistant_version": 1, "steps": [ { "question_handle": "color", "option_handles": ["color-blue"] } ] }'require 'faraday'require 'json'
connection = Faraday.new(url: 'https://live.luigisbox.com') do |conn| conn.use FaradayMiddleware::Gzipend
response = connection.post('/v1/assistant') do |req| req.params['tracker_id'] = '1234-5678' req.params['assistant_handle'] = 'piano_finder' req.params['user_id'] = '123456' req.headers['Content-Type'] = 'application/json' req.headers['Accept-Encoding'] = 'gzip, deflate' req.body = { assistant_version: 1, steps: [ { question_handle: 'color', option_handles: ['color-blue'] } ] }.to_jsonend
if response.success? puts JSON.pretty_generate(JSON.parse(response.body))else puts "Error: HTTP Status #{response.status}, Response: #{response.body}"end<?phprequire 'vendor/autoload.php';
use GuzzleHttp\Client;
$client = new Client();$response = $client->request('POST', 'https://live.luigisbox.com/v1/assistant', [ 'query' => [ 'tracker_id' => '1234-5678', 'assistant_handle' => 'piano_finder', 'user_id' => '123456', ], 'json' => [ 'assistant_version' => 1, 'steps' => [ [ 'question_handle' => 'color', 'option_handles' => ['color-blue'], ], ], ], 'headers' => [ 'Accept-Encoding' => 'gzip, deflate', 'Content-Type' => 'application/json', ],]);
echo json_encode(json_decode($response->getBody()), JSON_PRETTY_PRINT);const axios = require("axios");
axios .post( "https://live.luigisbox.com/v1/assistant", { assistant_version: 1, steps: [ { question_handle: "color", option_handles: ["color-blue"], }, ], }, { params: { tracker_id: "1234-5678", assistant_handle: "piano_finder", user_id: "123456", }, headers: { "Content-Type": "application/json", "Accept-Encoding": "gzip, deflate", }, }, ) .then((response) => { console.log(JSON.stringify(response.data, null, 2)); }) .catch((error) => { if (error.response) { console.error(`Error: HTTP Status ${error.response.status}`); console.error(JSON.stringify(error.response.data)); } else { console.error(error.message); } });HTTP response
Section titled “HTTP response”The response to an assistant request is a structured JSON.
Success response (200 OK)
Section titled “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
Section titled “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
Section titled “Integration guide”Building a structured dialogue flow
Section titled “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 dialogueasync 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
Section titled “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
Section titled “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
Section titled “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
Section titled “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
Section titled “Best practices”Design effective questions
Section titled “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
Section titled “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
Section titled “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
Section titled “Ensure mobile compatibility”Design your assistant interface to work well on mobile devices, where users may prefer a guided experience over traditional filtering.
Was this page helpful?
Thanks.