Custom Template
You can create a custom template carousels either a list or slider, with Handlebars, JavaScript and CSS
What is Handlebars
Handlebars is a popular templating language used in web development. It helps you generate HTML dynamically by combining templates (HTML with special tags) and JSON data, that comes from an endpoint that you have specified. Introduction Handlebars
Endpoint data requirements
Your endpoint, ideally return an object that contains items array at the root. Within an item you can have other arrays. You can not have other arrays at the root.
When your endpoint returns array that is not named items
When interacting with an endpoint, like shopify MCP, when using the search_shop_catalog. It returns an array of products, you have to transform this JSON to be an array of items
Using JSONata Response for the transformation
{
"items": products,
"pagination": pagination,
"available_filters": available_filters,
"instructions": instructions
}
Which will generate the JSON that now has an array of items
Endpoint Data Handling
When should endpoint data go to the LLM, the Carousel (bypassing the LLM), or both?
1. No Carousel Items:
- If the Carousel exists but
items.length === 0
, the LLM processes the returned data (which contains no items) and typically responds with "no results found" along with possible recommendations.
2. Carousel Items Exist — Data Routing Rules: Data routing is controlled by two parameters:
- The endpoint JSON object property:
process
- The LLM response parameter:
llmCarouselBothProcess
Routing Logic:
-
If the
process
parameter is set:-
process = "llm"
:- Data is not sent to the Carousel.
- The LLM processes the JSON and generates the response.
-
process = "both"
:- Data is sent to both the LLM and the Carousel.
- The LLM processes the JSON and provides additional commentary or context around the Carousel.
-
process =
carousel`- Default, if no process is set, it is carousel, That is the data is not sent to the LLM. Carousel processes data
-
-
If the LLM response includes
llmCarouselBothProcess
:-
llmCarouselBothProcess = "llm"
:- Data is not sent to the Carousel.
- The LLM processes the JSON exclusively.
-
llmCarouselBothProcess = "both"
:- Data is sent to both the LLM and the Carousel.
- The LLM processes the data and enriches the Carousel with additional context.
-
-
If neither
process
norllmCarouselBothProcess
is set to"llm"
or"both"
:- Data bypasses the LLM and is sent directly to the Carousel for rendering.
- You either use process or llmCarouselBothProcess, - they can also set parameter to
carousel
The LLM can deal with getting a lot of data, and add color to the carousel display, it is not good at generating a lot of data, because it is slow to generate.
Summary Table
Condition | Sent to LLM | Sent to Carousel | Notes |
---|---|---|---|
Carousel exists, items.length === 0 | ✔️ | ❌ | LLM handles empty results |
process = "llm" | ✔️ | ❌ | LLM only |
process = "both" | ✔️ | ✔️ | Both LLM and Carousel |
llmCarouselBothProcess = "llm" | ✔️ | ❌ | LLM only |
llmCarouselBothProcess = "both" | ✔️ | ✔️ | Both LLM and Carousel |
(Default: neither flag set to "llm"/"both") | ❌ | ✔️ | Carousel only, bypassing LLM |
process = "carousel" unless 0 items | ❌ | ✔️ | Carousel only, bypassing LLM |
Buttons
Hyperlink button
<button class="panel-button list-btn text-white" onclick="window.open('https://www.ai12z.com', '_blank')">ai12z</button>
Panel button, to list note class is panel-button
<button class="panel-button list-btn text-white" data-type="panel" onclick='carousel.selectByName("List")'>Back</button>
Panel button, to any other tab, class is card-button
<button class="card-button list-btn uppercase flex-grow hover:bg-gradient-to-t md:flex-none" data-type="panel" onclick='carousel.selectByName("Units")'>Units</button>
Using sendMessage or sendJSON, requires knowing which type of client side control is being used, Bot or Search
<button class="card-button list-btn uppercase flex-grow hover:bg-gradient-to-t md:flex-none" onclick='ai12zBot.sendMessage("Request a Tour form","Request a Tour")'>Book Tour</button>
JavaScript functions
Shadow Root
Shadow Root allows ai12z bot widget to encapsulate its HTML, CSS, and JavaScript, preventing the host website’s styles or scripts from interfering with your bot’s appearance or behavior. This isolation ensures your chatbot always looks and functions as intended, no matter where it’s embedded. For bot providers, this means fewer conflicts, easier maintenance, and a more reliable user experience across all customer sites.
Where to add your Script
Add your javascript to the bot, config under the tab Script
, do not add to the handlebars template. Note: You cannot add it outside of the script tag, because the code is modified to work with a shadow root. To if you put it in an external js file it will not work.
function openLink() {
window.open("https://www.google.com", "_blank")
}
<button class="panel-button list-btn text-white" onclick="openLink()">
ai12z
</button>