Formulir feedback untuk website atau aplikasi

Formulir feedback untuk website atau aplikasi5 menit baca

Kumpulkan feedback beta tester per build

Formulir feedback beta dengan tautan pribadi per tester dan build, dua skala rating, dan ringkasan mingguan yang menunjukkan apakah setiap build makin baik.

Preet SutharPendiri, Ikiform

Beri setiap tester tautan pribadi yang membawa kode tester yang tidak bisa ditebak dan nomor build, sehingga formulir tahu siapa dan build mana tanpa bertanya. Tanyakan untuk apa mereka memakai build itu, dua rating 1 sampai 5 untuk stabilitas dan kegunaan, serta apa yang menghambat mereka. Lalu bandingkan antar-build, bukan jawaban individual, untuk melihat apakah setiap rilis menggeser angkanya.

Apa yang berbeda dari feedback beta

Feedback publik datang dari orang asing, sekali saja. Feedback beta datang dari kelompok kecil orang yang sama, berulang kali, tentang software yang berubah setiap minggu. Satu jawaban kurang penting dibanding trennya: apakah build 1.4.0 terasa lebih stabil daripada 1.3.0 bagi orang yang sama? Itu butuh dua hal yang tidak dimiliki formulir feedback biasa: siapa yang menjawab, dan build mana yang mereka pakai.

Meminta tester mengetik email dan nomor versinya gagal dalam praktik. Mereka lupa versinya, salah ketik, atau menulis "terbaru". Jadi keduanya dimasukkan ke tautan yang Anda kirim, dan halaman yang mengisinya.

Siklus feedback beta mingguan, dari satu build baru ke build berikutnyabuild1.4.0riliskegrupbetaemailundangansatutautanpertestertestermenjawabkodedanbuildterisiringkasanperbuildrata-rata,tester,akanrindubuild1.5.0memperbaikihambatanteratas?t=…&build=APISiklus feedback beta mingguan, dari satu build baru ke build berikutnyabuild 1.4.0 riliske grup betaemail undangansatu tautan per testertester menjawabkode dan build terisiringkasan per buildrata-rata, tester, akan rindubuild 1.5.0memperbaiki hambatan teratas?t=…&build=API
  1. Build baru dikirim ke grup beta.
  2. Script membuat satu tautan per tester dengan kode mereka dan nomor build, lalu Anda mengirimnya lewat email.
  3. Tester membuka tautan. Halaman mengisi field tersembunyi tester dan build, serta menampilkan build mana yang ditanyakan.
  4. Script ringkasan membaca setiap jawaban lewat API dan menghitung rata-rata skor per build.
  5. Hambatan dari skor terendah menjadi daftar perbaikan untuk build berikutnya.
Bandingkan kolom, bukan baris. Minggu buruk satu tester hanyalah noise; penurunan di seluruh grup adalah regresi.

Field-nya

Pratinjau

Menjalankan validator Ikiform di browser Anda. Tidak ada yang dikirim.

Seberapa stabil rasanya?
Seberapa berguna build ini?
Jika Anda tidak bisa memakainya lagi, bagaimana perasaan Anda?
tester dan build adalah input tersembunyi yang diisi dari tautan. Pattern-nya menolak apa pun yang bukan dari undangan asli.
FieldAlasan
testerKode acak 10 karakter. Memungkinkan Anda mengikuti satu orang di berbagai build tanpa menaruh email mereka di URL
buildMengikat setiap skor ke sebuah rilis. Pattern-nya hanya menerima versi seperti 1.4.0
triedApa yang sebenarnya mereka lakukan. Skor tanpa ini sulit ditafsirkan
stability, usefulnessDua field rating, 1 sampai 5. Dipisah, karena build yang stabil untuk hal yang salah tetaplah hal yang salah
would_missSeberapa kecewa mereka tanpanya. Porsi "Sangat" yang naik adalah tanda terkuat bahwa beta-nya berhasil
blockersOpsional, dan dari sinilah daftar perbaikan berasal

Simpan daftar email tester biasa di testers.txt. Script ini memberi masing-masing kode tetap saat pertama kali melihatnya, menyimpan pemetaannya di testers.json, dan menulis satu tautan undangan per tester untuk build yang Anda sebutkan. Mulai testers.json dengan {}.

links.mjs
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}`);

Kirim CSV lewat fitur mail merge alat email Anda, atau tempel tautannya secara manual untuk grup kecil. Jaga testers.json tetap privat: hanya di sanalah kode dipetakan kembali ke seseorang.

Halaman feedback

Taruh ini di halaman /beta/feedback di situs Anda. Halaman membaca kode dan build dari tautan, menolak menampilkan formulir tanpa keduanya, dan mengirim dengan cara biasa. Atur Redirect after submit ke halaman terima kasih. Ini bekerja di host statis atau pembuat situs mana pun yang mengizinkan script.

beta/feedback.html
<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>
Siapa pun yang memegang tautan seorang tester bisa menjawab sebagai tester itu. Itu bisa diterima untuk beta: kodenya acak, grupnya kecil, dan jawaban yang janggal akan menonjol. Jangan pakai kode itu untuk memberi akses ke apa pun.

Bandingkan build

Dashboard menampilkan jawaban satu per satu. Untuk membandingkan build, baca semuanya dengan SDK dan kelompokkan berdasarkan build. Jalankan ini dengan secret key di IKIFORM_SECRET_KEY:

summary.mjs
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)}%`,
  })),
);

Rating datang sebagai angka, jadi rata-ratanya tidak perlu parsing. Hitung jumlah tester di samping setiap rata-rata: build dengan tiga jawaban tidak bisa dibandingkan secara adil dengan build yang punya tiga puluh.

Pastikan berfungsi

  1. Jalankan node links.mjs 1.4.0 dan buka salah satu tautannya. Formulir menampilkan "Feedback for build 1.4.0".
  2. Buka halaman tanpa query string. Hanya pesan undangan yang tampil.
  3. Kirim jawaban, lalu ubah build menjadi latest di dev tools browser dan kirim lagi. Ikiform menjawab 422 dengan "Use a version like 1.4.0".
  4. Jalankan summary.mjs. Tabel menampilkan build 1.4.0 dengan satu tester dan dua skor Anda.

Hal yang sering menjebak

  • Grup beta sering menguji dari satu kantor, yang berbagi satu IP. Batas Standard menghitung mereka bersama-sama, jadi pilih Relaxed, 20 per menit per pengunjung untuk formulir ini.
  • Beta mobile di TestFlight sudah memungkinkan tester mengirim feedback screenshot ke App Store Connect. Gunakan itu untuk bug di level layar dan formulir ini untuk pertanyaan mingguan.
  • Ajukan pertanyaan yang sama setiap minggu. Mengubah kata-katanya merusak perbandingan antar-build.
  • Tester makin jarang menjawab seiring berjalannya beta. Jaga formulir agar selesai dalam beberapa menit, dan ucapkan terima kasih dengan menyebut nama di catatan rilis.
  • Ikiform tidak menggabungkan jawaban berulang. Jika seorang tester menjawab dua kali untuk satu build, simpan yang terakhir di ringkasan Anda.

Pemecahan masalah

MasalahYang harus dilakukan
422 dengan "Open the link from your invite email"Nilai tester tidak cocok dengan pattern, biasanya karena tautannya terpotong di klien email. Kirim ulang tautannya.
429 rate_limitedSatu pengunjung mengirim melebihi rate limit formulir. Standard mengizinkan 5 per menit per pengunjung. Tunggu sesuai Retry-After, atau pilih Relaxed atau Custom untuk formulir yang mengirim dari satu IP bersama.
403 origin_not_allowed, atau setiap kiriman masuk ke spamDomain halaman tidak ada di Allowed domains formulir. Tambahkan, ditambah localhost untuk uji lokal. Subdomain dari domain yang terdaftar diizinkan.

Pertanyaan

Mentok di salah satu langkah, atau ingin panduan untuk situasi Anda? Email hello@ikiform.com.