Reference

Widget-interaction analytics (avoiding double-counting)

← Back to GenUI Reference

A recipe for reporting GenUI widget interactions — which widget the learner acted on, what they picked — to KAVA via KavaAnalytics.buttonClicked() (./experience/analytics), without duplicating anything the platform already tracks server-side.

What not to report (read this first)

The backend (the session server and the brain) already reports its own server-side KAVA events for every session a KalturaAvatarSession connects to. These are the 80000-range "Immersive Agents" events: callStarted, callEnded, messageResponse (message delivery), and messageFeedbackSent (feedback).

KavaAnalytics has no code path that can send any of these (see the module docblock in src/experience/analytics.js). That is deliberate, not a gap to fill. Do not build client-side reporting for:

Already server-tracked (80000-range) Don't re-report client-side as...
A message was delivered to the user A buttonClicked/pageLoad for "message shown"
The user thumbs-up/down'd a reply (mgmt.feedback.add) A buttonClicked for "feedback given"
A call/session started or ended A buttonClicked/pageLoad for "session start/end"

A GenUI widget rendering on screen isn't itself one of those signals — the widget's arrival rides the same message-delivery event the server already counted. What's safe to report (because it has no server-side equivalent) is the client-only choice the learner makes on that widget. That could be which chip they clicked, which link they opened, or which answer they picked. That choice is the only thing this recipe reports.

The recipe: two widget interaction types, two distinguishable events

Wire each widget's onAction intent (see GenUI · Authoring and Consuming Widgets § onAction, WIDGET_KINDS, and the hand-rolled escape hatch above) straight into one buttonClicked() call. Construct one KavaAnalytics per page/session (same pattern as README's KAVA analytics section) and call it from the same onAction handler you already pass to ExperienceRenderer:

import { ExperienceRenderer } from '@kaltura/intelligent-agents/experience/genui';
import { KavaAnalytics } from '@kaltura/intelligent-agents/experience/analytics';

// AGENTIC_PARTNER_ID: your partner id (see the README's KAVA analytics section linked above)
// session: an active KalturaAvatarSession from your app
const analytics = new KavaAnalytics({
  partnerId: AGENTIC_PARTNER_ID,
  sessionId: session.threadId,   // ties the event to this conversation without re-reporting the conversation itself
  hostingKalturaApplication: 25, // HOSTING_APPLICATIONS.agents
});

new ExperienceRenderer({
  session,
  mount: document.getElementById('widgets'),
  onAction(action, payload) {
    if (action === 'followup') {
      // Interaction type 1: a followups-tool suggested-question chip was clicked.
      analytics.buttonClicked({
        buttonType: 'Select',
        buttonName: 'genui-followup-chip',
        buttonValue: payload.question,   // which chip — makes this event distinguishable per question
        buttonInfo: 'GenUI followups widget — suggested-question chip clicked',
      });
      session.speak(payload.question);
    } else if (action === 'open') {
      // Interaction type 2: a show-link-tool (or sources/content-gallery) link card was opened.
      analytics.buttonClicked({
        buttonType: 'Open',
        buttonName: 'genui-show-link-card',
        buttonValue: payload.url,
        buttonInfo: 'GenUI show-link widget — link card opened',
      });
    }
  },
}).start();

Two rules keep the two events distinguishable and non-duplicated:

Apply the same two-line pattern to any other onAction intent with no server-side equivalent:

Why the two events stay distinct

followups-tool and show-link-tool (the second requires enabling the show_link capability — OFF by default, see GenUI · Authoring and Consuming Widgets) can arrive in the same turn. Run through the two buttonClicked() calls above, the resulting payloads share the same partnerId/sessionId (same conversation), but differ in buttonName/buttonType/buttonValue. That makes them two distinguishable, non-duplicated events tied to one conversation, not two copies of the same one. To test this without landing rows on your live KAVA data, pass an injected transport to KavaAnalytics.

Doc Covers
GenUI · Authoring and Consuming Widgets ExperienceRenderer's onAction contract this recipe wires into
GenUI · Per-Runtime Widget Detail Per-runtime model keys, constraints, and descriptor shapes
GenUI Reference Back to the index
Click to talk with Nova — she knows this whole SDK.
Nova AI assistant — knows this whole site

Reloading starts a fresh chat. “New conversation” does the same without leaving the drawer.