pixl wird gerade aktiv entwickelt. Alle Neuerungen findest du im Changelog.
pixl

Events

Auf Twitch-Events reagieren

Custom Widgets registrieren Event-Handler mit overlay.on(). Sobald auf deinem Twitch-Channel etwas passiert, ruft pixl deinen Handler mit den Event-Daten auf.

overlay.on('twitch.follow', (data) => {
  showAlert(`${data.username} folgt jetzt!`);
});

overlay.on('twitch.cheer', (data) => {
  showAlert(`${data.username} hat ${data.bits} Bits gecheert`);
});

on() gibt die SDK-Instanz zurück, Handler lassen sich also verketten.

Event-Referenz

Jedes Event kann an drei Stellen ankommen:

  • Activity Logs/Events Tab — persistiert in der DB, sichtbar + wiederholbar im Dashboard. Bewusst nicht alles: sehr häufig feuernde Zwischenstände (*_progress) und kleinteilige/sensible Events (Chat, Moderation, Guest Star) würden das Log nur zumüllen.
  • Actions — geplante Automatisierungsebene (n8n-artig, mit Schreibzugriff wie Bot-Antworten). Noch nicht gebaut — deshalb aktuell überall ❌, auch wenn ein Event technisch schon existiert.
  • Overlay SDKoverlay.on(). Aktuell ein einziger ungefilterter Broadcast: jedes existierende Event kommt bei jedem Handler an, unabhängig davon, ob es auch im Events-Tab landet. Deshalb überall ✅.
EventDatenAuslöserActivity Logs/Events TabActionsOverlay SDK
twitch.follow{ username }Neuer Follower
twitch.sub{ username, tier, gift?, months?, streak?, message? }Neuer Sub oder Resub. Feuert NICHT für Gift-Empfänger (weder Einzel- noch Bomben-Gifts) — die stehen ausschließlich in twitch.sub_gift (recipient/recipients), sonst gäbe es doppelte Zeilen. gift/months/streak bleiben nur aus Altdaten-Kompatibilität im Typ, months = Gesamtmonate, streak = aktuelle Serie (fehlt, wenn versteckt), message = Resub-Nachricht
twitch.sub_gift{ username, tier, amount, community?, months?, recipient?, recipients?, totalGifted? }Sub-Gift (Direkt-Gift an eine Person, oder Community-Gift-Bombe an zufällige Zuschauer) — einzige Quelle für den/die Empfänger, es gibt bewusst kein zusätzliches twitch.sub-Log dafür. amount = Anzahl, community: true = Community-Gift (Tier + Menge wählbar, immer 1 Monat, kein fester Empfänger — auch bei amount === 1 möglich, deshalb eigenes Feld statt aus amount geraten), sonst Direkt-Gift (Tier + Länge wählbar, months = gekaufte Länge in Monaten, recipient = Empfänger). recipients = { username, login? }[] bei Community-Gifts, trudelt nach der Notification per Chat-Notice nach und nach ein, totalGifted = alle je verschenkten Subs des Gifters, username kann Anonym sein
twitch.cheer{ username, bits }Bits gecheert
twitch.raid{ from, viewerCount }Eingehender Raid
twitch.channel_point{ username, reward, cost, input }Channel-Point-Belohnung eingelöst (custom oder automatisch, z.B. Sub-Emote-Unlock)
twitch.channel_point_resolved{ username, reward, status }Streamer erfüllt/storniert eine Einlösung. status: fulfilled/canceled
twitch.power_up{ username, title, bits, input }Custom Power-up eingelöst
twitch.poll_started{ title, choices }Poll wurde gestartet
twitch.poll_progress{ title, results }Zwischenstand während die Poll läuft, results = { title, votes }[]. Feuert bei jeder Stimme
twitch.poll_ended{ title, status, results }Poll beendet. status: completed/archived/terminated, results = { title, votes }[]
twitch.prediction_started{ title, outcomes }Prediction wurde gestartet
twitch.prediction_progress{ title, results }Zwischenstand während die Prediction läuft, results = { title, points }[]. Feuert bei jedem Einsatz
twitch.prediction_locked{ title, results }Einreichung geschlossen — noch nicht aufgelöst/abgebrochen (siehe twitch.prediction_ended). results = { title, points }[] (eingesetzte Channel Points je Outcome)
twitch.prediction_ended{ title, status, winningOutcome?, results }Prediction aufgelöst oder abgebrochen. status: resolved/canceled, results = { title, points }[] (eingesetzte Channel Points je Outcome)
twitch.hype_train_started{ level, goal, total }Hype Train beginnt
twitch.hype_train_progress{ level, progress, goal, total }Hype-Train-Fortschritt
twitch.hype_train_ended{ level, total }Hype Train endet
twitch.goal_started{ type, description, current, target }Creator-Goal beginnt
twitch.goal_progress{ current, target }Goal-Fortschritt
twitch.goal_ended{ type, description, current, target, achieved }Creator-Goal endet
twitch.charity_started{ name, target, currency, decimalPlaces }Charity-Kampagne gestartet
twitch.charity_progress{ current, target, currency, decimalPlaces }Charity-Fortschritt
twitch.charity_donated{ username, name, amount, currency, decimalPlaces }Spende an die Charity-Kampagne
twitch.charity_stopped{ name, current, target, currency, decimalPlaces }Charity-Kampagne beendet
twitch.ad_break{ durationSec, isAutomatic }Werbepause läuft an
twitch.shoutout_sent{ to, viewerCount }Du gibst einen Shoutout
twitch.title_changed{ title }Titel wechselt mitten im Stream (Twitch schickt bei jedem channel.update immer Titel + Kategorie, egal was sich ändert — pixl vergleicht selbst gegen den Vorwert und meldet nur, was sich wirklich geändert hat)
twitch.category_changed{ category }Kategorie/Spiel wechselt mitten im Stream (gleicher Diff wie bei twitch.title_changed)
twitch.ban{ username, moderator, reason, isPermanent, endsAt }Viewer gebannt/getimeoutet
twitch.unban{ username, moderator }Viewer entbannt
twitch.vip_added / twitch.vip_removed{ username }VIP-Status vergeben/entfernt
twitch.moderator_added / twitch.moderator_removed{ username }Mod-Status vergeben/entfernt
twitch.watch_streak{ username, streak, channelPoints }Viewer erreicht einen neuen Watch-Streak-Meilenstein (X Streams in Folge geschaut)
twitch.modiversary{ username, months }Mod-Jubiläum: X Monate als Moderator im Kanal
stream.online{ streamId, title, category, url, thumbnailUrl }Stream ist live gegangen
stream.offline{ durationSec? }Stream wurde beendet
twitch.chat_message{ username, text, color }Chat-Nachricht
twitch.chat_cleared{ }Chat komplett geleert
twitch.chat_user_cleared{ username }Alle Nachrichten eines Users gelöscht
twitch.chat_message_deleted{ username, messageId }Einzelne Nachricht gelöscht
twitch.chat_settings_updated{ emoteMode, followerMode, followerModeDuration, slowMode, slowModeWait, subscriberMode, uniqueChatMode }Chat-Einstellungen geändert
twitch.chat_message_held{ username, text, messageId }Nachricht von Automod zurückgehalten
twitch.chat_message_held_updated{ username, status, messageId }Automod-Status einer zurückgehaltenen Nachricht geändert
twitch.shared_chat_started / twitch.shared_chat_updated{ sessionId, participants }Shared-Chat-Session beginnt/ändert sich
twitch.shared_chat_ended{ sessionId }Shared-Chat-Session endet
twitch.guest_star_session_started / twitch.guest_star_session_ended{ sessionId }Guest-Star-Session beginnt/endet
twitch.guest_star_guest_updated{ sessionId, guest, state, slotId }Gast-Status in einer Guest-Star-Session ändert sich
twitch.guest_star_settings_updated{ slotCount, groupLayout }Guest-Star-Einstellungen geändert

Mehr Events geplant

Weitere Events (z.B. Spotify-Track-Wechsel) sind in Arbeit. Die Referenz wird laufend erweitert.

Beispiel: Alert mit Sound

const overlay = new Pixl({
  token: '__TOKEN__',
  settings: {
    sound: { type: 'file', label: 'Alert-Sound', accept: 'audio/*' },
  },
});

overlay.on('twitch.raid', (data) => {
  document.querySelector('#alert').textContent =
    `${data.from} raidet mit ${data.viewerCount} Leuten!`;
  new Audio(overlay.settings.sound).play();
});

Für Werte, die sich merken sollen (Counter, Ziele), nutzt du statt Events den State.

On this page