Feedback-Formular für eine Website oder App6 Min. Lesezeit
Feedback von Beta-Testern Build für Build sammeln
Ein Beta-Feedback-Formular mit einem persönlichen Link pro Tester und Build, zwei Bewertungsskalen und einer Wochenübersicht, die zeigt, ob jeder Build besser wurde.
Gib jedem Tester einen persönlichen Link mit einem undurchsichtigen Tester-Code und der Build-Nummer, damit das Formular weiß, wer und welcher Build, ohne zu fragen. Frag, wofür der Build genutzt wurde, zwei Bewertungen von 1 bis 5 für Stabilität und Nutzen und was die Person aufgehalten hat. Vergleiche dann Builds, nicht einzelne Antworten, um zu sehen, ob jedes Release die Zahlen bewegt hat.
Was an Beta-Feedback anders ist
Öffentliches Feedback kommt von Fremden, einmal. Beta-Feedback kommt von derselben kleinen Gruppe, immer wieder, zu Software, die sich jede Woche ändert. Eine einzelne Antwort zählt weniger als der Trend: Fühlte sich Build 1.4.0 für dieselben Leute stabiler an als 1.3.0? Dafür braucht es zwei Dinge, die ein normales Feedback-Formular nicht hat: wer geantwortet hat und auf welchem Build.
Tester ihre E-Mail und Versionsnummer eintippen zu lassen, scheitert in der Praxis. Sie vergessen die Version, vertippen sich oder schreiben „neueste“. Also kommt beides in den Link, den du verschickst, und die Seite füllt es aus.
- Ein neuer Build geht an die Beta-Gruppe.
- Ein Skript erstellt pro Tester einen Link mit Code und Build-Nummer, und du verschickst sie per E-Mail.
- Der Tester öffnet den Link. Die Seite füllt die versteckten Felder für Tester und Build aus und zeigt, nach welchem Build sie fragt.
- Ein Übersichtsskript liest jede Antwort über die API und bildet die Durchschnitte pro Build.
- Die Blocker aus den niedrigsten Bewertungen werden zur Fix-Liste für den nächsten Build.
Die Felder
Vorschau
Führt den Validator von Ikiform in deinem Browser aus. Es wird nichts gesendet.
tester und build sind Hidden Inputs, die aus dem Link befüllt werden. Ihre Patterns lehnen alles ab, was nicht aus einer echten Einladung stammt.| Feld | Warum |
|---|---|
tester | Ein zufälliger Code aus 10 Zeichen. Damit verfolgst du eine Person über Builds hinweg, ohne ihre E-Mail in eine URL zu schreiben |
build | Verknüpft jede Bewertung mit einem Release. Das Pattern akzeptiert nur Versionen wie 1.4.0 |
tried | Was sie tatsächlich getan haben. Ohne das sind Bewertungen schwer zu deuten |
stability, usefulness | Zwei rating-Felder, 1 bis 5. Getrennt, denn ein stabiler Build des Falschen ist immer noch das Falsche |
would_miss | Wie enttäuscht sie ohne ihn wären. Ein wachsender Anteil von „Sehr“ ist das stärkste Zeichen, dass die Beta funktioniert |
blockers | Optional, und hier entsteht die Fix-Liste |
Einen Link pro Tester erstellen
Führe eine einfache Liste der Tester-E-Mails in testers.txt. Dieses Skript gibt jedem beim ersten Auftauchen einen festen Code, speichert die Zuordnung in testers.json und schreibt pro Tester einen Einladungslink für den Build, den du angibst. Beginne testers.json mit {}.
import { randomBytes } from "node:crypto";
import { readFileSync, writeFileSync } from "node:fs";
const BUILD = process.argv[2];
if (!/^\d+\.\d+\.\d+$/.test(BUILD ?? "")) throw new Error("Usage: node links.mjs 1.4.0");
const known = JSON.parse(readFileSync("testers.json", "utf8"));
const emails = readFileSync("testers.txt", "utf8").split(/\r?\n/).map((line) => line.trim().toLowerCase()).filter(Boolean);
for (const email of emails) {
known[email] ??= randomBytes(5).toString("hex");
}
writeFileSync("testers.json", JSON.stringify(known, null, 2));
const rows = emails.map((email) => {
const link = new URL("https://example.com/beta/feedback");
link.searchParams.set("t", known[email]);
link.searchParams.set("build", BUILD);
return `${email},${link}`;
});
writeFileSync(`invites-${BUILD}.csv`, ["email,link", ...rows].join("\n"));
console.log(`${rows.length} links for build ${BUILD}`);Verschick die CSV über die Serienbrief-Funktion deines E-Mail-Tools oder füge die Links bei einer kleinen Gruppe von Hand ein. Halte testers.json privat: Nur dort lässt sich ein Code einer Person zuordnen.
Die Feedback-Seite
Setze das auf eine Seite unter /beta/feedback deiner Site. Sie liest Code und Build aus dem Link, zeigt das Formular ohne sie nicht an und sendet auf dem normalen Weg. Setze Redirect after submit auf eine Dankeseite. Das funktioniert auf jedem statischen Host oder Baukasten, der ein Skript erlaubt.
<p id="beta-missing" hidden>This page needs the link from your invite email.</p>
<form id="beta" action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="post" hidden>
<h2>Feedback for build <span id="beta-build"></span></h2>
<input type="hidden" name="tester" />
<input type="hidden" name="build" />
<label for="tried">What did you use this build for?</label>
<textarea id="tried" name="tried" rows="4" required minlength="15"></textarea>
<fieldset>
<legend>How stable did it feel?</legend>
<label><input type="radio" name="stability" value="1" required /> 1, it crashed a lot</label>
<label><input type="radio" name="stability" value="2" /> 2</label>
<label><input type="radio" name="stability" value="3" /> 3</label>
<label><input type="radio" name="stability" value="4" /> 4</label>
<label><input type="radio" name="stability" value="5" /> 5, no problems</label>
</fieldset>
<fieldset>
<legend>How useful was it?</legend>
<label><input type="radio" name="usefulness" value="1" required /> 1, not at all</label>
<label><input type="radio" name="usefulness" value="2" /> 2</label>
<label><input type="radio" name="usefulness" value="3" /> 3</label>
<label><input type="radio" name="usefulness" value="4" /> 4</label>
<label><input type="radio" name="usefulness" value="5" /> 5, I rely on it</label>
</fieldset>
<fieldset>
<legend>If you could no longer use it, how would you feel?</legend>
<label><input type="radio" name="would_miss" value="very" required /> Very disappointed</label>
<label><input type="radio" name="would_miss" value="somewhat" /> Somewhat disappointed</label>
<label><input type="radio" name="would_miss" value="not" /> Not disappointed</label>
</fieldset>
<label for="blockers">Anything that stopped you?</label>
<textarea id="blockers" name="blockers" rows="3"></textarea>
<input name="_gotcha" type="text" tabindex="-1" autocomplete="off" hidden />
<button>Send this week's feedback</button>
</form>
<script>
const params = new URLSearchParams(location.search);
const tester = params.get("t") ?? "";
const build = params.get("build") ?? "";
const form = document.getElementById("beta");
if (/^[a-z0-9]{10}$/.test(tester) && /^\d+\.\d+\.\d+$/.test(build)) {
form.elements.tester.value = tester;
form.elements.build.value = build;
document.getElementById("beta-build").textContent = build;
form.hidden = false;
} else {
document.getElementById("beta-missing").hidden = false;
}
</script>Builds vergleichen
Das Dashboard zeigt einzelne Antworten. Um Builds zu vergleichen, lies sie alle mit dem SDK und gruppiere nach build. Führe das mit einem Secret Key in IKIFORM_SECRET_KEY aus:
import { createClient } from "@ikiform/sdk";
const ikiform = createClient({ apiKey: process.env.IKIFORM_SECRET_KEY });
const builds = new Map();
for await (const submission of ikiform.submissions.iterate({ formId: "frm_xxxxxxxxxxxxxxxx", status: "received" })) {
const { build, tester, stability, usefulness, would_miss } = submission.fields;
const row = builds.get(build) ?? { testers: new Set(), stability: 0, usefulness: 0, very: 0, answers: 0 };
row.testers.add(tester);
row.stability += stability;
row.usefulness += usefulness;
row.very += would_miss === "very" ? 1 : 0;
row.answers += 1;
builds.set(build, row);
}
console.table(
[...builds].map(([build, row]) => ({
build,
testers: row.testers.size,
stability: (row.stability / row.answers).toFixed(1),
usefulness: (row.usefulness / row.answers).toFixed(1),
"very disappointed": `${Math.round((row.very / row.answers) * 100)}%`,
})),
);Bewertungen kommen als Zahlen an, also brauchen die Durchschnitte kein Parsing. Zähle neben jedem Durchschnitt die Tester: Ein Build mit drei Antworten lässt sich nicht fair mit einem mit dreißig vergleichen.
Prüfen, ob es funktioniert
- Führe
node links.mjs 1.4.0aus und öffne einen der Links. Das Formular zeigt „Feedback for build 1.4.0“. - Öffne die Seite ohne Query-String. Nur der Hinweis auf die Einladung erscheint.
- Sende eine Antwort, ändere dann
buildin den Entwicklertools des Browsers auflatestund sende erneut. Ikiform antwortet mit422und „Use a version like 1.4.0“. - Führe
summary.mjsaus. Die Tabelle zeigt Build 1.4.0 mit einem Tester und deinen zwei Bewertungen.
Stolperfallen
- Beta-Gruppen testen oft aus einem Büro, das sich eine IP teilt. Das Limit Standard zählt sie zusammen, also wähle für dieses Formular Relaxed, 20 pro Minute pro Besucher.
- Mobile Betas über TestFlight lassen Tester bereits Screenshot-Feedback an App Store Connect senden. Nutze das für Bugs auf Bildschirmebene und dieses Formular für die wöchentlichen Fragen.
- Stell jede Woche dieselben Fragen. Eine geänderte Formulierung macht den Vergleich zwischen Builds kaputt.
- Tester antworten im Laufe der Beta seltener. Halte das Formular bei ein paar Minuten und danke den Leuten namentlich in den Release Notes.
- Ikiform führt wiederholte Antworten nicht zusammen. Antwortet ein Tester für einen Build zweimal, behalte in deiner Übersicht die spätere.
Fehlerbehebung
| Problem | Was zu tun ist |
|---|---|
422 mit „Open the link from your invite email“ | Der Wert von tester passt nicht zum Pattern, meist weil der Link in einem E-Mail-Client abgeschnitten wurde. Schick den Link erneut. |
429 rate_limited | Ein Besucher hat mehr gesendet, als das Rate-Limit des Formulars erlaubt. Standard erlaubt 5 pro Minute und Besucher. Warte Retry-After ab oder wähle Relaxed oder Custom für Formulare, die von einer gemeinsamen IP aus senden. |
403 origin_not_allowed, oder jeder Post landet im Spam | Die Domain der Seite steht nicht unter Allowed domains des Formulars. Füge sie hinzu, plus localhost für lokale Tests. Subdomains einer eingetragenen Domain sind erlaubt. |
Fragen
Gib jedem Tester einen zufälligen Code und setze ihn in seinen persönlichen Link. Die Seite kopiert ihn in ein Hidden Field, und nur deine private Zuordnungsdatei verbindet den Code mit einer E-Mail.
Setze auch die Build-Nummer in den Link, validiere sie mit einem Pattern und gruppiere Antworten nach Build. submissions.iterate aus dem SDK liest jede Antwort für eine Übersicht.
Wofür der Build genutzt wurde, wie stabil und wie nützlich er sich auf einer Skala von 1 bis 5 angefühlt hat, wie enttäuscht die Person ohne ihn wäre und was sie aufgehalten hat. Stell jede Woche dieselben Fragen.
Führe für alles, was reproduziert werden muss, ein separates Bug-Report-Formular. Das wöchentliche Formular dreht sich darum, wie sich der Build insgesamt anfühlt; beides zu mischen macht beides schwerer lesbar.
Hängst du bei einem Schritt fest oder willst eine Anleitung für deinen Fall? Schreib an hello@ikiform.com.