Widget API für
SupportTheWork.
Erweitere das eingebettete widget.js per JavaScript-Hooks, DOM-Events und CSS-Overrides. Diese Referenz dokumentiert jeden Lifecycle-Hook, jeden CSS-Selektor und jede Variable, die das Widget öffentlich macht.
Einbindung
Das Widget wird als asynchrones Script geladen. Es injiziert einen Floating-Button und ein Modal in deine Seite. Sonst gibt es keine globalen Nebenwirkungen.
<script
src="https://supportthework.com/api/widget.js"
data-key="DEIN_WIDGET_KEY"
data-theme="auto"
async
></script>Konfiguration via data-*
Die meiste Konfiguration läuft über das Dashboard und wird beim Laden geholt. Drei Attribute kannst du aber im Script-Tag setzen.
| Attribut | Werte | Beschreibung |
|---|---|---|
| data-key | string | Dein Widget-Key aus dem Dashboard. Pflicht. |
| data-theme | "auto" | "light" | "dark" | Erscheinung. auto folgt prefers-color-scheme. |
| data-preview | boolean | Preview-Modus: Keine echten Zahlungen, kein Backend-Call. |
JavaScript Hooks
Nach dem Laden stellt das Widget window.SupportTheWork bereit. Hooks kannst du vor oder nach dem Script-Tag registrieren - vorausgemeldete Hooks werden beim Bootstrap übernommen.
Vorab deklarieren
<script>
window.SupportTheWork = window.SupportTheWork || {};
window.SupportTheWork.hooks = {
ready(detail) {
console.log('Widget bereit', detail.projectId);
},
'amount:select'(detail) {
console.log('Betrag gewählt:', detail.amount);
},
'checkout:start'(detail) {
console.log('Checkout startet', detail);
},
};
</script>
<script src="https://supportthework.com/api/widget.js" data-key="DEIN_WIDGET_KEY" async></script>Dynamisch registrieren
const unsubscribe = window.SupportTheWork.on('modal:open', (detail) => {
console.log('Modal offen', detail);
});
// später:
unsubscribe();Wildcard-Hook
window.SupportTheWork.on('*', (detail) => {
console.log(detail.event, detail);
});DOM Events
Jeder Hook wird parallel als CustomEvent auf window ausgesendet. Der Eventname ist immer stw:<hook-name>. Damit kannst du das Widget ohne JavaScript-Globals beobachten - z. B. aus einem Framework heraus.
window.addEventListener('stw:checkout:start', (event) => {
console.log(event.detail.amount);
});detail-Payload. Verwende Hooks für eng gekoppelte Custom-Logik, DOM-Events für lose gekoppelte Beobachter wie Analytics oder Consent-Banner.Öffentliche Methoden
Vier Methoden zum direkten Steuern des Widgets von außen.
| Methode | Beschreibung |
|---|---|
| SupportTheWork.open() | Öffnet das Widget, wenn es geladen ist. Triggert modal:before-open und modal:open. |
| SupportTheWork.close() | Schließt das Modal. Triggert modal:before-close und modal:close. |
| SupportTheWork.getState() | Liefert den aktuellen Widget-Zustand synchron (siehe Event Payload). |
| SupportTheWork.version | Property, kein Funktionsaufruf. Aktuelle Widget-Version als String. |
Event Payload
Jeder Hook und jedes DOM-Event bekommt ein detail-Objekt mit dem vollständigen Snapshot-Zustand des Widgets. Beträge sind immer in Cent (500 = 5,00 €).
{
version: string;
widgetKey: string | null;
projectId: string | null;
project: {
id: string;
accentColor: string;
accentColorLight: string;
accentColorDark: string;
buttonText: string;
titleText: string;
presetAmounts: number[];
allowCustomAmount: boolean;
} | null;
preview: boolean;
modalOpen: boolean;
selectedAmount: number | null;
// + event-spezifische Felder: amount, field, value, error, url
}Cancelbare Hooks
Drei Hooks lassen sich abbrechen: modal:before-open, modal:before-close und checkout:before. Gib aus dem Handler false zurück oder rufe event.preventDefault() auf.
window.SupportTheWork.on('checkout:before', (detail, event) => {
if (!window.analyticsConsent) {
event.preventDefault();
return false;
}
});preventDefault() stillschweigend.Hook-Liste
Vollständige Liste aller Hooks, gruppiert nach Lifecycle-Phase. Tags markieren cancelbare Hooks.
| Hook | Typ | Wann |
|---|---|---|
| config:loaded | Lifecycle | Konfiguration wurde vom Backend geladen. |
| ready | Lifecycle | Widget ist gerendert und einsatzbereit. |
| unavailable | Lifecycle | Widget bleibt unsichtbar, weil es nicht geladen werden konnte. |
| button:render | UI | Floating-Button wurde in den DOM gemountet. |
| modal:before-open | Cancelbar | Vor dem Öffnen des Modals. |
| modal:open | UI | Modal wurde geöffnet. |
| modal:before-close | Cancelbar | Vor dem Schließen des Modals. |
| modal:close | UI | Modal wurde geschlossen. |
| amount:select | UI | Preset-Betrag wurde gewählt. detail.amount in Cent. |
| field:change | UI | Formularfeld wurde geändert. detail.field, detail.value. |
| validation:error | UI | Lokale Validierung zeigt einen Fehler. detail.field, detail.error. |
| status | UI | Statusmeldung wurde im Modal angezeigt. |
| checkout:before | Cancelbar | Nach Validierung, vor dem API-Request. |
| checkout:start | Flow | Checkout-Request startet. |
| checkout:redirect | Flow | Stripe-URL wurde erhalten, Redirect folgt. detail.url. |
| checkout:error | Flow | Checkout konnte nicht gestartet werden. detail.error. |
| return:show | Flow | Success/Cancel-Rückkehr-Modal wurde angezeigt. |
CSS Selektoren
Das Widget nutzt stabile IDs, Klassen und data-*-Attribute. Lade deine CSS-Datei nach dem Widget oder gib deinen Selektoren genug Spezifität, damit Overrides greifen.
Klassen
#stw-buttonFloating-Trigger.stw-overlayBackdrop.stw-panelModal-Container.stw-headerModal-Kopf.stw-logoProject-Mark.stw-titleTitle-Text.stw-descriptionSubtitle.stw-bodyScroll-Body.stw-amountPreset-Chip.stw-amount.is-selectedAktiver Chip.stw-custom-fieldCustom-Eingabe.stw-fieldFormularfeld.stw-submitSubmit-Button.stw-footerModal-Fuß.stw-brand"Powered by"Data-Attribute
[data-stw="button"]= #stw-button[data-stw="overlay"]= .stw-overlay[data-stw="panel"]= .stw-panel[data-stw="submit"]= .stw-submit[data-stw-field="email"]E-Mail-Input[data-stw-field="name"]Name-InputCSS Variablen
Subtle Overrides ohne hartes !important - überschreibe einfach die Custom Properties an .stw-panel bzw. #stw-button.
Panel-Variablen
| Variable | Default | Verwendung |
|---|---|---|
| --stw-panel | #ffffff | Modal-Hintergrund |
| --stw-text | #242231 | Primärtext |
| --stw-text-2 | #5b5667 | Sekundärtext |
| --stw-text-3 | #7e7787 | Tertiärtext |
| --stw-text-4 | #a9a19b | Placeholder, Disabled |
| --stw-border | #e6e0da | Inputs, Chips, Trennlinien |
| --stw-bg-sub | #f7f5f2 | Subtile Hintergründe |
| --stw-bg-soft | #efebe6 | Hover-States |
| --stw-accent | #6366f1 | Akzent (Submit, Selected) |
| --stw-accent-strong | #5658d4 | Akzent Hover |
| --stw-accent-soft | rgba(99,102,241,.1) | Akzent-Tint |
Button-Variablen
| Variable | Default | Verwendung |
|---|---|---|
| --stw-button-bottom | 24px | Abstand vom unteren Rand des Viewports |
| --stw-button-right | 24px | Abstand vom rechten Rand des Viewports |
Beispiel: Custom Theme
Stark angepasstes Look-and-Feel - Pill-Buttons, große Radii, kräftige Schatten. Drop-in nach dem Widget-Script.
#stw-button {
border-radius: 14px;
padding-inline: 22px;
box-shadow: 0 18px 60px rgba(0, 0, 0, 0.22);
}
.stw-panel {
width: min(92vw, 460px);
border-radius: 22px;
border: 0;
box-shadow: 0 30px 90px rgba(0, 0, 0, 0.28);
}
.stw-amount {
border-radius: 999px;
height: 48px;
}
.stw-submit {
height: 52px;
border-radius: 999px;
text-transform: uppercase;
letter-spacing: 0.06em;
}!important. Für normale Layout- und Design-Anpassungen reichen die Klassen und Variablen aber aus.