Find event names, payload fields, and capture requirements for your source. For a quick overview of supported alerts, see Events and Alerts Compatibility.
Capture settings, filters and payload conventions
Important: Event availability depends on the source, permissions, and capture settings. To hide event-marked rows in dock or featured overlays, add &hideevents or &hideallevents. To hide selected events, use &filterevents=subscription_gift,new_follower,gifted. These filters can also hide paid rows that carry an event; ordinary donation rows without an event marker are not matched by event filters. Other message filters still apply.
Choose the capture method: For YouTube, Twitch, and Kick, WebSocket mode generally provides broader event coverage. Standard DOM capture reads the rows and cards actually rendered on the page. YouTube Super Chats, Super Stickers, and Jewel gifts have capture paths in both modes; other gift, tip, and membership events vary by source. See the platform tables for the supported paths and required settings.
Building Automations? Check out the Event Flow Guide to learn how to use these event payloads in custom triggers, alerts, and workflows. The guide includes a Template Variables Reference for text formatting. For gift amounts, streak counting, and editable game examples, see Build games and rewards.
Payload shape: Donation-style chat rows should use hasDonation and optional donoValue. Do not set event: "donation" just because a normal chat/tip row has value; use specific event names only for real platform actions or paid item types, such as superchat, supersticker, gift, or jeweldonation. Use meta only for additional structured data that consumers actually need and that existing fields do not already cover.
Quick Feature Availability
Use this table to see which alert types each capture method currently delivers. Detailed payload notes follow below.
The dedicated Multi-Stream Alert Box groups live events into six core alert categories: Follow, Subscription/Member, Donation, Bits/Cheers, Raid/Host, and Purchase, plus two opt-in categories (Auction and Hype Train) enabled via URL parameters. It derives those categories from the existing event, membership, subtitle, hasDonation, and meta fields documented here; no separate payload format is required.
Source
New Subs / Members
New Followers
Donations
Counts & Extras
YouTube (Data API bridge)
Membership joins, renewals, gifts
Individual subscriber alerts* + totals
Super Chats & Super Stickers
Viewer, subscriber, and view totals (polled)
Twitch – DOM capture
Gift bundle lines & gifted-to notices
-
Bits flagged via hasDonation
Viewer count, reward cards, and community highlight cards
Twitch – EventSub/Websocket
Instant subs, resubs, and gifts
Instant follows + follower total
Cheers, Power-ups, and channel point redemptions
Viewer/sub/follower totals, stream status, ad notices
TikTok Live
-
Follow cards (when TikTok shows them)
Gifts converted to coin totals
Viewer count, join alerts, and like storms
YouNow
-
Fan and audience activity
-
Viewer count from the live audience panel
Favorited Studio
-
-
-
Viewer count from the live viewers tab
Whatnot
-
-
-
Viewer count, join alerts, live auction metadata, products, and giveaway snapshots
eBay Live
-
-
-
Viewer count, follower count, live event card snapshots, auction footer metadata (when exposed), reaction hearts, and upcoming event metadata
Streamlabs Alert Box
Subs, gifts, sponsors, follows
Cheer/bits, donations (with currency)
Cheer/bits, donations (hasDonation)
While an alert box is open; also available via sources/websocket/streamlabs.html socket token
OBS Flow Actions
-
-
-
OBS output, scene, replay-buffer, and media-ended events for Event Flow when actions.html is connected to OBS WebSocket
Kick – DOM
-
-
-
Viewer count plus basic reward/gift system notices; use the Kick bridge for richer alerts
Kick – Websocket/Bridge
New subs, renewals, and gifts
Follow alerts + follower total
Support/tip events (amount + currency)
Stream status, reward redemptions, and profile metadata
Facebook Live
-
-
Stars when visible in DOM
Chat rows, Stars, and viewer count polls
Rumble – DOM capture
-
-
Visible Rant prices
Chat, incoming raids, and viewer count polls
Rumble – Websocket/API URL
New subs and gifted subs
Follow alerts + follower total
Rants/tips (amount + currency)
Viewer totals, subscriber totals, live status, and chat feed
Streamplace
-
-
-
Viewer count plus chat names, colors, badges, replies, and links
WorldsWave
-
-
Donation labels when present
Rendered live chat plus opt-in viewer count updates
CHZZK
-
-
Visible cheese donation rows
Chat rows, badge images, emotes, and viewer count polls
BEAM
-
-
-
Chat rows and viewer count polls when the chat-only page exposes a viewer counter
Seal Team Sloth
-
-
-
Rendered pop-out chat rows plus viewer_update polls when viewer counts are enabled
Castyr
-
-
-
Rendered pop-out chat rows plus opt-in viewer count updates
RPLAY
-
-
-
Signed-in /live/chat/box/ popout: type: "rplay" chat, avatars, tier badge images, and emotes. Coin tips retain their amount/unit in hasDonation for shared USD conversion, without a donation event. Opt-in viewer_update polls use integer meta from RPLAY's public stream endpoint. Relayed Twitch rows are excluded.
FLEX TV
-
-
-
Rendered chat rows with names, author colors, badge images, and member metadata
Chat capture and viewer counts on chat and watch pages
*YouTube subscriber alerts are polled and may be delayed or incomplete. The API reference does not promise a fixed four-hour delivery window. See the official subscription API limits.
Field Overview
data here means the message object, not an extra wrapper to add. Chat rows and metadata-only events have different shapes: counters and status snapshots may omit chatname/chatmessage. In platform tables, message describes an ordinary chat row, not a literal event: "message".
Field
Shape
Usage
data.type
string
Source identifier used by overlays, filters, and Event Flow. Instagram keeps live chat as instagramlive and non-live comments as instagram. See the Source Types Guide for variants, generic sources, and outbound routing.
data.chatname
string
Source-provided display name used by message processing and non-overlay outputs. A configured user display-name alias may replace this value only in copied dock and overlay transport payloads.
data.username
string
Source username when available. An aliased dock or overlay payload may add this field to preserve the original chatname for user actions; the canonical message remains unchanged.
data.userid
string
Platform-specific user identifier. User actions prefer this value over username and chatname.
data.platform
string (optional)
Some integrations include this alongside type. Many source adapters omit it; use type for source routing.
data.id
string | number (optional)
Message or event identifier. Its meaning depends on the source and transport; do not assume it is always a platform-native moderation ID. Use meta.messageId when the adapter exposes it for delete sync.
data.donoValue
number (optional)
Source-supplied numeric USD equivalent, including estimates. A valid value (including zero) overrides currency.js conversion. Without it, consumers estimate USD from hasDonation and source context. Original amounts and units remain in hasDonation and existing provider metadata.
data.chatbadges
array | string (optional)
Badge image URLs or badge objects (type: "img" with src, type: "svg" with html, or type: "text" with text). The relay retains a text badge's literal label in optional rawText and produces escaped text for older overlays. On later relay passes, regenerate text from rawText; do not escape text again. Current renderers display rawText literally when present and retain legacy encoded-text handling otherwise. This is a representation field, not permission to render HTML. Older sources can send a single HTML string instead of an array. Badge-rendering overlays accept both formats and sanitize badge HTML and URLs locally, including when the sender is an older extension. Invalid badges must not prevent the chat or membership message from displaying.
data.event
string | boolean
Identifier for system activity (for example viewer_update, subscription_gift, giftpurchase). Regular chat should leave this empty/false so overlays can distinguish system notices from conversational text.
data.chatmessage
string
Message body. It may contain sanitized/renderable HTML only when data.textonly is false.
data.textonly
boolean
Applies only to data.chatmessage. true means render chatmessage as plain text, preserving literal tags and entity-looking text; do not decode, HTML-sanitize, or add formatting tags to that body. Apply event styling to the displayed element. false means chatmessage may contain sanitized/renderable HTML; older messages without the flag retain that HTML behavior. Other normal fields are plain text, except media fields such as chatimg and contentimg. Display plain fields with textContent, or escape them once when constructing an HTML template; do not strip or repeatedly decode their contents.
data.contentimg
string (optional)
Content image or supported media URL. In the extension and desktop app, the opt-in allowExternalGifs setting fills an empty field from the first direct HTTP(S) GIF link in the message text or an HTML link. The URL path must end in .gif (case-insensitive); query parameters and fragments are preserved. It requires no API key, preserves chatmessage and existing attachments, and respects removeContentImage. The optional hideExternalGifUrl setting adds meta.hideExternalGifUrl: true; the dock and featured overlay then hide the matching GIF link only after their image loads, retaining surrounding text and the original payload. Failed or timed-out images collapse their attachment container and leave the link visible. The GIF-only overlay tries direct image display if fetching image bytes fails, using the configured display time when animation timing is unavailable; failed or stalled loads advance its queue. It does not add an event or change the source type. External images are not content-filtered and may fail to load if the host blocks embedding.
data.membership
string
Readable membership state such as MEMBERSHIP, new_sponsor, gift_recipient. Surfaces use it for badges, filters, and announcements.
data.subtitle
string
Supplemental descriptor (membership tenure, tier upgrades, gifted by...). Keep it short and text-only so overlays can slot it under the display name.
data.hasDonation
string
Monetary or virtual gift amount ($5.00, 500 bits, 300 coins). Populate even when data.event is blank so donation overlays can detect it.
data.meta
number | object | string (legacy)
Use plain integers for single counters (viewer, follower, subscriber) and objects for richer context. Some older events, such as Twitch DOM community_highlight, carry a string. Check the event-specific shape before reading object properties; new structured details belong in an object.
data.firsttime
boolean
Set to true when First-time chatter detection is enabled, the local database is enabled, and this is the first stored chat message for that user/source. The dock uses it for first-time highlighting and first-time beep filters; the optional first-time badge setting prepends a leaf badge to chatbadges.
data.lastactivity
number
Unix timestamp in seconds for that user's previous stored chat activity, when First-time chatter detection and the local database are enabled. Omitted for brand-new users.
Meta Conventions
Overlay control transport is separate from captured chat/events. Updated receivers use an ssnControl envelope containing a delivery id, feature target, optional reply channel and snapshot client ID. Existing feature bodies remain intact. Public feature controls use channel 7; Actions retains channel 6. Poll and Map state includes a host epoch, revision and reset marker; Timer, Ticker and Spotify use ssnState with an epoch and revision. These markers describe host state, not restored vote/chat history. Sources must not add control-envelope fields to captured messages. A receipt acknowledgement does not establish action completion or OBS visibility. See the migration status for supported features, reply negotiation and reconnect limits.
Phrase Guess uses the native {response: text} request for server2 chat replies and {action: "phraseGuessResponse", value: {type: "bot", chatname: name, chatmessage: text}} for dock-only announcements. The host must enable incoming server3 messages; disabling host control still blocks these requests. Dock announcements are forwarded as ordinary bot chat rows with textonly: true, without sending them to capture-source chat inputs. Legacy API mode retains its existing command format.
To keep dashboards and automations aligned, follow these conventions when extending data.meta:
viewer_update, follower_update, subscriber_update, and likes_update use a plain integer meta value. likes_update is an authoritative platform total: consumers must set the displayed value rather than adding it. The background script aggregates viewer counts into viewer_updates with an object keyed by data.type.
giveaway_state is a host-generated meta-only snapshot for managed displays. meta.giveaway version 2 includes giveawayId, persistent roundId/epoch, increasing generation across new rounds, revision within a round, status, open, draw, keyword, count, ticketCount, frozen config, up to 120 preview entrants, and the latest 20 winners. Entries expose id, name, platform and tickets; winners add drawnAt and awarded points. Coin Flip Pot adds outcome; Number Hunt adds number with public low, high and recent guesses, never the secret. Consumers filter by giveaway ID and discard older generations/revisions. These are display samples, not a full ticket book or payout instruction. Wallet keys, balances and reservations stay off audience snapshots. The host publishes to the giveaway P2P label and enabled overlay WebSocket feeds; this does not imply OBS visibility. Guide.
meta.giveawayControlResult contains the result of an Event Flow giveaway action (ok, optional error, giveaway or simulated). meta.giveawayHandled lists giveaway IDs already handled by an entry/purchase flow action so the automatic chat command cannot charge them again. The editor adds meta.economyTest for simulated giveaway actions; it is not a source-platform event or an authorization credential.
video_stats uses a structured meta object for external encoder/server health, including provider, label, online, bitrateKbps, rttMs, bufferMs, packet loss/drop counters, and optional codec details.
Donation-style events may include a descriptive object: for example { amount, currency, supporter } for Kick, { bits } for Twitch cheers. Membership events have their own source-specific metadata; they are not automatically monetary donations.
Normalized Stripe, Ko-fi, Buy Me a Coffee, and Fourthwall webhook messages include provider-scoped meta.webhookId, copied from the provider's stable event identifier, so downstream pages can suppress retry and mixed-transport duplicates.
Twitch raids pass { fromId, fromLogin, viewers }. Other sources differ: Whatnot uses meta.numRaiders, while SharePlay uses optional meta.fromLogin/meta.viewers. Check the source-specific row before reading raid metadata.
Twitch EventSub reward redemptions expose meta.rewardId, cost, rewardTitle, redemptionId, and a legacy alias alongside the prepared message. DOM reward cards and other sources may supply fewer or different fields.
user_banned is metadata-only for moderation widgets. It intentionally omits chatname and chatmessage; use meta.username, meta.displayName, meta.avatarUrl, and meta.profileUrl.
Chat transports that support source-control delete sync should expose the platform-native chat identifier as meta.messageId instead of relying on the dock's internal data-mid value.
Source deletions use {delete: {type, id}} for a known dock message ID, or {delete: {type, meta: {messageId}}} for a native platform message ID. A known ID removes only matching messages. When only the target user is known, send {delete: {type, userid}} or {delete: {type, chatname}} to remove that user's messages from that platform. Never substitute the moderator's identity for the target user. Incoming deletions do not require the optional dock-to-platform moderation sync setting.
SSApp source identity metadata may add meta.ssnAccountRole, meta.ssnSourceId, and meta.ssnSession when a source is assigned a non-normal account role.
Event Flow can request a highlight by setting meta.featured = true on the chat payload, which auto-features the message in dock/featured overlays.
AI Event Overlay: the action showAiEventOverlay sends a copy of the triggering message to label aievent-CONFIGURATION_ID, adding meta.aiEventOverlay: {profile: "CONFIGURATION_ID"}. Existing message fields and object metadata are preserved; scalar metadata is retained as meta.value. This is targeted delivery, not a new platform event. The original message is not modified. See the setup guide.
Optional meta.aiEventOverlay.variation selects an exact phrase approved in the saved overlay settings. Viewer text and metadata populate template fields after generation.
AI Event Overlay display requests require a profile and its private display token. Settings and API keys are managed only through the local SSN popup. Replies use {aiEventResponse: {target, value}} or {aiEventResponse: {target, error}}. Generated results contain template, duration, warnings, and optional media data URLs in image/audio.
Paid AI overlay rewards use aiEventPresentation (id, profile, expiresAt, result, message) and acknowledge receipt with aiEventDelivered (delivery ID). Point receipts and refund amounts stay on the host.
Event Flow can request dock pinning by setting meta.pinned = true; optional meta.pinnedTarget limits that pin to a dock with the matching label.
Event Flow thermal printing records its result under meta.thermalPrintResult (success and optional code/error), preserving the chat event and other metadata. For events with numeric or other non-object metadata, the diagnostic stays in the action result and the event remains unchanged.
Opt-in SSN sticker rewards:event: "sticker" is sent only to the stickers overlay label after a loyalty-point debit. It sets platform and type to the originating message's type, and preserves chatname, with empty chatmessage, textonly: true, and contentimg containing a packaged relative image path or a host-approved HTTPS media URL. meta.sticker contains id, pack, name, cost, duration (seconds), motion, redemptionId, and expiresAt (Unix milliseconds). This is an SSN reward, not a platform donation or native channel-points event. See the gallery and setup guide.
The sticker player returns a control packet {action: "stickerReceipt", meta: {sticker: {redemptionId, success}}} to its sender when the image loads or fails. Only receipts from a connected stickers peer resolve a pending redemption. Failed or unconfirmed delivery triggers a refund; this control packet is not a chat event. One active sticker display per session is recommended.
AI stage overlay commands use { action: "aiOverlay", target, meta } or dock-controlled co-host playout uses { action: "cohostOverlay", target, meta }; keep all command details such as command, text, emotion, avatar, and tts inside meta.
If a platform exposes multiple counters together, prefer a structured object with explicit keys (meta.viewer_count, meta.follower_count) instead of overloading strings.
Commerce overlays should use snapshot objects under meta (for example auction_update and commerce_update) and avoid ad-hoc top-level fields.
Platform Coverage
YouTube – Standard DOM Capture
Implementation: sources/youtube.js
Keep the live chat tab open. Capture reads the membership and gift cards rendered in that session; it does not require the viewer to be the channel owner or a moderator. Account access and the selected chat view can affect which rows are visible.
Opening the Viewer Count & Chat Activity overlay with viewers displayed automatically requests viewer counts. The Show viewer count and Track active chatters settings also enable collection.
For follower alerts and additional events, enable WebSocket mode in extension settings.
Event
When it Fires
Payload Notes
sponsorship
Membership welcome header without explicit chat text (new members, gifted bundles landing), including structured welcome cards or localized “Welcome to …” text.
membership populated with translated “MEMBERSHIP”; subtitle contains streak/tier when detected; nameColor uses membership green when allowed.
giftpurchase
Gift bundle purchase banner (ytd-sponsorships-live-chat-gift-purchase).
membership becomes gift_giver; subtitle carries the gift count when known; no hasDonation or donoValue.
giftredemption
Gift redemption announcement for recipients.
membership becomes “MEMBERSHIP”; subtitle includes “Gifted by …”.
resub
Upgrade banners that include “upgraded to …”.
subtitle captures new tier label; membership remains “MEMBERSHIP”.
membermilestone
Membership milestone cards containing chat text, when no other event type has already been identified.
chatmessage contains the member's message; membership carries the membership label and subtitle includes tenure when detected. This marks a milestone message, not a new membership purchase or gift.
superchat, supersticker, jeweldonation
Super Chats, Super Stickers, donation announcement cards, and YouTube Gifts powered by Jewels (yt-gift-message-view-model).
hasDonation carries the value; event identifies the YouTube paid item type. YouTube Gifts use N Jewels when present, or 1 YouTube Gift when YouTube hides the count. Gift images use contentimg, gift labels use subtitle, and minimal gift details are mirrored under meta.youtubeGift.
jeweldonation gift effect
YouTube displays an animated Jewel gift over live chat (ytls-gift-overlay-item-view-model).
Sent directly to the dedicated GIF/media target so the animation can play without duplicating the normal gift row. contentimg carries the animated asset and meta.youtubeGift.animationUrl/animationDescription preserve the effect details.
reaction
A viewer reaction appears in YouTube's live emoji fountain.
Sent directly to the dedicated reactions target. The anonymous emoji and image URL are preserved in chatmessage/contentimg and under meta.reactionType/reactionImage. Known live variants include ❤, 😄, 🎉, 😳, and 💯.
thankyou
Fallback message when a donation amount exists but no chat text was supplied.
Keeps hasDonation and auto-injects “Thank you for your donation!” for overlays.
redirect
YouTube redirect banner appears in live chat (the closest equivalent to a raid notice).
DOM-only capture from yt-live-chat-banner-redirect-renderer. Sets event to redirect and uses membership as the label so overlays render it like other system notices.
viewer_update
30s poll of Social Stream’s viewer endpoint (fallback to page scrape on quota errors).
meta is the live viewer integer; contributes to aggregated viewer_updates in the background script.
Membership blocks also set membership for moderator/member chat, while subtitle carries either month counts or tier names. sourceName/sourceImg populate once getChannelInfo succeeds. Standard DOM chat now includes meta.messageId when YouTube exposes a native live-chat message ID, which the dock uses for delete sync.
YouTube – Websocket/Data API Capture
Implementation: sources/websocket/youtube.html, shared helpers under shared/
Defaults to OAuth scopes youtube.readonly and youtube.channel-memberships.creator. Optional write access adds youtube.force-ssl for chat sending, moderation, bans, and stream-detail edits; Google may present this as broad YouTube management permission because YouTube does not provide a chat-only write scope.
Channel statistics respect the per-setting toggles (showsubscount, showviewercount).
The API cannot deliver custom badge imagery; badge fallbacks use emoji icons noted below.
When the API explicitly reports authorDetails.isChatModerator: true, chat, Super Chat, Super Sticker, YouTube Gift, and membership-gift payloads include mod: true. Moderator status is not inferred or cached between events.
New subscriber alerts use the myRecentSubscribers API (polled every 5 minutes). Note: Results may be delayed or incomplete; only publicly visible subscriptions can be identified.
YouTube redirect banners are not exposed by the Data API, so redirect remains available only from Standard DOM capture.
Event
When it Fires
Payload Notes
superchat
Super Chat entries from the Data API backlog or stream polling.
hasDonation preserves site amount (currency + value); event is superchat. Older WebSocket builds used event: "donation" for this row, so consumers may keep accepting that as a legacy alias.
supersticker
Super Stickers (message text fallback only, no image from API).
hasDonation holds the amount; chatmessage contains decoded description text.
jeweldonation
YouTube giftEvent messages when viewers redeem Jewels for Gifts.
hasDonation holds N Jewels, or 1 YouTube Gift when YouTube hides the count; contentimg uses the gift asset URL when exposed; subtitle carries the gift label; meta.youtubeGift carries extra gift details.
sponsorship
New member joins via newSponsorEvent.
membership becomes new_sponsor or new_member; meta includes originalEventType, durations, and level info.
resub
Member renewals or tier upgrades.
membership becomes renewed_member (renewals) or upgraded_member (upgrades); subtitle shows tier.
giftpurchase
Gift bundles purchased via the API.
membership set to gift_giver; subtitle lists count/tier; no hasDonation or donoValue.
giftredemption
Gift redemption notifications.
membershipgift_recipient; badges default to 🎁; subtitle indicates gifted tier.
membermilestone
Milestone chats (memberMonth or displayMessage present).
membershipmember_milestone; subtitle summarizes months + tier; meta captures the raw milestone mapping.
viewer_update
Streaming stats (concurrent viewers) when viewer reporting is enabled.
meta is integer count; mirrors DOM scripting so downstream consumers can merge both flows. A dock using &showviewercount requests viewer-count collection for 70 minutes and renews that request hourly without permanently changing the global setting.
likes_update
Official video statistics poll when Send platform like totals is enabled.
meta is the current video like-count integer. It emits when the count changes and periodically while unchanged so consumers stay fresh. The global captureliketotals setting enables this; legacy captureyoutubelikes remains a compatibility alias. Enabling the popup's per-dock &showlikecount option also persistently enables those global capture settings, while adding the URL parameter manually controls rendering only. Turning the display option off does not disable global collection.
subscriber_update
Channel stats poll (subscribers) when showsubscount not explicitly disabled.
meta is total subscriber count; UI updates dashboard counters.
view_update
Channel stats poll (lifetime views) when showviewercount or hype mode is active.
meta is view count integer.
live_chat_ended
Live chat becomes unavailable for the bound broadcast.
meta.streamTitle populated when stream metadata was cached.
user_banned
userBannedEvent from the live-chat API or gRPC stream.
Metadata-only event for moderation widgets. meta includes username/display name, channel ID, avatar/profile URL, moderator, ban/timeout duration, and permanence.
new_follower
New subscriber detected via myRecentSubscribers API (polled every 5 minutes).
chatname is subscriber's channel name; chatmessage is empty unless subscriber alert messages are enabled in the YouTube source page. meta includes channelId, title, subscribedAt, and grouped bursts add grouped, count, others, and subscribers. Note: Results may be delayed or incomplete; only publicly visible subscriptions can be identified.
Chat relays from the API use meta.plainText for the plain-text message alongside rich chatmessage content. It is text, not HTML, and can still contain Unicode emoji. Membership badges fall back to emoji (⭐, 💝, 🏅, etc.) to remain consistent with DOM capture. Regular chat payloads also include meta.messageId so dock-side delete actions can round-trip back to the YouTube moderation API.
YouTube Subscriber Alerts (new_follower)
Social Stream can now detect new YouTube subscribers using the myRecentSubscribers API endpoint. This works similarly to Streamlabs subscriber alerts.
How it works:
Polls the YouTube API every 5 minutes for recent subscribers
Tracks seen subscribers in localStorage to detect new ones
Emits new_follower events with the subscriber's name, avatar, and channel ID
Keeps subscriber alert messages disabled by default; enabling them uses the current translation string for alert-just-subscribed
Groups bursts larger than three new subscribers by default so reconnects do not flood overlays or Event Flow
Requires WebSocket mode to be enabled in extension settings
Limitations (these are YouTube API restrictions, not Social Stream limitations):
No guaranteed delivery delay – SSN polls every five minutes, but the API may return delayed or incomplete results. Do not rely on a fixed four-hour window.
Public subscriptions only – Subscribers who have set their subscription list to private will not trigger alerts. Subscriptions are private by default on YouTube.
Channel owner only – You can only receive subscriber alerts for channels you own and are authenticated as.
API quota usage – Each poll costs 1 API unit. At 5-minute intervals, this uses approximately 288 units per day (out of the default 10,000 daily quota).
Event Flow Editor trigger: Use data.event === "new_follower" and data.type === "youtube"
Keep Twitch chat open. Membership and user notices are captured when Twitch renders them; they are not restricted to broadcaster or moderator accounts. Authentication may be needed for account-specific features.
Viewer count requests hit https://api.socialstream.ninja/twitch/viewers every 30 seconds.
For follower alerts, raids, and full event support, enable WebSocket mode in extension settings.
Viewer-shared Watch Streak notices are disabled by default and require the Show Twitch Watch Streaks setting.
The opt-in PluralMind setting may replace chatname, nameColor, and the proxy-wrapped portion of chatmessage, and may add a pronoun text badge. username remains the Twitch login; related deletes carry delete.meta.pluralmind so the dock uses that stable login.
Event
When it Fires
Payload Notes
reward
Channel point redemption cards (including 7TV reward container).
System lines such as “User gifting X Subs in the channel”.
chatmessage is the system line, enabling overlays to highlight gifter campaigns.
subscription_gift
Gifted subscription notices (“User gifted a Sub to …”).
Marks the event for highlight filters; membership remains the recipient badge label.
viewer_update
30s fetch to Social Stream viewer proxy (fallback 0 on error).
meta integer viewer count.
hype_train
Twitch sticky community highlight shows an active Hype Train in popout chat.
Metadata-only DOM fallback with meta.sourceMode set to dom. Uses visible level, timer, and meta.progressPercent when Twitch does not expose EventSub point totals.
community_highlight
Elements inside Twitch’s “Community Highlight” widget.
meta is the extracted highlight text for automation hooks.
knock
Stream Together collaboration invites displayed above chat.
chatmessage contains the invite text; chatname is derived from the alert user when available.
watch_streak
Opt-in viewer-shared Watch Streak notice rendered in Twitch chat.
meta.streakCount contains the visible count when detected; meta.milestoneId uses the DOM notice identifier when available.
Bits/Cheers populate hasDonation (for example “500 bits”) even though data.event remains empty; rely on that field when rendering donation widgets. Subscriber streak information appears in subtitle when badges expose months.
Twitch – EventSub/Websocket
Implementation: sources/websocket/twitch.js with shared core providers/twitch/chatClient.js
Events delivered by EventSub, plus Helix polling for viewer/follower/subscriber totals.
WebSocket mode provides real-time follower alerts, subscription events, raids, cheers, Power-ups, channel point redemptions, and hype train metadata.
Shared Chat rows use Twitch IRC source-room-id to populate sourceName/sourceImg with the originating channel when it differs from the connected channel.
Viewer-shared Watch Streak notices are disabled by default and require the Show Twitch Watch Streaks setting.
The opt-in PluralMind setting may replace chatname, nameColor, and the proxy-wrapped portion of chatmessage, and may add a pronoun text badge. username and userid retain the Twitch identity; related deletes carry delete.meta.pluralmind so the dock uses those stable fields.
Event
When it Fires
Payload Notes
cheer
Cheer notifications from IRC or EventSub channel.bits.use.
hasDonation “N bits”; meta.bits numeric; chatmessage preserves raw message; identified cheerers include chatimg.
powerup
Built-in or custom Power-up notifications from EventSub channel.bits.use.
Event-only payload with an empty chatmessage and no hasDonation, so it does not create a normal chat row. meta.bits is numeric and meta.powerUp preserves the Twitch subtype, title/reward id, effect details, and supplied message text when available.
new_subscriber
channel.subscribe or USERNOTICE with msg-id=sub.
meta includes { userId, tier, isGift }; the cached subscriber total increments when available; viewer totals are polled separately.
resub
channel.subscription.message or USERNOTICE msg-id=resub.
meta carries streak and cumulative months; chatmessage includes the resub text.
subscription_gift
channel.subscription.gift or USERNOTICE msg-id=subgift.
meta exposes gifted total and tier; chatmessage summarizes the action.
meta includes reward id, title, cost, prompt, user input, redemption id/status, and legacy alias. No top-level reward object is emitted by this EventSub handler. Older consumers may still surface channel_points as a deprecated alias.
raid
EventSub channel.raid or USERNOTICE msg-id=raid.
meta = { fromId, fromLogin, viewers }.
watch_streak
Opt-in Twitch IRC USERNOTICE with msg-id=viewermilestone and msg-param-category=watch-streak.
Includes the viewer in chatname, Twitch's notice text in chatmessage, and meta.streakCount/meta.milestoneId. Other generic USERNOTICE types remain ignored.
new_follower
channel.follow EventSub notifications.
Auto-increments follower_update; meta records { userId, followedAt }.
viewer_update
Helix streams poll every 30 seconds.
meta integer viewer count; suppressed unless viewer stats enabled in settings.
follower_update
Helix follower total, triggered after follow events or periodic poll.
meta integer follower count.
subscriber_update
Helix subscriber total (requires broadcaster token with subscription scope).
meta integer subscriber count.
stream_online / stream_offline
EventSub stream.online/stream.offline.
meta.startedAt present for online events; offline uses empty object.
ad_break / ad_request / ad_schedule
Ad manager API responses (channel.ad_break.begin, manual POST channels/ads, GET channels/ads).
meta details duration, requester, and schedule payload for dashboards.
hype_train
EventSub channel.hype_train.begin, channel.hype_train.progress, and channel.hype_train.end v2 notifications.
Metadata-only event: no chatname or chatmessage. meta.phase is begin, progress, or end; meta includes train id, level, progress, goal, total, contributors, timing fields, shared-train flag, and trainType. Treasure trains are surfaced through meta.trainType when Twitch labels them.
user_banned
EventSub channel.ban, or IRC CLEARCHAT fallback when EventSub ban events are unavailable.
Metadata-only event for moderation widgets. meta includes username/display name, user ID, avatar/profile URL, moderator, reason, ban/timeout duration, and permanence.
Chat payloads reuse the shared provider, so data.event is populated for `/me` (action) and legacy bits tags even outside EventSub flows. Twitch GIF messages put the Giphy asset in contentimg, leave chatmessage empty, and preserve Twitch's fallback label in meta.gifLabel. Dedupe and deletion logic uses message IDs; messages sent through SSN use the native message_id from Twitch's IRC echo in data.id.
Twitch Hype Train Metadata
hype_train is metadata-only and does not include chatname or chatmessage. Dashboards should update an existing train display by meta.id instead of appending each progress update as chat. The Meta Data Bar (meta.html) renders these events as a top progress bar.
Field
Type
Notes
type
string
Always twitch.
event
string
Always hype_train.
meta.phase
string
begin, progress, or end.
meta.id
string
Stable train id. Use this to upsert/update one visible train widget.
meta.broadcasterUserId
string
Twitch broadcaster user id.
meta.broadcasterUserLogin
string
Twitch broadcaster login.
meta.broadcasterUserName
string
Twitch broadcaster display name.
meta.total
number | null
Total support value reported by Twitch for the train.
meta.progress
number | null
Current progress toward the level goal.
meta.goal
number | null
Current level goal.
meta.progressPercent
number | null
DOM fallback percentage when Twitch only exposes the visible popout progress bar.
meta.level
number | null
Current or ending train level.
meta.topContributions
array
Top contributors. Each entry includes userId, userLogin, userName, type, and numeric total.
meta.lastContribution
object | null
Most recent contribution, using the same contribution shape as topContributions.
meta.sharedTrainParticipants
array
Raw shared-train participant data from Twitch when provided.
meta.startedAt
string
ISO timestamp for train start.
meta.expiresAt
string
ISO timestamp for current train expiry.
meta.endedAt
string
ISO timestamp for train end, or empty before end.
meta.cooldownEndsAt
string
ISO timestamp for cooldown end, or empty before end.
meta.isSharedTrain
boolean
True when Twitch marks the train as shared.
meta.trainType
string
Usually regular; treasure trains are surfaced here when Twitch labels them.
meta.allTimeHighLevel
number | null
All-time high train level when Twitch provides it.
meta.allTimeHighTotal
number | null
All-time high train total when Twitch provides it.
meta.sourceMode
string
Optional source marker such as dom.
meta.eventSubType
string
Original EventSub type: channel.hype_train.begin, channel.hype_train.progress, channel.hype_train.end, or dom.community_highlight.
Twitch EventSub: Event Quick Reference
data.event
Scenario
new_follower
User followed channel
new_subscriber
New subscription
resub
Resubscription with message
subscription_gift
Gifted subs to channel
cheer
Bits cheered
powerup
Built-in or custom Power-up used
reward
Channel point redemption
raid
Incoming raid
viewer_update
Concurrent viewer count
follower_update
Total follower count
subscriber_update
Total subscriber count
stream_online
Stream went live
stream_offline
Stream ended
ad_break
Ad break started
hype_train
Hype Train/Treasure Train status metadata
user_banned
User was banned or timed out
OBS Flow Actions
Implementation: actions.html through OBS WebSocket v5 events, with dock.html OBS Browser Source events as a fallback
Keep the Flow Actions overlay open with the same Social Stream session as the Event Flow editor/background, or keep the dock loaded inside OBS.
Configure OBS WebSocket v5 on OBS 28+; the default URL is ws://127.0.0.1:4455.
These are Event Flow system events. They do not include chatname or chatmessage, and extra OBS details stay inside meta.
Event
When it Fires
Payload Notes
stream_started
OBS reports the stream output reached the started state.
type is obs; event is stream_started; meta.source is obs-websocket or obs-browser-source; meta.outputState may carry the raw OBS output state.
stream_stopped
OBS reports the stream output reached the stopped state.
type is obs; event is stream_stopped; meta.outputActive may be false.
recording_started
OBS reports recording started.
type is obs; meta.obsEvent identifies the OBS event source.
recording_stopped
OBS reports recording stopped.
type is obs; meta.outputState may carry the raw WebSocket state.
scene_changed
OBS changes the active program scene.
type is obs; meta.sceneName contains the scene name when OBS provides it.
media_ended
An OBS media input finishes playback.
type is obs; meta.inputName and meta.inputUuid identify the media input.
replay_buffer_saved
OBS saves the replay buffer.
type is obs; meta.savedReplayPath may contain the saved replay path.
Streamlabs Alert Box
Implementation: sources/streamlabs.js (alert-box DOM); optional socket bridge at sources/websocket/streamlabs.html
Keep your Streamlabs alert box open in a tab or browser source so alerts render; the content script reads the alert DOM for message/image/tokens.
Donation-style alerts set hasDonation (e.g., “$10 USD” or “100 bits”) and optional donoValue in USD.
For the socket bridge, paste your Streamlabs Socket API token and connect; alerts relay without the alert-box page.
Event
When it Fires
Payload Notes
donation
Tips, charity, JustGiving, or generic “donated” alerts.
hasDonation preserves the currency text (e.g., “$36” or “$10 CAD”); donoValue is supplied only when a USD value is available; other labelled amounts use shared currency conversion.
cheer
Twitch bit/cheer alerts.
hasDonation becomes “100 bits” and donoValue captures the USD value.
subscription
Subscription alerts.
Standard fields set; chatmessage is the alert line; meta.tokens carries tokenized values (name, amount, levelName, etc.).
gift
Gifted memberships/subs.
meta.tokens.amount may show gift count; meta.tokens.levelName can hold tier.
follow
Follower alerts.
No donation fields; chatname reflects the alert name token.
raid
Raid alerts.
meta.tokens.count holds the raider count when present.
redeem
Cloudbot redemption alerts.
meta.tokens.product captures the redemption item.
merch
Merch purchase alerts.
meta.tokens.product contains the purchased item name.
superchat
Super Chat style alerts from YouTube or supported alert integrations.
hasDonation carries the amount; consumers may keep accepting legacy donation aliases.
sponsor
Sponsor/member style alerts surfaced by Streamlabs.
Standard fields; no donation unless the text includes an amount.
TikTok Live – DOM Capture and TikFinity Feed
Implementation: sources/tiktok.js for native TikTok pages and sources/tikfinity.js for TikFinity's activity-feed widget/iframe. SSApp still has a native TikTok integration with the widest event coverage (see SSApp docs). Standard chat includes meta.messageId when the page exposes a native message ID; distinct messages with identical text retain distinct IDs.
Works on the broadcaster's live page. Gift/like/follow banners only populate when the session is authenticated.
TikTok provides many events via DOM detection without requiring WebSocket mode – gifts, follows, likes, and opt-in joins are captured from rendered rows.
TikFinity widget pages at tikfinity.zerody.one/widget/activity-feed* also work. The embedded activity-feed iframe emits the same canonical TikTok payload fields for chat, follows, shares, gifts, subscriptions, opt-in joins, and treasure chests.
No additional API authentication required.
SSApp native mode still adds events beyond the page/widget capture paths: question_new, emote, viewer_update, and the opt-in aggregate likes_update.
Event
When it Fires
Payload Notes
gift
Gift banner rows or DivGiftMessage entries.
hasDonation converts to “N coins” (with gift lookup fallback); membership uses badge text when available.
joined
Join notifications when the global Capture "joined" stream events setting is enabled.
Skips share notifications; chatname might be empty for some system strings.
followed
Follow messages parsed from social cards.
Ensures chatname exists before emitting.
shared
TikFinity share rows.
chatmessage is the rendered share text.
subscribe
TikFinity subscription rows.
membership is set to SUBSCRIBER.
envelope
TikFinity treasure chest rows.
meta.coins and meta.canOpen carry the chest details.
liked
Like storm summaries triggered by TikTok social cards.
chatname is included when TikTok exposes it; anonymous/system like cards may still emit. TikTok sends this through the normal background path. The background routes one copy to the Reactions Overlay, then continues to the main chat/events pipeline only when capturelikeevent is enabled.
likes_update
SSApp receives an authoritative cumulative TikTok LIVE total while captureliketotals is enabled.
meta is the current total integer. SSApp sends the first value immediately, coalesces bursts to at most one update every five seconds, repeats the latest value about every 90 seconds, and sends zero when the stream ends. This is separate from viewer-specific liked events.
true (boolean)
Generic social/system broadcasts where TikTok provides no subtype.
Use chatmessage content to decide presentation; boolean true indicates “system event – type unknown”.
membership mirrors badge tooltips (subscriber tiers). Avatar caching keeps chatimg valid between events; if the DOM suppresses color for moderators the script clears nameColor. TikFinity Activity Feed capture supports legacy docks and the new widgets.tikfinity.com browser-source URLs. New stream_event messages are translated into the same chat, gift, follow, share, subscription, join, and envelope payloads described here. TikFinity gift rows also set contentimg to the gift icon when available. For explicitly streakable gifts with a repeatEnd flag, TikFinity sends only the completed streak and its final quantity; intermediate count updates are not forwarded. Non-streak gifts and older payloads without that flag continue through immediately. Native DOM gift streak updates and TikFinity gift rows include meta.tiktokGiftStreakId, meta.tiktokGiftCount, and meta.tiktokGiftQuietMs so overlays can coalesce repeated updates; legacy streak IDs are unique to the page instance. Gift metadata may also include tiktokGiftMessageId (the original TikTok message ID), tiktokGiftSenderId, groupId, giftId, giftName, streakable, and repeatEnd. Native IDs identify the same gift across capture windows; a nonzero group ID with sender and gift IDs identifies cumulative streak updates. SSApp WebSocket capture supplies the same fields after settling a streak, with count retained for compatibility. Its donation toggle is checked when forwarding each gift: disabling TikTok donations removes hasDonation and donoValue while retaining the gift event and metadata. TTS uses these identities to coalesce updates and suppress completed duplicates for up to ten minutes (bounded cache), and reads TikTok gifts as sender, quantity, and gift name. Older payloads fall back to their existing streak IDs and message text; no identity is inferred from gift text alone. TikTok gift speech uses the selected TTS/voice language, independently of the UI language. Announcement verbs are localized for English, Spanish, Portuguese, French, German, Italian, and Dutch; other languages use sender, quantity, and gift name without an English verb. Simplified TTS retains that neutral format. Gift names remain as supplied by the platform; this does not automatically translate gift catalogs or chat messages, or infer a stream’s language.
For these streak updates, the count and donation label are cumulative: 1, 2, 3 means three gifts, not six. Totals consumers should add only the increase over the largest amount already seen for that streak ID. Standard capture supports legacy gift classes and current image/count rows; both retain event: "gift" and hasDonation. Unknown prices retain gift counts/names for display and use a USD estimate of one coin per gift. Source-supplied donoValue takes priority; rendered gift metadata may provide coinsPerGift or diamondsPerGift before the gift table or default is needed. Standard/TikFinity coin estimates and SSApp native diamond estimates use their existing distinct conversions; neither represents a guaranteed cash payout.
Whatnot
Implementation: sources/whatnot.js
Use the Whatnot source in SSApp for public chat and auction events without video, or open the live show page for website capture. Both connect to the public auction feed. Website capture also reads rendered auction and catalog sections.
Capture Stream Events controls Whatnot system events plus auction/catalog metadata updates; joined rows also require Capture "joined" stream events; viewer counts still follow the viewer/hype toggles.
Event
When it Fires
Payload Notes
viewer_update
Viewer count changes from websocket livestream updates, with DOM polling as a fallback.
meta is an integer viewer count.
donation
Whatnot websocket tips and community boost contribution events.
hasDonation contains the formatted amount; websocket-specific context stays under meta.
raid
Whatnot websocket raid events, including backlog activity replies.
meta.numRaiders is included when Whatnot supplies it.
joined
Chat rows whose normalized body starts with joined, when Capture "joined" stream events is enabled.
Uses string event labels for join notices (not boolean true).
auction_update
When the live footer auction state changes (winner/winning text, title, bids, price, timer, sold state), often accelerated by websocket auction lifecycle packets.
Metadata-only event. No chatname/chatmessage; data lives in meta (for example meta.title, meta.bids, meta.price, meta.timer, meta.status).
commerce_update
When catalog sections change (products, surprise sets, upcoming giveaways), often accelerated by websocket giveaway/product lifecycle packets.
Metadata-only update. Website section snapshots use meta.products, meta.surpriseSets, and meta.upcomingGiveaways. Public giveaway updates use meta.giveaway.productId and meta.giveaway.entryCount. Pinned-item updates use meta.pinnedItems, containing the supplied type, ID, product ID, or name. meta.websocketEvent identifies giveaway_entry_count_updated or pinned_item_updated; unchanged states are suppressed.
The corresponding live websocket notification arrives. These are individual events, separate from the existing display snapshots.
platform/type: "whatnot", plain-text chatname, userid when supplied, product name in subtitle, and a plain-text chatmessage with textonly: true. Available identifiers and auction details are under meta: productId, auctionId, orderId, transactionId, livestreamId, bidId, bids, auctionEndTime, and status. Optional price is in major currency units, with priceText and currency when supplied.
giveaway_started, giveaway_won
The public auction feed announces a giveaway start or winner.
Uses the auction event fields for the supplied product and winner. meta.entryCount contains the entry count when supplied. Entrant lists and raw order details are not forwarded.
payment_failed
A live payment-failure websocket notification arrives.
The same available buyer, product and identifier fields, with meta.paymentStatus: "failed". When only product.purchaserUserId identifies the buyer, it fills userid on sale/payment events and the buyer name stays empty. No buyer is inferred from a different or previous auction.
payment_succeeded
A live payment-success websocket notification arrives.
meta.paymentStatus: "succeeded", with the buyer, item, order ID and other allowed fields supplied by that notification. This remains a distinct payment event; it does not emit another purchase or donation. Missing fields stay empty or omitted, even if an earlier sale supplied them.
Auction/commerce display updates remain DOM-backed snapshots. To match an individual websocket event in Event Flow, use Event Type (Advanced), select Custom Event, and enter its exact name. Labels can use **{username}**\n{subtitle} with selected text weight; conditions can compare meta.paymentStatus with failed. An importable Whatnot label example is available. Existing stream-event capture settings still apply.
Additional optional fields are meta.catalogProductId (the packet's product.productId), meta.parentProductId (product.parentId), meta.transactionType (Whatnot's sale type, unchanged), and meta.placeOrderErrorReason (Whatnot's supplied order/payment error code). These product references describe the catalog or parent listing; they do not replace an order ID. Stock quantity is not treated as purchased quantity.
For payment-success automation, set an Event Type (Advanced) trigger to Custom Event: payment_succeeded, and filter the source to Whatnot. Existing conditions and templates can use that event's userid, chatname, subtitle and meta.orderId directly. No remembered purchase is needed when the notification contains the required details.
An auction ending or an item being marked sold does not confirm successful payment: these notifications are not emitted as paid purchase events and do not set donation amounts. A success event is emitted only for a received payment_succeeded notification; capture does not poll for payment completion or infer it from a sale. Other paymentStatus values are forwarded only when explicitly supplied in a captured packet. Missing identifiers are omitted; a product ID alone may cover multiple sales, so use a supplied order/auction ID to correlate notifications. Capture does not remember purchases or match payment updates; any such workflow must be explicitly configured in Event Flow. Repeated commerce notifications with the same native event timestamp/ID are suppressed across overlapping channels and reconnects, within a 2,000-event cache. Packets without a native event identity use a brief duplicate window. Raw order/payment objects are not forwarded.
eBay Live
The Monetization eBay seller connection requires a configured SSN eBay service and seller OAuth consent; eBay Live capture below is independent. Sandbox mode uses sandbox listing URLs, labels the buyer "eBay Sandbox buyer", and prefixes the message with "Sandbox test purchase:". Sandbox purchases retain the same purchase contract and can trigger enabled alerts/chat actions during testing. Its implemented payment contract emits event: "purchase", with type and platform set to ebay. It requires a paid order matching a selected product. id is a stable opaque order-line identifier; chatname is "eBay buyer", chatmessage is plain text (textonly: true), subtitle is the product name and optional contentimg is its image. meta.ebayPurchase contains itemId, itemName, quantity, and public url. No buyer identity, shipping data, hasDonation or donoValue is included. This differs from scraped auction or stock updates, which do not prove payment.
Implementation: sources/ebay.js
Open either /ebaylive/events/<id>/chat or /ebaylive/events/<id>/stream. Both receive the same live auction feed.
The public WebSocket feed supplies auctions, bids, winners, timing extensions and stock changes; a read-only GraphQL query supplies listing details. DOM capture remains a fallback when network data is unavailable.
When the active event viewer count changes (header count or live event pill fallback).
meta is an integer viewer count.
follower_update
When the seller follower count is returned from the seller stats endpoint.
meta is an integer follower count. The source polls the seller endpoint every 60 seconds; the endpoint may still return a cached value for up to 5 minutes.
auction_update
When active auction metadata changes.
Metadata-only event. Network capture sets meta.sourceMode to network and supplies title, price, bidder, winner, bids, timer and endingAt. meta.ebay contains eventId, listingId, the GraphQL listing record (listing), current public socket listing (eventListing), and latest auction update (update). These preserve category, images, currencies, quantities, case-break details, auction results and timing fields without flattening away platform detail. The GraphQL record is a fetched snapshot; the socket listing and update carry newer live state. Initial/reconnect history is folded into the current snapshot rather than emitted as old wins. Removing all presented listings emits status: "idle" with cardCount: 0 to clear the auction. DOM fallback retains player-card or event-preview fields.
commerce_update
When catalog/live-event snapshot sections change.
Metadata-only snapshot under meta. Network mode includes eventId, navigation.viewerCount and playerCards for the currently presented listings, each with the same detailed ebay object as an auction snapshot. An empty card list clears removed listings. DOM fallback may also include liveEvents, livePreview, currentEvent and upcomingEvents.
reaction
When eBay Live renders a heart/reaction animation.
Sent directly to the dedicated reactions target. meta.reactionType is heart; eBay does not expose a per-user name for these DOM animations.
eBay metadata events intentionally omit chatname/chatmessage; downstream overlays should render from data.event + data.meta only.
Kick – Standard DOM Capture
Implementation: sources/kick.js. Chat includes meta.messageId when the page exposes a native message ID.
Needs an authenticated session to resolve profile images and subscriber badges.
Limited event detection via chat text matching and badges; viewer counts still work when the toggle is enabled.
Event
When it Fires
Payload Notes
gift
KICKs gifts detected via the sticker image and visible Kick currency amount.
hasDonation carries N KICKs (1 KICK for one) when the visible amount is available; contentimg carries the gift image. Existing message text is preserved.
reward
Reward redemptions ("has redeemed …").
chatmessage contains redemption text.
true (boolean)
Generic system notices that don’t match gift or reward patterns.
Use chatmessage content to decide presentation; boolean true indicates "system event – type unknown".
viewer_update
Polls Kick’s channel API every 30 seconds (only when viewer stats are enabled).
meta integer viewer count; for subs, follows, or tips use the Kick bridge below.
Kick – Websocket/Bridge
Implementation: sources/websocket/kick.js with shared helpers under providers/kick/core.js
OAuth via the Social Stream Kick bridge. Current scopes are user:read, channel:read, channel:write, channel:rewards:read, chat:write, events:subscribe, moderation:ban, moderation:chat_message:manage, and kicks:read. Tokens are refreshed automatically.
Kick webhook provisioning may take several minutes; the UI lists active subscriptions per channel.
Event
When it Fires
Payload Notes
message
Bridge chat payload.
meta.plainText contains the plain-text message (which may still include emoji); badges merge platform + profile cache. Thread replies populate initial, reply, and meta.reply when reply details or a cached parent message are available.
reward
channel.reward.redemption.updated, plus bridge chat/system payloads that look like redemptions.
meta includes reward/redemption id, title, cost, status, user input, and redeemer.
new_subscriber
channel.subscription.new.
membership assigned to subscriber role; meta includes { subscriber, plan }.
resub
channel.subscription.renewal.
meta.duration (months) and meta.plan available; subtitle summarizes streak.
subscription_gift
channel.subscription.gifts.
meta.totalGifted, meta.gifter; badges fallback to 💝 icon.
donation
Support/tip events detected via event type heuristics; KICKs gifts use gift below.
hasDonation carries the formatted amount; meta contains { amount, currency, supporter, message, giftName }.
gift
kicks.gifted (KICKs gifts), matching the DOM scraper.
hasDonation carries N KICKs (1 KICK for one); contentimg carries the gift image when available. Structured gift details remain under meta.
raid
Compatibility handling for legacy host-shaped socket payloads such as App\Events\StreamHostEvent.
Kick's current official event catalog has no raid/host subscription. If a compatible legacy payload arrives, it maps to canonical raid; do not depend on this for a current Kick workflow.
new_follower
channel.followed.
Follower icons derive from profile cache; follower_update fires when Kick provides running totals.
follower_update
Bridge supplies follower counts in webhook payloads.
meta integer total; used by dashboards for follower goals.
stream_online / stream_offline
livestream.status.updated.
meta contains the raw status body from Kick (is_live, title, etc.).
viewer_update
livestream.status.updated when Kick includes concurrent viewer totals.
meta integer viewer count; emits 0 on offline status to clear stale counters.
user_banned
moderation.banned from the bridge/webhook, or Kick chat socket ban events.
Metadata-only event for moderation widgets. meta includes username/display name, user ID, avatar/profile URL, moderator, reason, ban/timeout duration, and permanence.
Profile lookups leverage profileCache; mapBadges merges Kick's badge assets with cached SVG when available. When Kick reports donations in KICKs, the bridge converts them into hasDonation plus meta.amount with currency fallback to "KICKs". Chat payloads include meta.messageId when the bridge exposes a native Kick message ID so delete sync can target the correct message. Reply payloads include meta.reply with the parent messageId, author, and text when known. Supplied reply details remain available even when the original message is not cached; an ID-only reply without cached context can still lack a visible quote.
Kick Websocket: Event Quick Reference
data.event
Scenario
new_follower
User followed channel
new_subscriber
New subscription
resub
Subscription renewal
subscription_gift
Gifted subs
reward
Channel reward redemption or reward-style chat/system message
donation
Tip/support event
gift
KICKs gift event
raid
Compatibility-only legacy host/raid input; not a current official Kick subscription
follower_update
Total follower count
stream_online
Stream went live
stream_offline
Stream ended
user_banned
User was banned or timed out
VPZone - WebSocket
Implementation: sources/websocket/vpzone.js
Connects to wss://chat.vpzone.tv/ws?channel=USERNAME; OAuth requests profile:read, chat:read, chat:write, channel:read, channel:write, and chat:moderate. A bearer token can also be supplied manually.
Flat VPZone frames such as type: "msg" are normalized into standard chat payloads.
Platform-side delete_message / clear_chat frames remove the matching rows from the dock; optional toggles sync dock deletes and blocks back to VPZone (channel owner only).
Channel owners get a page-local Stream Info panel to update the live stream's title and category (same pattern as the Twitch source page).
Event
When it Fires
Payload Notes
message
VPZone msg, message, new_message, or chat_message websocket frame.
chatname comes from username; chatmessage comes from body; subscriber/owner/mod/VIP flags are copied into chatbadges, top-level role flags, and meta. Native IDs populate data.id and meta.messageId.
viewer_update
VPZone presence frame with count or equivalent viewer field.
meta is the live viewer integer; contributes to aggregated viewer_updates.
new_subscriber
VPZone subscribe / subscription frame.
membership is set to Subscriber when subscription flags are present.
subscription_gift
VPZone gift / gift_subscription frame.
Uses the same gifted-sub event name as Twitch, Kick, Rumble, and Velora. subtitle carries the gift count (x5) or recipient.
message + hasDonation
VPZone system frame with metadata.kind: "pixels_cheer" (Pixels tip).
Donation-bearing chat row; hasDonation is the amount label (for example 100 Pixels), meta.pixels the integer. event stays blank; detect this tip from hasDonation. Kick bridge support events instead use event: "donation".
Rendered like Kick replies: initial holds the "author: excerpt" label, reply the raw reply text, meta.reply the structured target. Respects the exclude "replying to" setting.
raid
VPZone raid frame with metadata.kind: "incoming".
Outgoing raid frames are skipped; meta.viewers carries the raid size when provided.
shoutout
VPZone shoutout frame (!so command).
meta.targetUser names the shouted-out channel.
reward
VPZone system frame with metadata.kind: "channel_points_redeem".
Channel-point redemption, using the same event name as Twitch rewards.
stream_online / stream_offline
VPZone system frames with metadata.kind: "stream_started" / "stream_ended".
Attributed to the channel name (the frames carry no actor).
new_follower
VPZone follow frame.
Mapped into the standard follower event shape.
joined
VPZone join/presence-style websocket events, when Capture "joined" stream events is enabled.
Mapped into a chat-style system event with VPZone actor metadata under meta.
Joystick
Implementations: sources/joystick.js, sources/inject/joystick-ws.js, and sources/websocket/joystick.js
The normal Joystick 2.0 website source runs on the signed-in /u/<channel>/chat page. It reads the page's ChatChannel, WhisperChatChannel, EventLogChannel, and SystemEventChannel Action Cable frames, with a rendered-row fallback for Electron and reconnect cases.
Website chat messages use the same core fields as YouTube, Twitch, and Kick: native id, chatname, chatmessage, chatimg, chatbadges, nameColor, membership, mod, private, username/userid, and timestamp when Joystick supplies them. When the socket omits a username color, the rendered row supplies the same nameColor field used by color-enabled docks.
Website-side message edits replace the matching dock row; deletes, mutes, and blocks remove matching rows using the native ID or username.
The separate WebSocket source uses Joystick bot credentials (client_id + client_secret); the website source uses the signed-in page session.
Authorizes on https://joystick.tv/api/oauth/authorize, then exchanges/refreshes tokens at https://api.joystick.tv/api/oauth/token.
Connects to wss://api.joystick.tv/cable and subscribes to GatewayChannel.
Optional OAuth token exchange is used for helper endpoints like https://api.joystick.tv/api/users/stream-settings.
The separate bot-credential source does not emit viewer_update. The signed-in website source does emit viewer counts when its page socket supplies them, as described below.
Event
When it Fires
Payload Notes
message
Joystick ChatMessage, BotMessage, new_message, bot_message, event_bot_message, pvp_message, and whispers.
Regular chat has no event. The native ID is placed in top-level id and meta.messageId; roles and private state use the established top-level/badge fields.
new_follower
Joystick StreamEvent with type Followed.
Uses the standard follower shape and is deduplicated against Joystick's matching bot row. Optional meta.userId/meta.followedAt are included only when Joystick supplies them.
Uses the Kick-compatible subscription metadata keys: eventType, subscriber, gifter, totalGifted, duration, and plan.
donation
Joystick StreamEvent types Tipped / TipMenu.
hasDonation carries the token amount and unit for shared USD conversion when available, and the matching Joystick bot row is deduplicated. meta uses the established Kick support-event keys: eventType, supporter, amount, currency, message, giftName, giftType, and tier.
stream_online / stream_offline
Joystick StreamEvent types like Started, StreamResuming, Ended, StreamEnding.
Used for transport-aware online/offline automations.
Presence notifications are emitted as event messages and can be suppressed by hide-events settings. Hide-events also suppresses non-donation stream events.
viewer_update
The signed-in website source receives ViewerCountUpdated through EventLogChannel.
Uses a plain integer meta, matching YouTube, Twitch, and Kick. Emitted only when viewer-count or hype mode is enabled. The separate bot-credential source still does not receive viewer counts.
follower_update / subscriber_update
Joystick follower/subscriber count-update events.
Uses a plain integer meta, matching the Twitch counter contract.
Ignored internal notifications
ChatMessageReceived, device state, and unmapped widget refreshes such as tip-goal/PvP/subathon state.
These are transport or page-state notifications, not Social Stream events. They are not converted into invented snake_case event names; the real ChatChannel/new_message row remains the single chat payload.
XP Sync
Implementation: sources/xpsync.js
Chat rows use the canonical payload fields with type: "xpsync", including author, message, avatar, image and inline SVG badges, name color, membership, moderator/member/bot flags, and the native message UUID as id when available.
Replies follow the YouTube, Twitch, and Kick DOM-source convention: unless reply prefixes are disabled, initial contains the replied-to user, reply preserves the unprefixed message, and chatmessage receives the visible reply prefix.
Sparks-highlighted rows are captured even though XPSync renders them without the normal chat row class or message id; the visible amount is exposed through hasDonation as N Sparks.
When event capture is enabled, rows containing “just followed” or “followed the channel” emit event: "new_follower".
When viewer counts are enabled, the permanent chat dock emits event: "viewer_update" from the live-video count already loaded by the XPSync page and refreshes it from XPSync's live page updates. No separate SSN credentials are required.
Instagram – Live REST Capture and News Inbox
Implementation: sources/instagram.js and sources/instagramlive.js (identical copies)
On live pages (/<user>/live/?broadcast_id=...), live chat comes from Instagram's own web API, polled same-origin with the session cookie: GET /api/v1/live/{broadcast_id}/get_comment/?last_comment_ts={ts} every ~2s, and POST /api/v1/live/{broadcast_id}/heartbeat_and_get_viewer_count/ every ~5s when viewer counts are enabled. After 3 consecutive failures (or when no broadcast_id is discoverable) the source falls back to parsing the rendered chat DOM.
The account's own activity feed is polled via POST /api/v1/news/inbox/ every ~45s on any Instagram page. The first poll only seeds the dedupe set so backlog is never replayed; stories dedupe by tuuid.
All activity-feed events use type: "instagram"; live chat stays type: "instagramlive". Like events use the normal background path: the background sends one copy to the dedicated Reactions Overlay, then includes them in the main chat/events feed only when capturelikeevent is enabled, matching TikTok and MeetMe. hideevents and the custom event filter block them everywhere. Because inbox events belong to the signed-in account, they are suppressed while watching someone else's live (both /<user>/live/ pages and lives in the stories viewer; ownership is resolved per profile and retried after lookup failures) and emitted on your own live and all non-live pages. One active Instagram tab polls the account inbox at a time, and polling only runs when logged in.
Event
When it Fires
Payload Notes
message (live)
New entries in the get_comment response (comments[]/system_comments[]), or new DOM chat rows when REST is unavailable.
Standard chat payload, type: "instagramlive". REST provides exact user.username, user.profile_pic_url, and a unique pk used for dedupe.
viewer_update
heartbeat_and_get_viewer_count reports a changed viewer_count, when viewer-count capture or hype mode is enabled.
meta integer viewer count. Polling stops when broadcast_status is no longer "live".
stream_online / stream_offline
stream_online fires once when a REST broadcast session starts; stream_offline fires when the heartbeat reports a non-live broadcast_status (requires viewer-count capture or hype mode).
Metadata-only events matching the shared stream-status vocabulary used by Twitch and Joystick.
new_follower
A news-inbox story with a follow-type notif_name (or story_type 12) appears.
chatname is the new follower, chatimg their profile image, chatmessage the inbox text (for example "x started following you.").
follow_request
A private_user_follow_request story appears (private accounts receive requests instead of direct follows).
Same shape as new_follower, kept distinct so automations can approve requests or greet differently.
liked
A news-inbox story with a like-type notif_name (including comment_like) appears.
Shared like vocabulary with TikTok/MeetMe. chatname is the actor, chatmessage the inbox text (for example "x liked your photo.").
message (comment on own post)
A news-inbox story with a comment-type notif_name appears.
Plain chat row (event: false), type: "instagram"; chatmessage carries the inbox text including the comment excerpt.
notification
Any other news-inbox story type (mentions, tags, shopping, and so on).
Generic catch-all; meta.notifName and meta.storyType preserve the raw story classification.
Facebook Live
Implementation: sources/facebook.js (DOM scraping) and optional Graph API bridge at sources/websocket/facebook.html
DOM capture reads rendered Facebook comments; the managed-Page Graph API bridge reads video comments. Both use type: "facebook", the standard chat fields, and no event for ordinary comments. The API bridge also includes the optional platform: "facebook".
The API bridge uses userid for the author ID when available, timestamp for a valid creation time in Unix milliseconds, and contentimg for an HTTP(S) attachment image supplied by the API. Image-only comments may have an empty chatmessage. textonly applies only to the message body: raw text when true, escaped HTML when false.
API comment context uses meta.messageId (native comment ID), meta.permalink, meta.videoId, and meta.pageId. Earlier API builds used meta.commentId, duplicated author/time fields under meta, and passed raw attachments there. New builds use the standard author/time/media fields instead; this does not add delete-sync support.
Viewer counts refresh only when enabled. The API bridge reads concurrent live_views; it does not substitute cumulative video views or invent a zero for an unavailable count. API capture does not infer Stars, memberships, highlights, or replies from ordinary comment text.
Stars are captured from the rendered Live Chat DOM when Facebook shows the visible N sent marker; they populate hasDonation and donoValue at 100 Stars = $1 USD without setting data.event.
For testing, add ssnreplay=1 to the Facebook Live URL to process chat rows already visible after refresh.
Event
When it Fires
Payload Notes
viewer_update
DOM polls the live viewer badge; the API bridge polls concurrent live views when enabled.
meta integer viewer count, matching other sources. Missing or unparseable counts are skipped; an actual zero is valid.
hasDonation
Facebook Stars rendered in the Live Chat DOM.
Standard chat payload; hasDonation carries the visible Stars amount, such as 100 Stars, and donoValue carries the USD value. Stars do not set data.event.
highlightColor
Facebook renders a visible HIGHLIGHTED label.
Uses the normal chat fields and highlightColor; no data.event is set. Stars still use hasDonation.
Online Church
Implementation: sources/onlinechurch.js
Relies on DOM scraping of the public chat and media header.
Viewer counts only refresh when Show viewer count or hype mode is enabled.
Event
When it Fires
Payload Notes
message
New entries appear under #publicchat.
Standard chat payload with sender name, avatar, badges, and optional membership label when present in the DOM.
viewer_update
Polls the live occupancy badge in the media header every 10s.
meta integer viewer count; sends 0 when the badge is missing or unreadable to clear stale counters.
SharePlay.tv
Implementation: sources/shareplay.js
Desktop API implementation: ssn_app/resources/shareplay-client.js. The native SSApp source subscribes to the authorizing user's own channel using a staff-provisioned public OAuth client.
Relies on DOM scraping of the live chat drawer on SharePlay channel pages.
Only newly inserted chat rows and cards are emitted after the scraper attaches; the existing backlog is intentionally ignored.
The desktop API source receives new EventSub events; disconnected messages are not replayed. Chat carries SharePlay's message ID in id and sender ID in userid, but no avatars or badges. Emotes respect textonly; replies populate the existing reply fields when the parent is in the 200-message session cache.
The desktop API maps completed channel.blitz events to raid, chat shoutouts to shoutout, and stream.viewers to viewer_update when viewer counts or hype mode are enabled. API shoutouts contain the provided chat text without the DOM card's banner or button metadata. Synthetic chat/Blitz events preserve meta.is_synthetic: true; viewer updates retain integer meta.
Event
When it Fires
Payload Notes
message
New chat rows appear inside the main chat feed.
Standard chat payload with author, avatar, badge images, and HTML-preserved emotes. Thread replies also populate initial, reply, and meta.reply when the parent row is still present.
raid
SharePlay inserts a Blitz card into the live chat feed.
Mapped to the canonical raid event. meta.cardType is "blitz", with optional meta.fromLogin and meta.viewers when the card text exposes them.
shoutout
SharePlay inserts a shoutout/follow card into the chat feed.
Emitted as data.event = "shoutout". The card banner image is forwarded via contentimg, while meta.cardType and meta.action preserve the card label/button text.
viewer_update
Polls the visible header viewer badge every 10s.
meta integer viewer count; only emitted when Show viewer count or hype mode is enabled, and sends 0 if the badge becomes unreadable to clear stale counters.
Streamplace
Implementation: sources/streamplace.js
Reads Streamplace's React-rendered live page and skips the visible chat backlog when attaching.
Relay-style messages such as Name (Discord): message are normalized to the relayed sender name.
Event
When it Fires
Payload Notes
message
New Streamplace chat rows appear after attach.
Standard chat payload with nameColor, chatbadges, HTML-preserved links, and reply fields initial, reply, and meta.reply when visible.
viewer_update
The header viewer badge changes while viewer-count capture or hype mode is enabled.
meta integer viewer count.
WorldsWave
Implementation: sources/worldswave.js
Supports WorldsWave live pages and chat-only URLs such as https://worldswave.com/kn_livecmd.php?cmd=viewStream&streamId=STREAM_ID&chatonly=1.
Uses the stable data-ww-*/ww-chat-* markup when available, while retaining the legacy kontackt selectors for chat-only pages and older layouts.
Existing chat history is skipped when capture attaches; test with a new message.
Viewer counts require Show viewer count or hype mode. Dedicated gift/tip events and send-back are not implemented. A rendered row may still provide a donation label through data-ww-donation.
Event
When it Fires
Payload Notes
message
A new rendered WorldsWave chat row appears.
Standard chat payload with type: "worldswave", sender name, avatar, optional user ID, name color, badges, moderator state, membership, donation value, attachment, and channel identity. Stable WorldsWave message IDs are exposed as meta.messageId and deduplicated across simultaneous preview/full-chat panels. Inline message images remain sanitized when text-only mode is disabled.
viewer_update
The visible live viewer total changes while viewer-count capture or hype mode is enabled.
meta is the integer viewer count. The stable data-ww-viewer-count value is preferred; compact legacy values such as 1.2K are normalized as a fallback.
FLEX TV
Implementation: sources/flextv.js
Reads the rendered chat panel on https://www.flextv.co.kr/channels/*/live pages.
The chat panel must be visible. Existing chat history is skipped when the source attaches, so test with a new chat row.
No viewer count, donation, or send-back path is documented for this source yet.
Event
When it Fires
Payload Notes
message
New visible FLEX TV .chat-item rows appear in the live chat feed.
Standard chat payload with type: "flextv", chatname, chatmessage, nameColor, badge images in chatbadges, and FLEX member details under meta when exposed by data-member.
Seal Team Sloth
Implementation: sources/sealteamsloth.js
Reads the rendered pop-out chat on https://sealteamsloth.com/popout-chat/* pages.
Viewer counts require Show viewer count or hype mode.
Event
When it Fires
Payload Notes
message
A new rendered Seal Team Sloth chat row appears.
Standard chat payload with type: "sealteamsloth", sender name, avatar, and message content.
viewer_update
The visible live viewer total changes while viewer-count capture or hype mode is enabled.
meta is the integer viewer count; compact values such as 1.2K are normalized.
MeetMe - DOM and WebSocket Capture
Implementation: sources/meetme.js
Reads MeetMe's rendered live chat DOM on app.meetme.com/live/view/... pages and inside the api.gateway.meetme-live.com/web-live/... iframe.
When the iframe websocket is available, wss://video-live.meetme.com/ frames are parsed before the DOM fallback to capture richer live events.
hideevents suppresses non-donation events; MeetMe gifts and diamond donations still populate donation fields. capturejoinedevent enables join/rejoin notices. Actor-specific liked events use the shared background routing controlled by capturelikeevent; aggregate reaction effects remain explicitly targeted to the Reactions Overlay.
Viewer counts prefer the visible MeetMe header count, falling back to websocket totals only when the DOM count is unavailable. Counts emit on change and repeat the latest count about every 30 seconds while showviewercount/hypemode is enabled; follower totals are changed-only and rate-limited to roughly 60 seconds.
Event
When it Fires
Payload Notes
message
New SNSChatMessage websocket frames arrive, or new ChatMessage_* DOM rows appear under ChatHistoryContainer_*.
Standard chat payload with sender name, avatar, message HTML/text, and badge images/text. DOM row details are flat meta keys, including messageId, roomId, level, levelColor, badgeLabels, badgeSrcs, badgeClasses, isBouncer, isTopStreamer, isBestOfTheWeek, rank, and rowClassName. Websocket payloads set meta.source = "websocket".
joined / rejoined / left
SNSChatParticipant websocket create, update, or delete frames arrive, or MeetMe renders a DOM join-cell row. Joined/rejoined notices require Capture "joined" stream events.
Emits chat-style system notices with actor name/avatar when MeetMe exposes them. meta.isNewViewer, meta.viewerLevelId, meta.isBouncer, and meta.isSubscriber preserve participant state.
new_follower
MeetMe renders a DOM favorite/follow row such as Favorited.
Uses the shared follower event vocabulary. chatname is the actor, chatimg is the detected profile photo when available, and flat meta.favoriteText/meta.targetName preserve the original row details.
gift
SNSGiftMessage websocket frames arrive, or MeetMe renders a gift image in a chat row.
hasDonation carries the visible gift label or diamond value, contentimg carries the gift image when exposed, and flat keys such as meta.giftName, meta.giftCount, meta.amount, and meta.currency preserve structured details. The gift event is reserved for actual gift frames/rows; donation rendering should still key off hasDonation.
Dedicated diamond frames are treated as donation events. hasDonation is formatted as diamonds for shared USD conversion, and meta.amount/meta.currency stay flat for automations.
liked / reaction
SNSLike websocket frames arrive.
Actor-specific likes use the same liked vocabulary and centralized background routing as TikTok. Aggregate/anonymous like totals are sent only to the reactions target as reaction, with flat meta.reactionType, meta.totalLikes, and meta.subscriberLikes. The distinction is event meaning, not anonymity: capturelikeevent controls only individual liked/like events.
Metadata-only event for guest/live cohost state. Flat meta keys include status, position, totalGuests, isMuted, guestBroadcastId, videoViewerId, and broadcastId.
viewer_update
The visible header viewer badge changes, or SNSVideo websocket metadata exposes viewer totals when the badge is unavailable; unchanged totals repeat about every 30 seconds while enabled.
meta integer viewer count; only emitted when viewer-count capture or hype mode is enabled.
Velora
Implementation: sources/velora.js and sources/websocket/velora.js
Standard mode reads the visible chat DOM; WebSocket mode uses the Velora Events API with OAuth.
Supported Standard mode URLs include https://velora.tv/*, https://velora.tv/dashboard/stream/popout?panels=chat%2Cactivity&channel=CHANNEL&layout=vertical, and https://velora.tv/dashboard/stream/popout/CHANNEL/obs-chat.
Volts and channel point style cards are emitted as event payloads when exposed by the DOM or Events API.
Event
When it Fires
Payload Notes
message
New Velora chat rows appear or Events API chat messages arrive.
Standard chat payload with badges, author color, links, and emotes preserved when not in text-only mode.
volts
Velora Volts cards or channel.volts Events API payloads arrive.
hasDonation carries the displayed Volts amount; DOM captures include meta.source = "dom".
channel_points
Velora channel point/redemption cards or channel.channel_points_redemption Events API payloads arrive.
chatmessage carries the redemption message or reward title; meta.rewardTitle identifies the reward when available.
subscription
Visible Velora activity row says a user became a channel member/subscriber.
membership carries the visible membership label.
viewer_update
Visible viewer count changes while viewer-count capture or hype mode is enabled.
meta integer viewer count.
Parti - Profile / Popout Chat Capture
Implementation: sources/parti.js
Supports profile URLs like https://parti.com/USERNAME and popout URLs like https://parti.com/popout-chat?id=USER_ID.
Viewer counts use Parti's livestream heartbeat endpoint when viewer-count capture or hype mode is enabled.
Event
When it Fires
Payload Notes
message
Visible Parti chat rows appear in the profile or popout chat stream.
Standard chat payload; nameColor preserves Parti's rendered author color and chatmessage preserves inline content unless text-only mode is enabled.
donation
Visible Parti tip rows say a user tipped an amount.
hasDonation carries the displayed amount, meta.amount/meta.currency are populated when parsable, meta.amountText preserves the raw amount text, and donoValue is set for USD tips.
viewer_update
The Parti heartbeat returns a live viewer count.
meta is the integer viewer count; the page reuses one heartbeat token per source window to avoid inflating counts.
CHZZK - Popout Chat Capture
Implementation: sources/chzzk.js
Supports https://chzzk.naver.com/live/*/chat and https://chzzk.naver.com/iframe/live/*/chat.
Viewer counts use CHZZK's live-status polling endpoint when viewer-count capture or hype mode is enabled.
Event
When it Fires
Payload Notes
message
Visible CHZZK chat rows appear in the popout chat stream.
Standard chat payload with type: "chzzk", nameColor, badge image URLs in chatbadges, and rendered emotes in chatmessage unless text-only mode is enabled.
chat with hasDonation
Visible CHZZK cheese donation rows appear in chat.
hasDonation carries the displayed cheese amount. These rows do not set data.event.
viewer_update
The live-status poll returns a viewer count.
meta is the integer viewer count.
Rumble - Standard DOM Capture
Implementation: sources/rumble.js
Requires authenticated session cookies so the service.php viewer API responds.
Rendered Rant rows provide hasDonation; incoming raid cards provide event: "raid". This DOM source does not emit the API bridge's subscriber/follower event feed.
Event
When it Fires
Payload Notes
message
Visible Rumble chat rows appear in the page or popup chat.
Standard chat payload; chatmessage preserves Rumble emote image HTML after the page renders it unless text-only mode is enabled.
viewer_update
Calls Rumble’s video.watching-now service every 30s.
meta integer viewer count; uses credentials: 'include' to reuse session cookies.
chat with hasDonation
A visible Rant row contains a price.
hasDonation preserves the rendered price; no donation event marker is added.
raid
An incoming raid card appears in chat.
Uses the visible raid message and optional card image in contentimg.
Rumble - Websocket/API URL
Implementation: sources/websocket/rumble.js
Requires the creator-owned Live Stream API URL from https://rumble.com/account/livestream-api. Rumble documents that this URL includes the live stream key, does not require separate authentication, and should only be shared with trusted third parties.
Read-only transport. The public Rumble Live Stream API docs do not describe an official chat-send endpoint, so this source relays messages/events into Social Stream but does not send chat back to Rumble.
livestreams[].chat only populates while the selected stream is live. Use ?streamId=... to pin a specific stream when the API exposes more than one; invalid IDs now fail instead of silently falling back to another stream.
The page also resolves https://rumble.com/chat/popup/<livestreams[].id> so you can open the normal injected popup chat directly without first loading the broadcaster's /live page.
Event
When it Fires
Payload Notes
message
New entries arrive from Rumble's SSE chat stream after the official API resolves livestreams[].id; falls back to livestreams[].chat.recent_messages.
Standard chat payload. meta.source is rumble_sse when the SSE chat stream is available and includes avatar URLs from users[].image.1; otherwise it falls back to live_stream_api without avatars. When the popup emote catalog is available, chatmessage renders Rumble shortcode emotes as image HTML and meta.plainText preserves the original shortcode text.
donation
New rant entries appear in livestreams[].chat.recent_rants.
hasDonation carries the USD-formatted amount; meta includes amount_cents, amount_dollars, and expiresOn.
new_follower
New entries appear in followers.recent_followers.
System event with chatname set to the follower username and timestamp under meta.followedOn.
new_subscriber
New entries appear in subscribers.recent_subscribers.
membership is set to SUBSCRIBER; subtitle mirrors the documented USD amount when Rumble provides it.
subscription_gift
New entries appear in gifted_subs.recent_gifted_subs.
chatname is the gifter, hasDonation becomes N Gifted, and meta includes totalGifted, remainingGifts, giftType, and videoId.
follower_update
Whenever the selected follower counter changes.
meta integer follower count. Defaults to followers.num_followers; with ?followerMode=total, uses followers.num_followers_total when Rumble provides it.
subscriber_update
Whenever subscribers.num_subscribers changes.
meta integer subscriber count.
stream_online / stream_offline
When the selected livestream switches between live and offline states.
meta includes a sanitized subset of stream fields (id, title, createdOn, category labels, likes/dislikes, and viewer totals). Sensitive values such as stream_key are intentionally not forwarded.
viewer_update
Whenever livestreams[].watching_now changes for the selected stream.
meta integer concurrent viewer count; emits 0 when the selected stream goes offline to clear stale counters.
This transport is intended for channels you own or manage. Because the API URL contains a live stream key, do not expose it in overlays, logs, screenshots, or shared browser profiles. Chat avatars come from Rumble's SSE chat stream once the official API resolves the stream ID; this transport does not scrape Rumble pages for avatars.
YouNow - DOM Capture
Implementation: sources/younow.js
Reads the rendered live chat DOM and emits standard chat payloads with type: "younow".
Audience activity lines such as is watching, I became a fan!, and invited N fans to this broadcast. are flagged with event: true so event filters can route them.
Event
When it Fires
Payload Notes
message
New chat rows appear in the live audience chat.
Standard chat payload; fan/audience activity rows set event: true.
viewer_update
The visible audience panel count changes while showviewercount/hypemode is enabled.
meta integer viewer count; emits 0 when the counter disappears.
Favorited Studio - DOM Capture
Implementation: sources/favorited.js
Reads the rendered live chat DOM and emits standard chat payloads with type: "favorited".
Event
When it Fires
Payload Notes
message
New chat rows appear.
Standard chat payload.
viewer_update
The live viewers tab count changes while showviewercount/hypemode is enabled.
meta integer viewer count read from the content-live-viewers tab.
BEAM - DOM Capture
Implementation: sources/beamstream.js
Reads the rendered live chat DOM and emits standard chat payloads with type: "beamstream".
Event
When it Fires
Payload Notes
message
New chat rows appear.
Standard chat payload with plain-text chatname, avatar URL in chatimg, and image URLs or SVG badge objects in chatbadges. Fields hidden in Beam's capture page remain empty. Native Beam profile links are not treated as external relay sources. contentimg may carry inline video/webm attachments when exposed.
viewer_update
A viewer counter element changes while showviewercount/hypemode is enabled.
meta integer viewer count; only emitted when the chat page exposes a viewer counter.
Starvios
Implementation: sources/starvios.js
Captures new rendered chat rows on https://starvios.com/popout/chat/USERNAME with type: "starvios", plain sender names, name colors, and text or inline emotes according to textonly.
Paid chat rows retain the displayed amount in hasDonation (for example, 100 Starvies). No USD conversion or donation event is supplied.
Existing rows and rows rendered during the initial 1.5-second history settling period are skipped. Separate pinned cards, reply previews, and subscription/raid notices are excluded. The popout supplies no verified viewer count.
Uses the standard focusChat reply hook when a visible, editable input is present. Authenticated sending remains unverified.
RobotStreamer
Open https://robotstreamer.com/chat.html?c=CHANNEL_ID and keep Stream Chat selected for channel-only capture. Each new message, including messages grouped beneath the same author, uses platform/type: "robotstreamer", plain-text chatname, userid, chatimg, chatbadges, and nameColor. Message bodies preserve safe inline images; textonlymode uses literal text and image labels. Initial history and system notices are excluded. RobotStreamer deletions are not forwarded; remove moderated messages in the SSN dock if needed.
Castyr - DOM Capture
Implementation: sources/castyr.js
Reads new rendered chat rows from https://castyr.live/homebeta/popout-chat/* and emits standard chat payloads with type: "castyr".
Existing chat history is skipped when the source attaches.
Event
When it Fires
Payload Notes
message
A new .chat-message row appears.
Standard chat payload with sender name, rendered message content, and name color when exposed.
viewer_update
The visible active-chat count changes while showviewercount/hypemode is enabled.
meta is the integer count read from Castyr's titled active-chat element.
SOOP - Player DOM Capture
Implementation: sources/sooplive.js. Supports the unified play.sooplive.com player and legacy play.sooplive.co.kr URLs. The former global chat layout remains recognized when served.
Public chat emits type/platform: "sooplive", plain-text chatname/userid, nameColor, and sanitized chatmessage. Existing rows, duplicate message IDs, translation copies, and private whispers are excluded. Emotes become safe images or alt text in text-only mode.
With showviewercount or hypemode enabled, viewer_update carries an integer meta from the player's #nAllViewer. Chat-only popouts may not expose this count. SSApp uses the full player when opening a detached popup, since current SOOP popouts depend on their opener.
Gosh - Channel Chat Capture
Implementation: sources/gosh.js. Open https://gosh.com/USERNAME with chat visible, or paste that URL into SSApp's Add other source. A chat popout is not required.
New chat rows emit type/platform: "gosh", plain-text chatname, nameColor, and sanitized chatmessage. Inline images and GIFs retain safe HTTP(S) URLs. With textonlymode, images become alt text or [image] when no alt text is available. Avatars, badges, donations, and memberships remain empty when absent from the captured row.
Keep the virtualized chat scrolled to the newest messages. Existing history, rerendered rows, and authorless system notices are excluded. Render indexes stay internal and are not emitted as native message IDs. No follow, donation, viewer-count, or moderation events are inferred.
Livacha - Chat Room Capture
Implementation: sources/livacha.js. Open https://livacha.com/chat/ROOM with chat visible, or paste the room URL into SSApp's Add other source.
New chat rows emit type/platform: "livacha", plain-text chatname, chatimg, nameColor, and sanitized chatmessage. Relative avatar and inline image URLs become absolute HTTP(S) URLs. Paragraphs, line breaks, and lists are flattened into one chat message. With textonlymode, images become alt text or [image].
Message IDs are used internally to avoid recapturing edits and remounted rows. Initial history and prepended older messages are skipped; timestamps and reaction menus are outside the captured body. No donation, membership, moderation, or viewer-count events are inferred.
Chatango - Group Chat
Open https://ROOM.chatango.com/, or a page with an embedded Chatango room. New rows emit standard chat with type/platform: "chatango", plain-text chatname, nameColor, chatmessage, and chatimg when available. Inline images use HTTP(S) URLs; text-only mode uses their alt text or [image]. Rows already displayed when capture attaches and older messages prepended while scrolling back are skipped.
Vaughn Live - Channel Chat Capture
Implementation: sources/vaughn.js. Open https://vaughn.live/USERNAME with chat visible, or paste the channel URL into the desktop app's Add other source.
Each new message body emits standard chat with type/platform: "vaughn", plain-text chatname, chatmessage, and the group's avatar chatimg, nameColor, and image/SVG chatbadges when present. Compact chat reads the name preceding the message. Emotes use their displayed image URLs, or their trigger/alt text with textonlymode.
Message IDs and elements are tracked internally to avoid repeats when grouped messages arrive, IDs change after acknowledgement, or rows are rendered again. Existing messages and history rendered while the initial loading overlay is visible are skipped. Timestamps, message tools, and link-preview cards are excluded from message content.
Stream.space - Experimental DOM Capture
Implementation: sources/streamspace.js. Matches only https://beta.stream.space/chat-popup.php?channel=USERNAME and the equivalent https://stream.space popup.
New rendered chat rows emit type: "streamspace", platform: "streamspace", plain-text chatname/userid, chatmessage, avatar chatimg, image-based level chatbadges, and nameColor. Inline emotes are rebuilt as safe images, or their alt text when textonlymode is enabled. Existing history, welcome notices, reply previews, and pinned duplicates are excluded.
viewer_update carries an integer meta read from #popupViewersNum when showviewercount or hypemode is enabled. No donation, membership, or moderation events are inferred.
Experimental: the beta popup remained on Loading during inspection. SSApp loaded the popup and captured viewer updates, but live chat delivery and the production popup remain unverified. SSN cannot capture messages that the site does not render.
w.tv and Prime - DOM Capture
Implementations: sources/wtv.js on https://w.tv/USERNAME/chat and sources/prime.js on https://prime.gs/USERNAME?chat_popout=1.
New chat rows use type/platform of wtv or prime, plain-text chatname, nameColor, and sanitized chatmessage. Inline emotes become safe images or alt text in text-only mode. Prime also includes the row's userid and supports both signed-in profile links and signed-out username labels. Avatars and badges are left empty when not available in the verified row structure.
Initial history, pinned cards, and reply previews are excluded. w.tv virtualizes its chat: keep it scrolled to the newest messages for capture. Its DOM test IDs are render indexes, not native message IDs. Prime skips older history loaded above the initial messages and ignored-user placeholders.
Neither popup exposes a verified stream viewer count, so these adapters do not emit viewer updates or infer donation, subscription, or moderation events.
Goodgame, Pilled, Owncast, Picarto, and Piczel Viewer Counts
Enable Show viewer count or Track active chatters (showviewercount or hypemode) to collect viewer counts. Opening the Viewer Count & Chat Activity overlay with viewers displayed also requests them. Each source emits event: "viewer_update" with a nonnegative integer meta, refreshed every 30 seconds while capture is enabled. These are stream viewer counts; active chatters are counted separately. A reported zero is valid; failed requests do not produce a zero count.
Normal chat uses the source's type, chatname, chatmessage, and textonly fields without a viewer event marker. Viewer updates contain type, event, and integer meta; the background combines them into viewer_updates for overlays.
Source / type
Page to capture
Viewer count and chat fields
Goodgame goodgame
goodgame.ru/CHANNEL/chat
Stream viewers. Chat rows also include the native ID as a string in meta.messageId when available.
Pilled pilled
pilled.net/livechat/USERNAME or pilled.net/comment/TOPIC_ID
The current live topic's topicFacts.liveViews. The dedicated chat URL supports counts without opening the video page.
Owncast owncast
Your captured Owncast stream or chat page
viewerCount from that server's /api/status.
Picarto picarto
picarto.tv/chatpopout/CHANNEL/public
Channel viewers.
Piczel piczel
piczel.tv/chat/CHANNEL or piczel.tv/watch/CHANNEL
The matching stream's viewers. Join the chat or sign in to expose chat rows; viewer counts can be collected before joining.
Cross-Platform Event Alignment
Use this table to understand how similar concepts map across platforms. Where possible, new sources should align to the common event names in the first column.
Concept
YouTube WS
Twitch WS
Kick WS
New member/sub
sponsorship
new_subscriber
new_subscriber
Renewal/resub
resub
resub
resub
Gift subs
giftpurchase
subscription_gift
subscription_gift
Received gift
giftredemption
-
-
Milestone
membermilestone
-
-
Donation/tip
superchat, supersticker, jeweldonation with hasDonation
cheer (bits)
donation
New follower
new_follower (polled)*
new_follower
new_follower
Viewer count
viewer_update
viewer_update
viewer_update
Follower count
-
follower_update
follower_update
Sub count
subscriber_update
subscriber_update
-
Stream status
live_chat_ended
stream_online/stream_offline
stream_online/stream_offline
Raid
-
raid
-
Reward redemption
-
reward
reward
Alignment Notes
YouTube uses sponsorship for new members, while Twitch and Kick use new_subscriber. Consider checking both when building cross-platform triggers.
resub is consistent across all three platforms for renewals.
Gift events differ: YouTube uses giftpurchase/giftredemption, while Twitch and Kick use subscription_gift.
Donations vary by platform: YouTube uses specific paid event names such as superchat, supersticker, and jeweldonation with hasDonation; Twitch has bits (cheer); Kick has tips (donation).
new_follower is now consistent across all three platforms, but YouTube polls recent subscribers and may return delayed or incomplete results.
Likes and reactions are separate contracts: individual liked/like events reach the Reactions Overlay unless globally filtered, and enter the main pipeline only when capturelikeevent is enabled. Visual or platform-native reaction events retain producer-defined routing. Aggregate likes_update counters are separately controlled by captureliketotals.
Coverage and Compatibility Limits
This reference describes implemented payloads, not a guarantee that every platform delivers every event. Empty hasDonation assignments in a source do not demonstrate donation support. DOM visibility, account permissions, capture toggles, and API availability still determine what is received. Delete forwarding is source-specific; do not assume universal moderation sync.
channel_points is now a deprecated legacy alias for Twitch reward redemptions; new integrations should key off reward.
Kick: Standard vs Websocket
Standard emits lightweight markers (gift, reward, boolean true, viewer_update). Websocket adds official follow, subscription, gift, reward-redemption, KICKs, moderation, and live-status events. It retains compatibility handling for a legacy raid payload, but Kick does not currently offer an official raid/host subscription.
Websocket mode is richer; automation built around Standard-only event names should be reviewed when switching. Do not require a Kick raid event.
Core member/event names are aligned across both; Super Chat, Super Sticker, and Jewels use hasDonation, while membership gift purchases/redemptions do not.
All surfaces
Many sources populate hasDonation without setting data.event.
This is correct; donation rendering should key off hasDonation, with data.event reserved for system/event semantics.
Source-Specific Aliases and Legacy Names
These mappings are specific to the source/context listed, not global replacements. Consumer support for aliases varies by page. Current TikTok DOM and TikFinity sources still emit followed; Velora uses subscription and channel_points, and Streamlabs uses subscription. Accept the current source contract and its relevant legacy aliases rather than renaming every matching event.
Alias / Legacy Name
Canonical Replacement
Context
subscription
new_subscriber
Twitch/Kick new sub
subgift
subscription_gift
Twitch gifted sub
membership
sponsorship
YouTube new member (generic)
new_member
sponsorship
YouTube new member
new_membership
sponsorship
YouTube new member
newmember
sponsorship
YouTube new member
new-membership
sponsorship
YouTube DOM scraper (hyphenated variant)
upgraded_membership
resub
YouTube tier upgrade
upgraded-membership
resub
YouTube DOM scraper (hyphenated variant)
membership_upgrade
resub
YouTube tier upgrade
membership_milestone
membermilestone
YouTube milestone chat
member_milestone
membermilestone
YouTube milestone chat (underscore variant)
gift_membership
giftpurchase
YouTube gift bundle
membership_gift
giftpurchase
YouTube gift bundle
giftmemberships
giftpurchase
YouTube gift bundle (plural variant)
gifted_membership
giftredemption
YouTube gift received
gifted_memberships
giftpurchase
YouTube gift bundle (plural variant)
community_gift
giftpurchase
Community gift bundle
channel_points
reward
Twitch websocket reward redemption (legacy alias)
followed
new_follower
Current TikTok DOM/TikFinity output; accept both names when combining TikTok capture modes.
Using This Reference
When adding a new event, reuse existing vocabulary (subscription_gift, viewer_update, etc.) whenever possible. If a deviation is unavoidable, document it here along with the rationale.
Keep data.meta predictable: prefer flat keys, never overload strings with mixed data, and always include units (currency, bits, duration).
Update this page alongside payload changes; update agent instructions only when shared development rules change.
Validate payload changes against both the emitting source and the consuming overlay or Event Flow trigger.
Capture depends on source support and settings. To hide event-marked rows in dock or featured overlays, add &hideevents or &hideallevents. To hide selected events, use &filterevents=subscription_gift,new_follower,gifted.
For YouTube, Twitch, and Kick, enable WebSocket mode for the broadest platform-specific event support. Gift/donation capture for YouTube (including gifts and super chats) is available in both Standard and WebSocket modes; WebSocket adds additional event types. Exact support still varies by platform, account role, and granted scopes.
NinjaBacker tips use platform: "ninjabacker", type: "ninjabacker", chatname, plain-text chatmessage, textonly: true, a source-prefixed id, formatted hasDonation, and numeric donoValue. They are ordinary donation-style rows without an event override. meta.ninjabacker contains the ISO currency and major-unit amount. Anonymous tips use the display name Anonymous. The source uses either live SSE (no replay) or the opt-in signed webhook receiver on the SSN API (up to seven days of queued delivery). Reliable deliveries use a stable ninjabacker:delivery:DELIVERY_ID id. Neither mode receives refund/dispute reversals. Receiver credentials and signing secrets never enter event payloads. Caller-controlled callbackId values are not payment identity and are not forwarded. Dashboard test tips are excluded from donation rows. They emit event: "monetization_test" with meta.ninjabackerTest containing id and at (Unix milliseconds), for the dedicated preview alert only.
event: "monetization_update" is a meta-only snapshot from type/platform: "socialstream". meta.monetization.wishlist contains enabled, qr, position, rank, total, public url, and the current item (name, amount, currency, image, public url) or null. meta.monetization.ninja contains enabled, qr, position, username, and the public tipping url. Private Tip IDs are never included. meta.monetization.ebay contains enabled, qr, position, display (cycle/cheapest/first), seconds, opt-in announcement settings, and public items. Each item has id, name, amount, currency, image, url, auction, startingBid, endsAt, available, bought and updatedAt. Times are Unix milliseconds. No seller credential or buyer identity is included.
A host-confirmed wishlist purchase also includes meta.wishlistPurchase with id, name, optional supporter, and at (Unix milliseconds). This is a host confirmation, not an Amazon payment notification, and does not count as a monetary donation. Overlays should deduplicate its id and ignore old purchase notices.
Shopify paid orders
The optional signed Shopify receiver emits platform/type: "shopify" and event: "purchase" only for orders/paid with financial_status: "paid", a positive total, test: false, no cancellation, and a current signed-body update timestamp. Test, unpaid, stale, cancelled and refund notifications do not emit purchase actions. No gift intent is inferred.
chatname is Anonymous; customer fields, private notes and order URLs are excluded. chatmessage is plain text with textonly: true; subtitle holds up to three public product titles. meta.commerce contains orderTotal and currency in the shop's currency, plus quantity when a complete valid count is known. Recipient and physical/digital purpose remain unset. No hasDonation or donoValue is set. id is a stable opaque hash scoped to store/order with a Shopify prefix; it is not a raw order identifier.
Purchases use the existing activity, multi-alerts Purchase category and Event Flow paths. Product promotion uses the existing meta.monetization.commerce catalog. Importing a product or setting its promotional label to Gift does not generate a purchase or gift event. Shopify setup and delivery limits.
Gifts and commerce
Use event: "gift" for a gift, giftcontribution for paid support toward a gift, giftfunded for funding completion, and purchase for a product sale. These names are independent of the provider and whether an item is physical or digital. Reserve the legacy giftpurchase event for gifted memberships; Throne previously used that name incorrectly and now emits gift. Existing membership producers remain unchanged. Custom Throne event-name filters should switch to gift; donation filters need no change.
hasDonation remains the compatibility signal for paid support, with donoValue holding its supplied or estimated USD value. Gifts and contributions retain those fields. Funding completion omits both to avoid counting contributions twice. Ordinary product sales omit them by default, preserving the eBay contract. Do not infer gifting intent from a store, wishlist URL, or physical item: a purchase for the buyer or another recipient remains a sale unless the source explicitly identifies creator gifting.
Optional shared meta.commerce fields are recipient (creator, buyer, other), itemType (physical, digital, service), quantity (positive item count), currency (ISO currency), goalAmount (major-unit funding target, never new income), and orderTotal (known major-unit paid order total; commerce, not donation income). Omit unknown details. Keep item names in subtitle, images in contentimg, and supporter text in chatmessage. Existing provider metadata remains available. Throne supplies recipient and currency, plus goalAmount on completion; eBay supplies quantity. Neither guesses item type or exposes private recipient information.
The activity feed displays these events even without supporter text. Multi-alerts uses donation presentation for gifts and contributions, including a distinct Gift Fully Funded notification without monetary value. Purchases have a separate Purchase category, enabled by default, with purchasestyle, purchasesound, purchaseaccent, and disablepurchases URL controls. Purchase alerts do not change donation totals.
Event Flow offers these event names in Event Type and Other Event triggers. Donation triggers still inspect hasDonation; Gift Sub triggers retain membership semantics. Compare Property accepts nested paths such as meta.commerce.recipient. Action templates accept {meta.commerce.quantity} and {meta.commerce.currency}, alongside existing {donation}, {subtitle}, and {meta}. Nested paths are case-sensitive, missing values render empty, and prototype traversal is prohibited.
Creator commerce webhooks and promotional overlays
Ko-fi public Donation payments retain hasDonation and gain USD donoValue. Subscription payments use new_subscriber or resub, with the tier in membership. Shop Order and Commission use purchase without donation values. Private Ko-fi events remain excluded. Form-encoded JSON is decoded once; names and messages are plain text.
Buy Me a Coffee donation.created retains monetary support; extra_purchase.created and commission_order.created become purchase. wishlist_payment.created becomes giftcontribution using only that payment amount; meta.commerce.completed records the provider's completion flag without emitting another monetary row. membership.started becomes new_subscriber with the tier in membership, no longer misusing hasDonation for a tier name. A subscription-start amount is not independently treated as a paid charge. Test, refunded, failed, and unsupported update/lifecycle events do not produce paid alerts. Hidden supporter notes are omitted.
Fourthwall supports ORDER_PLACED (purchase), GIFT_PURCHASE (gift, recipient other), DONATION (normal donation row), and SUBSCRIPTION_PURCHASED (new_subscriber). Existing order totals retain hasDonation for backwards compatibility, marked meta.commerce.legacyDonationValue: true; this is an explicit exception to new product-sale defaults. Orders with applied gift cards emit a purchase alert without donation value: the new charge cannot be inferred reliably from the order total, and the gift purchase was already counted. Billing names and email addresses are not used for public identity. Dashboard test events and order updates do not generate paid alerts.
These adapters retain the existing relay, bot actions, Event Flow and destination routing, with meta.webhookId deduplication. They expose public names, plain-text messages, known item names in subtitle, and ISO meta.commerce.currency alongside numeric donation values when applicable. They do not add refund accounting or new receiver authentication; use the provider's existing configured webhook route.
meta.monetization.commerce in monetization_update contains enabled, qr, position, display (first/cycle), seconds, and a public items array. Each item has name, url, image, optional amount (null when unknown), currency, and purpose (shop/gift/support/membership). These are host-entered promotional details, not payment evidence. Adding or editing items emits no donation or purchase event. The generic overlay uses mode=commerce; view=both|showcase|card|alerts separates promotion from activity. Optional style, scale, cardevery, cardfor and onlytype URL parameters control presentation. Existing provider modes also accept view and scheduling controls. See the setup guide.
Throne gift events
The opt-in Monetization integration forwards signed Throne events with platform and type set to throne. All three use a stable delivery id, plain-text chatname, chatmessage with textonly: true, item name in subtitle, and optional HTTPS thumbnail in contentimg.
event
Meaning
Donation amount / rank
gift
A purchased gift
hasDonation and USD donoValue; +1 gift rank
giftcontribution
A contribution towards a gift
Contribution amount only; no rank increase
giftfunded
A crowdfunded gift completed
No hasDonation or donoValue, avoiding double-counting previous contributions; +1 gift rank
meta.throne contains itemName, creator (public username), completed, currency and major-unit amount. For giftfunded, amount describes the goal, not new income. Anonymous gifters remain Anonymous; completed community gifts use Community. Private payment and shipping fields are never forwarded.
monetization_update snapshots additionally contain meta.monetization.throne: enabled, username, url, qr, position, rank, and gifts. These snapshots contain no webhook URL or listening credential.
Host voice commands (desktop preview)
The Event Flow When I say... trigger receives trusted local microphone commands from SSApp. Its internal action context uses chatname: "Host", type: "hostvoice", the recognized phrase in chatmessage, and textonly: true. This is not an incoming platform event or a new chat transport. Sending these fields through chat cannot activate a voice trigger.
Requires an updated desktop build, explicit microphone start, and enabling actions after Test mode. See the preview setup and validation status.
Product display controls
Existing monetization_update snapshots may include meta.monetization.commerce.live: null for the saved schedule, or {mode: "show" | "hide", url?: "https://...", until: 0 | epochMilliseconds}. Show matches the exact saved product URL; a missing product shows no card. A positive until expires back to the saved schedule; zero lasts until changed or SSN restarts. Hide suppresses promotions, not paid activity alerts.
commerce.viewerURL is the published read-only shop URL, or an empty string. When present, promotional QR codes link there. It never contains the SSN session or publishing key. Products remain in commerce.items. No donation/purchase event is emitted by display controls, imports or publishing. See Product controls for Event Flow and remote API usage.
The Event Flow commerceControl action waits for the direct/Chrome reply (up to eight seconds). On ordinary event payloads it preserves the event and adds meta.commerceControlResult: {success: true, commerce: controlState} or {success: false, error: "..."}. For an existing numeric, array or other non-object meta, metadata stays unchanged and the diagnostic is returned as commerceControlResult on the action result instead. Failed controls stop later actions in that chain without suppressing the original payment event. A timeout does not prove the control was unapplied; inspect state before retrying a relative command such as Next. Success confirms local selection/hidden/scheduled state, never OBS visibility or public-page synchronization.
Named Stream Deck / API workflows
The named workflow trigger creates an internal Event Flow message with type: "api", event: "workflow_trigger", chatname: "Stream Deck / API", empty chatmessage, and textonly: true. Its meta.workflow object contains the trigger name and a caller-supplied JSON data object. Read values through templates such as {meta.workflow.data.minutes}. Only saved, enabled flows explicitly matching that trigger are evaluated. This is not an incoming viewer/chat event and is not broadcast as chat; copying these fields into chat does not activate the named trigger.
NinjaChatter audience pilot
The experimental paired extension connector sends display-only rows with type: socialstreamchat, platform: ninjachatter, and textonly: true. meta.ninjachatter carries origin: audience, the descriptive provider, and public room ID. These rows bypass platform replies, bots, Event Flow triggers and points. A displayed provider is not authorization. Legacy NinjaChatter source captures include meta.ninjachatter.room for room-specific duplicate suppression.
Cheer uses a separate authenticated claim and result path, never a special chat command. The fixed preset emits the existing Actions overlay show_text message for three seconds. Its receipt means transport acceptance, not verified OBS display. No audience payload can select arbitrary actions. The pilot is disabled by default on NinjaChatter; Electron retains its existing relay until the new private pairing boundary is qualified.
Commerce spot boards and recent sales
The existing monetization_update event (type/platform: socialstream) also includes meta.monetization.boards. Its board contains title, style (spots/teams), columns (1–20), visible, and up to 120 spots. Each spot has a string id, plain-text label, status (available/claimed/revealed) and result (plain text, empty until revealed). Claims and reveals are host-entered display state, not purchase evidence or randomized assignments.
boards.sales holds up to 100 recent records: id, title, optional amount (null when unknown), currency, quantity, source, and at (Unix milliseconds when recorded). automatic opts into collection, salesVisible controls the display and revision increments on changes. Automatic collection accepts only purchase events from Shopify, eBay seller, Fourthwall, Ko-fi and Buy Me a Coffee; private/test events are excluded. It does not treat auction metadata, tips, gifts or spot claims as purchases. Automatic records do not substitute order totals, listing prices or donation amounts for an item price. Manual records use source: "Host confirmed".
The state persists in this installation's private monetization storage; public snapshots exclude delivery-deduplication IDs, buyer identity and secrets. Explicitly displayed sales retain their event IDs for removal. Refunds require host removal. Duplicate purchase IDs are remembered separately (up to 2,000), including after clearing visible history. The existing getCommerceState response includes commerce.boards; commerceControl accepts the board/sales commands documented in the board guide. Manual edits broadcast updated state but never create purchase events, donation totals or paid rewards. Overlays hide when the host snapshot has been absent for 35 seconds.
Seller workflow additions: commerce.boards.board.id identifies a board generation. A manual saleAdd may supply boardId and spotId to record the sale and claim that spot atomically; duplicate linked sales still in recent history are rejected. saleRemove with reopenSpot: true releases that spot only if the board generation still matches. Public sale entries omit these operator linkage fields. An optional platform on a manual sale preserves its source for filtering while source: "Host confirmed" identifies the confirmation method. amount is the total for the entry, including its quantity. The eBay paid-order adapter’s meta.ebayPurchase.quantity is retained.
salesSettings.auctionSource opts into the Whatnot or eBay Live item helper. The control response’s commerce.auction contains only source, title, priceText, status and at from the latest captured auction_update, or null. It expires after five minutes and clears on source change, idle snapshot or restart. The helper is operator-only: it is neither persisted nor included in audience broadcasts; bidder/winner identity is discarded. Source scripts and auction event payloads are unchanged. Copying a draft does not confirm payment or create a sale.
Event Flow audio controls
The Actions overlay accepts actionType: "play_audio" with audioUrl, volume (0–1), and optional audioPlayback: "queue" or "interrupt". Omitting the playback option keeps overlapping playback. Local media continues to use sourceType: "local", localAssetId, and localAssetName. Queue mode holds up to 30 waiting clips with a two-minute limit per clip; interrupt mode replaces that queue's current clip and clears its waiting items.
actionType: "stop_audio" stops Flow Actions audio clips and clears the sound queue. These are overlay control messages, not source chat events or proof that OBS output was heard. Event Flow resolves a configured random sound set to one audio URL before sending the action. See Event Flow setup.