Embeddable widget
Drop the Iterna chat widget onto any page with a single <script> tag. The widget
mounts into an isolated Shadow DOM, so its styles never clash with your site.
Quick start
Copy the snippet from Settings → Widget (it already carries your scenario’s
public token) and paste it before </body>:
<script
src="https://app.example.com/widget/iterna-widget.js"
data-token="<public_token>"
data-mode="bubble"
async
></script>
Colors, title, launcher, position and language default to the scenario’s server
config; any data-* attribute overrides the server value. Use
data-mode="inline" together with data-target="#some-id" to render the chat
inside an element instead of a floating bubble.
Identify your end-user
If your page already knows who the visitor is, hand the widget a JWT signed with your workspace’s embed secret (rotate it in Settings → Widget). The widget keeps the token in the browser and attaches it to every message so the backend can attribute the conversation to that user.
Either pass it statically via data-user-jwt:
<script
src="https://app.example.com/widget/iterna-widget.js"
data-token="<public_token>"
data-user-jwt="<end-user JWT>"
async
></script>
…or call iternaWidget.identify(jwt) at runtime. Use the command-queue shim so it
works even before the bundle finishes loading:
<script>
window.iternaWidget = window.iternaWidget || { _q: [] };
iternaWidget.identify = iternaWidget.identify
|| function () { (iternaWidget._idq = iternaWidget._idq || []).push(arguments); };
iternaWidget.identify("<end-user JWT signed with the embed secret>");
</script>
Call browser JS from a scenario
A scenario can invoke JavaScript that runs on your page (read the cart, highlight
an element, open a modal). Declare functions with iternaWidget.defineFunction; the
handler stays in the browser, only its {name, description, parameters} shape is
advertised to the scenario each turn.
<script>
window.iternaWidget = window.iternaWidget || { _q: [] };
iternaWidget.defineFunction = iternaWidget.defineFunction
|| function () { iternaWidget._q.push(arguments); };
iternaWidget.defineFunction({
name: "get_cart_total",
description: "Returns the current shopping-cart total",
parameters: { type: "object", properties: {} },
handler: async () => ({ total: window.cart.total }),
});
</script>
When the scenario calls get_cart_total, the widget runs your handler and sends
the result back — a synchronous round-trip your scenario can branch on.
Tip: every run is isolated and billed to the scenario owner’s plan.