Widget Events
Widget receives few types of native events during lifetime. They are:
- onWidgetLoad - Triggers when the widget is loaded or refreshed.
- onEventReceived - Triggers on every event like a chat message, new tip, new follower, subscriber, etc.
- onSessionUpdate – Similar to
onEventReceived, but specifically triggers when the event affects session data such as latest subscriber, goals, totals, etc., visible in the Session Dashboard. It does not trigger for regular chat messages or events that don’t update session stats.
Example:
window.addEventListener('onWidgetLoad', function (obj) { console.log(obj); // You can check obj value in the browser console.});On Widget Load
Section titled “On Widget Load”Event received upon widget is loaded (or refreshed). Contains information about fieldData (fields values), channel information (including the apiToken) and session data.
window.addEventListener('onWidgetLoad', function (obj) { console.log(obj); // You can check obj value in the browser console. //fancy stuff here});In this scope obj has every information you could need to use. For better readability, let’s assign it:
window.addEventListener('onWidgetLoad', function (obj) { let data = obj["detail"]["session"]["data"]; let recents = obj["detail"]["recents"]; let currency = obj["detail"]["currency"]; let channelName = obj["detail"]["channel"]["username"]; let apiToken = obj["detail"]["channel"]["apiToken"]; let fieldData = obj["detail"]["fieldData"];});Session data
Section titled “Session data”data holds the per-feature session values for your channel: latest tip, follower counts, goals, top donators, recent events, and more. Every available key is documented in the Session Data Reference, grouped by platform and feature.
Recents and currency
Section titled “Recents and currency”There is also a list in chronological order of last 25 events (so if you want to make a list of all events - use this one) - variable recents initialized one line after variable data. It is an array of elements (each of them is an array) with the same elements as in data["*-recent"] (see Recent events).
The last element of obj is currency, which contains:
code- currency code (for example “USD”)name- currency name (for example “U.S. Dollar”)symbol- currency symbol (for example$)
On Event Received
Section titled “On Event Received”Live event for alerts, chat messages, SE_API store updates, etc.
window.addEventListener('onEventReceived', function (obj) { console.log(obj); // You can check obj value in the browser console. // fancy stuff here});In the example above you have obj forwarded to that function, which has two interesting scopes within obj.detail: obj.detail.listener and obj.detail.event.
Listener types
Section titled “Listener types”obj.detail.listener provides information about the event type. This value is a string. Possible values:
| Listener | Fires when |
|---|---|
follower-latest |
New follower |
subscriber-latest |
New subscriber |
host-latest |
New host |
cheer-latest |
New cheer |
tip-latest |
New tip |
raid-latest |
New raid |
message |
New chat message received |
delete-message |
Chat message removed |
delete-messages |
Chat messages by userId removed |
event:skip |
User clicked “skip alert” button in activity feed |
alertService:toggleSound |
User clicked “mute/unmute alerts” button in activity feed |
bot:counter |
Update of bot counter |
kvstore:update |
Update of SE_API store value |
widget-button |
User clicked custom field button in widget properties |
Event details
Section titled “Event details”obj.detail.event provides information about event details. It contains a few keys. For -latest events it is:
| Field | Description |
|---|---|
name |
User who triggered the action |
amount |
Amount of action |
message |
Message attached to sub |
gifted |
If this is a gift event for viewer |
sender |
If it was a gift, a gifter (for community and single gifts) |
bulkGifted |
If it is INITIAL event of community gift (${event.sender} gifted ${event.amount} subs to community) |
isCommunityGift |
If it is one of community gifts train (${event.sender} gifted ${event.name} a sub as part of random giveaway!) |
playedAsCommunityGift |
If the event was played as part of “cumulative sub bomb alert” |
There is also userCurrency for donations, you can use it (if initialized by let userCurrency;). For example: userCurrency.symbol
So expanding our sample code above you can have:
window.addEventListener('onEventReceived', function (obj) { const listener = obj.detail.listener; const data = obj["detail"]["event"]; // Assigned new const value, for easier handling. You can do it with .property or ["property"]. // I personally recommend using [""] as some of keys can have "-" within, // so you won't be able to call them (JS will try to do math operation on it).
// jQuery is included by default, so you can use following $("#usernameContainer").html(data["name"]); $("#actionContainer").html(listener);
// You can use vanilla JS as well document.getElementById("amount").innerHTML = data["amount"]});Chat Message
Section titled “Chat Message”For message events, there is an additional object that’s accessible at obj.detail.event.data, which looks like this:
{ "time": 1552400352142, "tags": { "badges": "broadcaster/1", "color": "#641FEF", "display-name": "SenderName", "emotes": "25:5-9", "flags": "", "id": "885d1f33-8387-4206-a668-e9b1409a998b", "mod": "0", "room-id": "85827806", "subscriber": "0", "tmi-sent-ts": "1552400351927", "turbo": "0", "user-id": "85827806", "user-type": "" }, "nick": "sendername", "userId": "123123", "displayName": "senderName", "displayColor": "#641FEF", "badges": [ { "type": "broadcaster", "version": "1", "url": "https://static-cdn.jtvnw.net/badges/v1/5527c58c-fb7d-422d-b71b-f309dcb85cc1/3", "description": "Broadcaster" } ], "channel": "channelname", "text": "Test Kappa test", "isAction": false, "emotes": [ { "type": "twitch", "name": "Kappa", "id": "25", "gif": false, "urls": { "1": "https://static-cdn.jtvnw.net/emoticons/v1/25/1.0", "2": "https://static-cdn.jtvnw.net/emoticons/v1/25/2.0", "4": "https://static-cdn.jtvnw.net/emoticons/v1/25/4.0" }, "start": 5, "end": 9 } ], "msgId": "885d1f33-8387-4206-a668-e9b1409a99Xb"}Every emote displayed on chat is within array of objects emotes with start/end index of text you can replace with image.
{ "kind": "youtube#liveChatMessage", "etag": "joNqfOov4YhUTK1ly5QnEw2O_04", "id": "LCC.EhwKGkNQakd1YS0tZ293REZWa1AxZ0FkMFU0VzNn", "snippet": { "type": "textMessageEvent", "liveChatId": "KicKGFVDT2p0eVFPaTNNUjhYT3lzMFdOZmtKZxILMXFObko0UHU5bTA", "authorChannelId": "noRfodywm2MXfIUCp9nm2MX", "publishedAt": "2025-03-11T16:51:20.385245+00:00", "hasDisplayContent": true, "displayMessage": ":face-blue-smiling: Testing message", "textMessageDetails": { "messageText": ":face-blue-smiling: Testing message" } }, "authorDetails": { "channelId": "noRfodywm2MXfIUCp9nm2MX", "channelUrl": "http://www.youtube.com/channel/noRfodywm2MXfIUCp9nm2MX", "displayName": "userName", "profileImageUrl": "https://yt3.ggpht.com/MkVId1UPvXogOyUqSyaFRZD2eFHqNaThFYO4-YNWAA4sQGvCPdoZKDkN5qgPUQ9BRiajmtcU=s88-c-k-c0x00ffffff-no-rj", "isVerified": false, "isChatOwner": false, "isChatSponsor": false, "isChatModerator": true }, "msgId": "LCC.EhwKGkNQakd1YS0tZ293REZWa1AxZ0FkMFU0VzNn", "userId": "noRfodywm2MXfIUCp9nm2MX", "nick": "username", "badges": [ ], "displayName": "userName", "isAction": false, "time": 1741711893915, "tags": [ ], "displayColor": null, "channel": "noRfodywm2MXfIUCp9nm2MX", "text": ":face-blue-smiling: Testing message", "emotes": [ ], "avatar": "https://yt3.ggpht.com/MkVId1UPvXogOyUqSyaFRZD2eFHqNaThFYO4-YNWAA4sQGvCPdoZKDkN5qgPUQ9BRiajmtcU=s88-c-k-c0x00ffffff-no-rj"}Message deletion
Section titled “Message deletion”When a user message is removed by a channel moderator there is an event emitted, either:
delete-message- with msgId of message to be removeddelete-messages- with userId of user whose messages have to be removed
This functionality is to prevent abusive content displayed in chat widget.
Bot counter
Section titled “Bot counter”Contains two elements - counter name (counter) and current value (value):
window.addEventListener('onEventReceived', function (obj) { const listener = obj.detail.listener; const data = obj.detail.event;
if (listener === 'bot:counter' && data.counter === counter) { document.getElementById("mycounter").innerHTML = data.value; }});Button click
Section titled “Button click”Contains two elements - field name (field) and value (value). Example below will send simplified event to test your chat widget:
window.addEventListener('onEventReceived', function (obj) { const listener = obj.detail.listener; const data = obj.detail.event; if (listener === 'widget-button') { if (data.field === 'chat' && data.value === 'First Message') { const emulated = new CustomEvent("onEventReceived", { detail: { "listener": "message", event: { data: { text: "Example message!", displayName: "StreamElements" } } } }); window.dispatchEvent(emulated); } }});On Session Update
Section titled “On Session Update”window.addEventListener('onSessionUpdate', function (obj) { console.log(obj); // You can check obj value in the browser console. //fancy stuff here});This event is triggered every time session data is updated (new tip/cheer/follower). Basically most scenarios can be covered by onEventReceived, but onSessionUpdate provides a lot more data you can use. The biggest advantage of using this is that you can check if the top donator (not donation) changed. Also it is the recommended option for goal widgets.
Example:
window.addEventListener('onSessionUpdate', function (obj) { const data = obj.detail.session; const tipTopDonator = data["tip-session-top-donator"]; const cheerTopDonator = data["cheer-session-top-donator"];
document.getElementById("top-donator").innerHTML = `${tipTopDonator["name"]} - ${tipTopDonator["amount"]}`; document.getElementById("top-cheerer").innerHTML = `${cheerTopDonator["name"]} - ${cheerTopDonator["amount"]}`;});data is the same as in onWidgetLoad, so every property is listed in the Session Data Reference.