Widgets

Add an iframe agents can open from the Kustomer navigation rail on any page, with per-org URLs, sizing, browser permissions and background loading.

A widget is a page you host that agents open from the navigation rail, whatever they're looking at. Use one for tools agents need alongside every conversation: a softphone, an order lookup, a knowledge tool, a portal into another system. Unlike a KView, a widget isn't tied to a record. It stays open as the agent moves around, and receives context updates through the Cards SDK.

If an org has one widget, its icon sits directly in the rail. With several, they're grouped under a widgets menu.

Define a widget

widgets (excerpt)
{
  "settings": {
    "default": {
      "storeDomain": { "type": "string", "defaultValue": "", "required": true }
    }
  },
  "widgets": [
    {
      "name": "order-lookup",
      "title": "Acme lookup",
      "url": "https://kustomer.acme.example/widget?store={{{settings.default.storeDomain}}}",
      "icon": "https://kustomer.acme.example/widget-icon.png",
      "width": "24vw",
      "height": "60vh",
      "iframePermissions": "microphone *; autoplay *;",
      "backgroundLoad": false
    }
  ]
}
Widget
urlstringrequired
iconURLrequired
titlestring
namestring
widthnumber | string
heightnumber | string
iframePermissionsstring
backgroundLoadboolean

Talk to Kustomer from the widget

A widget page loads the same Cards SDK as an embedded KView:

widget.html
<script src="https://cdn.kustomerapp.com/card-js/latest/kustomer-card.min.js"></script>
<script>
  Kustomer.initialize((context) => {
    showFor(context)
  })

  // Fires when the context changes, including when the agent opens or closes the widget.
  Kustomer.on('context', (context) => {
    if (context.widget && !context.widget.isOpen && hasUnsavedWork()) {
      Kustomer.open() // reopen so the agent can finish
      return
    }
    showFor(context)
  })
</script>

The widget context has type: "widget" and widget.isOpen, so your page can react when the agent opens or closes it. From there you can:

  • Read and write Kustomer data with Kustomer.request (as the agent).
  • Call your own API with credentials kept server-side through commands.
  • Send the agent to a customer with Kustomer.openCustomer(id) or Kustomer.openCustomerEvent(customerId, eventId).
  • Open the widget with Kustomer.open(), for example on an incoming call.

Voice and presence events

Softphone widgets can subscribe to telephony and routing events:

EventFires when
number-dialedAn agent clicks a phone number in Kustomer to dial it
routing-status-changeThe agent's routing status changes, such as available to busy
JavaScript
Kustomer.on('number-dialed', (payload) => softphone.dial(payload))

Background loading

backgroundLoad: true loads your page for every agent in the org as soon as Kustomer opens. Keep that cheap:

  • Load under 1 MB of assets before the agent interacts.
  • Keep console output to a minimum.
  • Don't open the widget automatically unless something needs the agent, like an incoming call. Several auto-opening widgets competing for attention frustrate agents.

Design checklist

  • Works at the smallest width you set, and at 2× that.
  • Uses the theme's CSS variables so it's readable in dark mode.
  • Handles masked fields in context data.
  • Shows a useful state when settings are missing, instead of a blank frame.
  • Served over HTTPS and allows framing by Kustomer (no X-Frame-Options: DENY, and a frame-ancestors policy that includes your customers' Kustomer domains).