Skip to main content
After this guide, every open, close, and message in the widget reaches your analytics. The widget reports activity with window.postMessage; the only callback option is onNavigate, covered in the configuration reference. Before you begin
  • The widget installed per the quickstart.
  • For the Tag Manager step, a GTM container on the page.
1

Listen for widget events

Every event is posted to the page’s own window with type: "LUA_POP_EVENT". Register the listener before or after init(); the order doesn’t matter.
The payload is { type: "LUA_POP_EVENT", eventType, timestamp, data? }: timestamp is Date.now() at emit time and data exists only on message_received. No event carries an end user identifier or the session ID.
2

Handle each event type

Four eventType values exist.widget_opened and widget_closed never fire in embedded mode, where the chat is always visible. message_received doesn’t fire for a reply whose stream fails part-way, nor for replies delivered as rich UI components instead of text.
3

Forward events to Google Tag Manager

GTM triggers fire on dataLayer pushes, so forward each event from a Custom HTML tag, then create a Custom Event trigger for lua_message_sent or any of the other names.
4

Optional: resize an iframe that hosts the widget

When the widget runs inside an iframe, it also posts a metadata-only copy of each event to window.parent, plus a LUA_POP_RESIZE message once when it mounts and whenever the floating window opens or closes. Handle that message in the parent page.
width and height are "350px" and "500px" while the window is open and "auto" when it is closed. The parent copy of message_received omits data, because the parent may be on another origin.
5

Verify

Open the widget and send a message. The console from the first step prints widget_opened, then message_sent, then message_received with the reply text.

Options you may need

Google Analytics 4

Call gtag directly instead of going through dataLayer.

If it isn’t working

The widget is in embedded mode, where the chat never opens or closes. Use message_sent as the engagement signal.
You are listening in the page that hosts the iframe. Only the copy posted to the widget’s own window carries data.
Any script on the page can post the same messages. Use them for analytics and UX, never for access control.

Next steps

Widget configuration

onNavigate and every other option.

Send proactive messages

Messages the agent starts also fire message_received.