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.