Skip to content

Bubble API & Events

The <saytv-chat-bubble> element exposes a JavaScript API for programmatic control and dispatches custom events for integration with your application.

JavaScript API

Access the bubble element and call methods directly:

js
const bubble = document.querySelector('saytv-chat-bubble');

Methods

MethodDescription
open()Open the chat panel. Creates the inner widget on first call.
close()Close the chat panel with a closing animation.
toggle()Toggle the panel open/closed.
show()Show the bubble (after it was hidden).
hide()Hide the entire bubble (launcher + panel). Closes the panel first if open.
destroy()Full teardown - removes the inner widget, clears timers, and removes event listeners.

open()

Opens the chat panel. If this is the first time opening, the inner <saytv-chat> widget is created and mounted. Subsequent calls show the existing widget without re-creating it.

js
bubble.open();

The greeting tooltip is automatically dismissed when the panel opens. The unread badge is reset to zero.

close()

Closes the chat panel with a slide-down animation (200ms). Focus returns to the launcher button.

js
bubble.close();

toggle()

Convenience method that opens the panel if closed, or closes it if open.

js
bubble.toggle();

show() / hide()

Control the visibility of the entire bubble element. hide() closes the panel first if it's open.

js
// Hide the bubble when user navigates to a page where chat isn't needed
bubble.hide();

// Show it again
bubble.show();

Internally, hide() sets the hidden attribute and show() removes it.

destroy()

Tears down the bubble completely. Removes the inner widget, clears greeting and animation timers, and removes all event listeners (keyboard, outside click, mobile detection).

js
bubble.destroy();

WARNING

After calling destroy(), the bubble element remains in the DOM but is inert. Remove it from the DOM if you no longer need it:

js
bubble.destroy();
bubble.remove();

Events

The bubble dispatches its own events prefixed with saytv:. These are standard CustomEvent objects that bubble up through the DOM.

EventFired WhenDetail
saytv:openChat panel opens-
saytv:closeChat panel closes-
saytv:readyInner <saytv-chat> widget fires stv:ready-
saytv:unreadUnread message count changes{ count: number }

Listening to Events

js
const bubble = document.querySelector('saytv-chat-bubble');

bubble.addEventListener('saytv:open', () => {
  console.log('Chat opened');
});

bubble.addEventListener('saytv:close', () => {
  console.log('Chat closed');
});

bubble.addEventListener('saytv:ready', () => {
  console.log('Chat widget is ready');
});

bubble.addEventListener('saytv:unread', (e) => {
  console.log('Unread messages:', e.detail.count);
});

Unread Badge

The bubble tracks incoming messages via the inner widget's stv:message-received event. When the panel is closed, each new message increments the unread count and the saytv:unread event fires. When the panel opens, the count resets to zero.

js
bubble.addEventListener('saytv:unread', (e) => {
  // Update your page title or favicon
  document.title = e.detail.count > 0
    ? `(${e.detail.count}) My Site`
    : 'My Site';
});

The badge displays counts up to 99 and shows "99+" for higher values.

Inner Widget Events

All standard <saytv-chat> events (stv:ready, stv:message-sent, stv:user-login, etc.) are dispatched on the inner widget element inside the shadow DOM. They do not automatically propagate to the bubble element.

To listen for inner widget events, use the saytv:ready event to know when the widget exists, then access it:

js
bubble.addEventListener('saytv:ready', () => {
  // The inner widget is now available in the shadow DOM
  const widget = bubble.shadowRoot.querySelector('saytv-chat');

  widget.addEventListener('stv:message-sent', (e) => {
    console.log('Message sent:', e.detail.message);
  });

  widget.addEventListener('stv:user-login', (e) => {
    console.log('User logged in:', e.detail.user);
  });
});

Common Patterns

Open bubble from a custom button

Use the JavaScript API to trigger the bubble from anywhere in your page:

html
<button id="help-btn">Need Help?</button>

<saytv-chat-bubble app-id="your-app-id"></saytv-chat-bubble>

<script>
  document.getElementById('help-btn').addEventListener('click', () => {
    document.querySelector('saytv-chat-bubble').open();
  });
</script>

Hide on specific pages

js
const bubble = document.querySelector('saytv-chat-bubble');

// Hide on checkout pages
if (location.pathname.startsWith('/checkout')) {
  bubble.hide();
}

Analytics integration

js
bubble.addEventListener('saytv:open', () => {
  analytics.track('chat_bubble_opened');
});

bubble.addEventListener('saytv:close', () => {
  analytics.track('chat_bubble_closed');
});

bubble.addEventListener('saytv:unread', (e) => {
  if (e.detail.count > 0) {
    analytics.track('chat_unread_message', { count: e.detail.count });
  }
});

Conditionally show based on user state

js
const bubble = document.querySelector('saytv-chat-bubble');

// Only show for logged-in users
if (!currentUser) {
  bubble.hide();
}

// Show after a delay for first-time visitors
if (isFirstVisit) {
  setTimeout(() => bubble.show(), 10000);
}

SayTV Chat SDK Documentation