Das Widget
Ein Script-Tag, ein schwebender Button, ein Feedback-Fenster, das auf jeder Seite funktioniert. Alles hier unten sind Stellschrauben, an denen du drehen kannst, aber nicht musst.
Das Script-Tag
Füge das in das HTML jeder Seite ein, auf der du Feedback sammeln willst. Ein schwebender Button erscheint in der Ecke; ein Klick öffnet das Feedback-Fenster.
<script
src="https://opini.dev/widget.js"
data-opini-key="pk_live_..."
data-opini-label="Send feedback"
data-opini-position="bottom-right"
data-opini-theme="light"
data-opini-accent="#C2410C"
defer></script>Läuft Opini auf einer anderen Origin? Ersetze opini.dev durch deinen eigenen Host. Das Widget leitet daraus ab, wohin es sendet.
Optionen
Alle Einstellungen stehen als data-*-Attribute am Script-Tag. Nur der Schlüssel ist Pflicht.
| Attribut | Pflicht | Was es tut |
|---|---|---|
| data-opini-key | ja | Der öffentliche Widget-Schlüssel deines Projekts (pk_live_...). |
| data-opini-label | nein | Text auf dem schwebenden Button. Standard ist „Send feedback“. |
| data-opini-position | nein | In welcher Ecke der Button sitzt. bottom-right (Standard), bottom-left, top-right, top-left. |
| data-opini-theme | nein | light (Standard) oder dark. Nimm, was zu deiner Seite passt. |
| data-opini-accent | nein | Deine Markenfarbe für den Senden-Button und Fokusrahmen. Jede CSS-Farbe: Hex, rgb() oder Name. |
| data-opini-base | nein | Zeigt auf einen anderen API-Host. Selten nötig: Das Script leitet das aus seinem eigenen src ab. |
Anpassung auf dem Server
Die data-*-Attribute oben sind der Fallback. Beim Laden holt das Widget die Projektkonfiguration von Opini, und ein Admin kann einige Texte ändern, ohne das Script-Tag auf deiner Seite anzufassen:
widget_label: der Text auf dem schwebenden Button.widget_headline: die Überschrift des Fensters.widget_placeholder: der Platzhaltertext im Textfeld.widget_submit_label: der Senden-Button.widget_thanks: die Dankesnachricht nach dem Senden.accent_hex,widget_theme,widget_position: Optik.
Vorrang: der Server gewinnt, data-* füllt Lücken, feste Standardwerte decken den Rest ab. So lässt sich jedes Widget auf jeder Website von einer Stelle aus umgestalten, ohne dass jemand das Script-Tag neu einfügen muss.
Schlägt das Laden der Konfiguration fehl (offline, blockiert, CORS), startet das Widget trotzdem mit Attributen und Standardwerten. Der Netzwerkaufruf blockiert nie etwas.
Nutzer identifizieren
Sag Opini, wer Feedback sendet, damit es mit Namen und allem, was du mitgeben willst, in der Triage landet.
Das Widget fragt jeden Besucher nach Name und E-Mail, damit dein Team antworten kann. Übergibst du hier name und email, werden diese Felder übersprungen.
window.opini.identify({
email: "[email protected]",
name: "Ada Lovelace",
plan: "pro",
signed_up_at: "2024-11-02"
});Ein paar Hinweise:
email: nur in der Triage sichtbar. Nie auf öffentlichen Seiten.name: wird als Anzeigename in der Triage und in Admin-Ansichten verwendet.- Alles andere (Plan, Registrierungsdatum, was auch immer) kommt als zusätzlicher Kontext im Detailbereich der Triage mit.
Ruf es auf, sobald du weißt, wer der Nutzer ist: beim Laden, nach dem Login, egal. Der letzte Aufruf vor dem Senden zählt.
Um in der Feedback-Liste nach einem dieser Werte zu filtern, nutz den Kontext-Filter mit einem Schlüssel mit Punkt, etwa identify.plan.
Theme
Zwei Stellschrauben. data-opini-theme wählt hell (Standard, weiße Fläche) oder dunkel (invertiert). Das Widget lebt in einem Shadow Root, das CSS deiner Seite kann also nicht hineinlaufen und es kaputt machen.
data-opini-accent ist deine Markenfarbe: Sie färbt den Senden-Button und die Fokusrahmen. Jede gültige CSS-Farbe funktioniert.
Rückfragen
Die Triage ist kein Posteingang in eine Richtung. Jedes Feedback hat in der Admin-Ansicht einen Button für eine Rückfrage: Stell eine Frage, und die Person bekommt per E-Mail einen Antwortlink. Kein Konto, keine Anmeldung, nur eine Seite mit dem Auszug des Feedbacks, der Frage und einem Textfeld.
Die Antwort landet in derselben Feedback-Zeile. Links laufen nach 30 Tagen ab und können nur einmal beantwortet werden. Alles Weitere unter Rückfragen.
Barrierefreiheit
Alles, was du dir wünschen würdest, ist schon erledigt:
- Das Fenster meldet sich bei Screenreadern als Dialog mit beschrifteter Überschrift.
- Mit der Tastatur geht man durch das Formular, ohne dass der Fokus auf die Seite entwischt; Esc schließt das Fenster und gibt den Fokus an den Button zurück, der es geöffnet hat.
- Der schwebende Button ist ein echter Button, kein verkleidetes div, und kein Tippziel ist kleiner als eine Fingerkuppe.
- Die Akzentfarbe färbt die Fokusrahmen, wer mit der Tastatur arbeitet, weiß also immer, wo er ist.
Entfernen
Lösch das Script-Tag. Das Widget nutzt weder localStorage noch sessionStorage noch Cookies deiner Seite, es bleibt also nichts zurück.
Fortgeschritten
Das brauchst du wahrscheinlich nicht. Klapp es auf, falls doch.
Strenge Content Security Policy?
Das musst du erlauben (wenn Opini unter opini.dev läuft):
Content-Security-Policy:
script-src 'self' https://opini.dev;
connect-src 'self' https://opini.dev https://*.r2.cloudflarestorage.com;
img-src 'self' blob:;
style-src 'self' 'unsafe-inline';Das Widget fügt seine Styles inline in seinen Shadow Root ein, daher ist 'unsafe-inline' bei style-src nötig, bis wir Styles mit Nonce laden. Kein eval, keine externen Bilder, keine Frames.
Bildanhänge werden direkt in den Speicher (den R2-Host) hochgeladen und zeigen eine lokale Vorschau (blob:). Erzwingt deine Policy Trusted Types, füge opini-widget zu trusted-types hinzu.
Genaue Paketgröße
Das Widget ist ein einziges Script: keine Abhängigkeiten, keine nachgeladenen Teile, nichts einzurichten außer dem Tag.
- Mit gzip: ~4.2 KB
- Unkomprimiert: ~12 KB