Events

React to chat events for analytics, conversion tracking, or custom UI updates. The widget exposes a small event bus you subscribe to via widget.on().

Quick example

// Track leads in Google Analytics
widget.on("lead_captured", (data) => {
  gtag("event", "generate_lead", { source: "chatbot" });
});
 
// Track conversation starts
widget.on("conversation_started", () => {
  analytics.track("Chat Started");
});
 
// React to widget open/close
widget.on("widget_opened", () => console.log("Chat opened"));
widget.on("widget_closed", () => console.log("Chat closed"));

Unsubscribing

on() returns an unsubscribe function. Call it to stop listening:

const unsub = widget.on("message_sent", (data) => {
  // ...
});
 
unsub(); // stop listening

Available events

EventFired whenData
widget_openedThe chat widget opens—
widget_closedThe chat widget closes—
conversation_startedFirst message in a new conversation—
message_sentUser sends a message{ message: string }
message_receivedAI responds—
lead_capturedAI captures a lead via the lead-capture tool{ conversationId: string }
trigger_shownA proactive message is waiting. Only with triggers: "events"{ message: string, triggerId: string, triggerType: string }
trigger_hiddenThe waiting message is gone: the chat opened, or triggers were switched off—

Common patterns

Conversion tracking with Google Ads

widget.on("lead_captured", () => {
  gtag("event", "conversion", {
    send_to: "AW-XXXXXX/YYYYY",
  });
});

Send leads to your CRM via your own backend

widget.on("lead_captured", async ({ conversationId }) => {
  await fetch("/api/internal/log-bot-lead", {
    method: "POST",
    body: JSON.stringify({ conversationId }),
  });
});

Note: BitPalm already pushes leads to your configured CRM (HubSpot, Pipedrive) — you don't need to do this manually. This pattern is for custom logging, not duplicating the CRM sync.

Analytics segmentation

widget.on("widget_opened", () => {
  // Mark this user as "engaged" in your analytics
  analytics.identify(userId, { hasOpenedChat: true });
});

A dot on your own chat button

const widget = createWidget({ slug: "...", launcher: false, triggers: "events" });
widget.on("trigger_shown", () => dot.hidden = false);
widget.on("trigger_hidden", () => dot.hidden = true);
chatButton.onclick = () => widget.open(); // opens with the waiting message

See Own Chat Button.

Triggering a tour or modal

widget.on("conversation_started", () => {
  // Show a "did you know" tooltip during the user's first chat
  if (!localStorage.getItem("bp_first_chat_seen")) {
    showTooltip("First time here? Here's how the chat works…");
    localStorage.setItem("bp_first_chat_seen", "1");
  }
});

Server-side leads

If you need lead data on your server (not just analytics), use BitPalm webhooks instead of the client event. Webhooks are more reliable (no ad blockers, no SSR issues) and contain the full lead payload. Set them up in dashboard → Settings → Webhooks.

See also