Events Reference
The <saytv-chat> element dispatches custom events that you can listen to for integration with your application. All events are prefixed with stv: and use CustomEvent with a detail payload.
Available Events
| Event | Fired When | Detail |
|---|---|---|
stv:ready | Widget initialized, auth resolved | - |
stv:user-login | User logs in (password, JWT, or registration) | { user: { id, username } } |
stv:user-logout | User logs out | - |
stv:message-sent | User's message is confirmed by the API | { message: { id, text } } |
stv:message-received | New message arrives from another user | { message: { id, text, userId, username } } |
stv:navigation | Widget page changes | { page, previousPage } |
stv:episode-changed | User selects an episode | { episode: { id, title } } |
stv:room-joined | User enters a chat room | { room: { id, name } } |
stv:theme-changed | Theme switches between light and dark | { theme: 'light' | 'dark' } |
stv:page-chat-ready | Page chat episode is created or reconnected | { episode: { id, title, externalId } } |
stv:error | An SDK error occurs | { error: { message, code? } } |
Listening to Events
Vanilla JS
js
const chat = document.querySelector('saytv-chat');
chat.addEventListener('stv:ready', () => {
console.log('Widget is ready');
});
chat.addEventListener('stv:user-login', (e) => {
console.log('User logged in:', e.detail.user);
});
chat.addEventListener('stv:user-logout', () => {
console.log('User logged out');
});
chat.addEventListener('stv:message-sent', (e) => {
console.log('Message sent:', e.detail.message);
});
chat.addEventListener('stv:message-received', (e) => {
const { id, text, username } = e.detail.message;
console.log(`New message from ${username}: ${text}`);
});
chat.addEventListener('stv:navigation', (e) => {
console.log(`Navigated from ${e.detail.previousPage} to ${e.detail.page}`);
});
chat.addEventListener('stv:episode-changed', (e) => {
console.log('Episode selected:', e.detail.episode);
});
chat.addEventListener('stv:room-joined', (e) => {
console.log('Joined room:', e.detail.room);
});
chat.addEventListener('stv:theme-changed', (e) => {
console.log('Theme changed to:', e.detail.theme);
});
chat.addEventListener('stv:page-chat-ready', (e) => {
console.log('Page chat ready:', e.detail.episode);
});
chat.addEventListener('stv:error', (e) => {
console.error('SDK error:', e.detail.error);
});React
Events are mapped to callback props:
tsx
<SayTVChat
appId="your-app-id"
onReady={() => console.log('Ready')}
onUserLogin={(e) => console.log(e.detail.user)}
onUserLogout={() => console.log('Logged out')}
onMessageSent={(e) => console.log(e.detail.message)}
onMessageReceived={(e) => console.log(e.detail.message)}
onNavigation={(e) => console.log(e.detail.page)}
onEpisodeChanged={(e) => console.log(e.detail.episode)}
onRoomJoined={(e) => console.log(e.detail.room)}
onThemeChanged={(e) => console.log(e.detail.theme)}
onPageChatReady={(e) => console.log(e.detail.episode)}
onError={(e) => console.error(e.detail.error)}
/>| DOM Event | React Prop |
|---|---|
stv:ready | onReady |
stv:user-login | onUserLogin |
stv:user-logout | onUserLogout |
stv:message-sent | onMessageSent |
stv:message-received | onMessageReceived |
stv:navigation | onNavigation |
stv:episode-changed | onEpisodeChanged |
stv:room-joined | onRoomJoined |
stv:theme-changed | onThemeChanged |
stv:page-chat-ready | onPageChatReady |
stv:error | onError |
Vue
Events are emitted as camelCase Vue events:
vue
<SayTVChat
app-id="your-app-id"
@ready="() => console.log('Ready')"
@user-login="(e) => console.log(e.detail.user)"
@user-logout="() => console.log('Logged out')"
@message-sent="(e) => console.log(e.detail.message)"
@message-received="(e) => console.log(e.detail.message)"
@navigation="(e) => console.log(e.detail.page)"
@episode-changed="(e) => console.log(e.detail.episode)"
@room-joined="(e) => console.log(e.detail.room)"
@theme-changed="(e) => console.log(e.detail.theme)"
@page-chat-ready="(e) => console.log(e.detail.episode)"
@error="(e) => console.error(e.detail.error)"
/>| DOM Event | Vue Event |
|---|---|
stv:ready | @ready |
stv:user-login | @user-login |
stv:user-logout | @user-logout |
stv:message-sent | @message-sent |
stv:message-received | @message-received |
stv:navigation | @navigation |
stv:episode-changed | @episode-changed |
stv:room-joined | @room-joined |
stv:theme-changed | @theme-changed |
stv:page-chat-ready | @page-chat-ready |
stv:error | @error |
Event Details
All events are standard CustomEvent objects that bubble up through the DOM. You can listen for them on the element itself or on any parent. Access the payload via event.detail:
ts
chat.addEventListener('stv:message-received', (event: CustomEvent) => {
const { message } = event.detail;
// message.id - Comment ID (number)
// message.text - Message body (string)
// message.userId - Sender's user ID (number)
// message.username - Sender's username (string)
});Common Patterns
Show a notification badge for unread messages
js
let unreadCount = 0;
chat.addEventListener('stv:message-received', () => {
unreadCount++;
updateBadge(unreadCount);
});
chat.addEventListener('stv:navigation', (e) => {
if (e.detail.page === 'episode-chat' || e.detail.page === 'room-chat') {
unreadCount = 0;
updateBadge(0);
}
});Sync theme with host application
js
chat.addEventListener('stv:theme-changed', (e) => {
document.documentElement.setAttribute('data-theme', e.detail.theme);
});Track user engagement
js
chat.addEventListener('stv:message-sent', (e) => {
analytics.track('chat_message_sent', { messageId: e.detail.message.id });
});
chat.addEventListener('stv:episode-changed', (e) => {
analytics.track('episode_viewed', { episodeId: e.detail.episode.id });
});