Formulir feedback untuk website atau aplikasi5 menit baca
Jalankan survei NPS di situs Anda sendiri, dari tautan email hingga skor
Jalankan survei NPS dengan skor 0 sampai 10 di email, pertanyaan lanjutan di halaman Anda sendiri yang berubah sesuai skor, dan script yang menghitung NPS.
Taruh sebelas tautan, 0 sampai 10, di email survei, masing-masing mengarah ke halaman di situs Anda dengan skor dan token responden yang tidak bisa ditebak di URL. Halaman memilih skor itu lebih dulu, mengajukan pertanyaan lanjutan sesuai skornya, dan tidak mencatat apa pun sampai orang itu menekan Kirim. Simpan skor di field number dari 0 sampai 10, lalu hitung NPS sebagai porsi skor 9 dan 10 dikurangi porsi skor 0 sampai 6.
Apa yang berbeda dari NPS
NPS mengajukan satu pertanyaan dengan skala tetap: seberapa besar kemungkinan Anda merekomendasikan kami, dari 0 sampai 10. Tiga detail membuatnya berbeda dari rating 1 sampai 5 di pilar:
- Skalanya mulai dari 0. Field
ratingIkiform berjalan dari 1 hingga maksimal 10, jadi tidak bisa menampung 0. NPS memakai fieldnumberdenganmin: 0,max: 10, daninteger: true, disimpan sebagai angka. - Biasanya dikirim lewat email. Klien email tidak bisa diandalkan untuk mengirim formulir atau menjalankan script, jadi email membawa tautan, dan formulirnya ada di situs Anda. Ikiform tidak punya halaman formulir yang di-host.
- Tautan di email diklik oleh mesin. Banyak pemindai keamanan email membuka setiap tautan dalam pesan untuk memeriksanya. Jika membuka tautan langsung mencatat skor, Anda akan mengumpulkan skor dari pemindai. Halaman hanya mencatat saat seseorang menekan Kirim.
- Skor 0 sampai 6 menanyakan apa yang mengecewakan mereka, dan dihitung sebagai detractor.
- Skor 7 atau 8 menanyakan apa yang akan membuatnya menjadi 10, dan hanya dihitung dalam total.
- Skor 9 atau 10 menanyakan apa yang paling mereka hargai, dan dihitung sebagai promoter.
- NPS adalah persentase promoter dikurangi persentase detractor, dari minus 100 hingga 100.
Field-nya
Pratinjau
Menjalankan validator Ikiform di browser Anda. Tidak ada yang dikirim.
wave yang tidak ada juga ditolak, jadi setiap jawaban termasuk dalam satu putaran survei.| Field | Alasan |
|---|---|
score | number, 0 sampai 10, hanya bilangan bulat. Disimpan sebagai angka |
reason | Pertanyaan lanjutan. Opsional, karena skor saja tetap dihitung |
respondent | Token yang tidak bisa ditebak yang Anda buat per orang lalu kirim. Dipetakan kembali ke pelanggan di database Anda sendiri |
wave | Putaran yang mana, seperti 2026-q4. Memungkinkan Anda membandingkan kuartal tanpa filter tanggal |
Jangan taruh email atau ID akun pelanggan di tautan. URL berakhir di riwayat browser, log proxy, dan email yang diteruskan. Token acak 16 karakter atau lebih memberi tahu Anda siapa yang menjawab dan tidak memberi tahu apa pun kepada orang lain.
Email survei
Susun deretan tautan dengan merge tag alat email Anda, atau buat di kode yang mengirim email. Fungsi ini mengembalikan HTML untuk satu responden:
function npsRow(respondent, wave) {
const cells = Array.from({ length: 11 }, (_, score) => {
const link = new URL("https://example.com/nps");
link.searchParams.set("score", String(score));
link.searchParams.set("r", respondent);
link.searchParams.set("wave", wave);
return `<td><a href="${link}" style="display:block;padding:8px 10px">${score}</a></td>`;
});
return `<table role="presentation"><tr>${cells.join("")}</tr></table>
<p>0 is not at all likely, 10 is extremely likely.</p>`;
}Batasi email pada pertanyaan dan deretan angka. Intro yang panjang mendorong skala ke bawah layar di ponsel, dan sebagian besar jawaban datang dari orang yang mengklik angka tanpa menggulir.
Landing page
Taruh ini di /nps di situs Anda. Halaman menggambar skala 0 sampai 10, memilih skor dari tautan, mengatur pertanyaan lanjutan untuk skor itu, dan mengirim dengan fetch hanya saat orang itu menekan Kirim. Jika mereka mengubah skor di halaman, pertanyaannya ikut berubah.
<form id="nps" action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="post">
<fieldset>
<legend>How likely are you to recommend us to a friend or colleague?</legend>
<div id="nps-scale"></div>
</fieldset>
<label for="reason" id="reason-label">What's the main reason for your score?</label>
<textarea id="reason" name="reason" rows="4" maxlength="4000"></textarea>
<input type="hidden" name="respondent" />
<input type="hidden" name="wave" />
<input name="_gotcha" type="text" tabindex="-1" autocomplete="off" hidden />
<button>Send</button>
<p id="nps-status" role="status"></p>
</form>
<script>
const QUESTIONS = [
[6, "What disappointed you most?"],
[8, "What would make it a 10 for you?"],
[10, "What do you value most about it?"],
];
const params = new URLSearchParams(location.search);
const form = document.getElementById("nps");
const label = document.getElementById("reason-label");
const scale = document.getElementById("nps-scale");
for (let score = 0; score <= 10; score += 1) {
scale.insertAdjacentHTML(
"beforeend",
`<label><input type="radio" name="score" value="${score}" required /> ${score}</label>`,
);
}
function askFor(score) {
label.textContent = QUESTIONS.find(([top]) => score <= top)[1];
}
const preset = Number(params.get("score"));
if (params.has("score") && Number.isInteger(preset) && preset >= 0 && preset <= 10) {
form.elements.score.value = String(preset);
askFor(preset);
}
form.elements.respondent.value = params.get("r") ?? "";
form.elements.wave.value = params.get("wave") ?? "";
scale.addEventListener("change", (event) => askFor(Number(event.target.value)));
form.addEventListener("submit", async (event) => {
event.preventDefault();
const status = document.getElementById("nps-status");
status.textContent = "Sending";
const response = await fetch(form.action, {
method: "POST",
headers: { Accept: "application/json" },
body: new FormData(form),
}).catch(() => null);
const result = await response?.json().catch(() => null);
if (result?.ok) {
form.replaceChildren(Object.assign(document.createElement("p"), { textContent: "Thanks for answering." }));
return;
}
status.textContent = result?.error?.fields?.score?.[0] ?? result?.error?.message ?? "Couldn't send it. Try again.";
});
</script>/nps langsung melihat skala tanpa pilihan. Jawaban mereka ditolak karena wave tidak ada, kecuali Anda mengatur nilai default, sehingga kunjungan nyasar tidak masuk ke angka Anda.Hitung skornya
Baca setiap jawaban untuk satu gelombang dengan SDK, simpan jawaban terakhir per responden, dan terapkan rumusnya. Jalankan dengan secret key di IKIFORM_SECRET_KEY:
import { createClient } from "@ikiform/sdk";
const WAVE = process.argv[2] ?? "2026-q4";
const ikiform = createClient({ apiKey: process.env.IKIFORM_SECRET_KEY });
const latest = new Map();
for await (const submission of ikiform.submissions.iterate({ formId: "frm_xxxxxxxxxxxxxxxx", status: "received" })) {
const { score, respondent, wave } = submission.fields;
if (wave !== WAVE) continue;
const key = respondent || submission.id;
const seen = latest.get(key);
if (!seen || seen.at < submission.created_at) latest.set(key, { score, at: submission.created_at });
}
const scores = [...latest.values()].map((answer) => answer.score);
const promoters = scores.filter((value) => value >= 9).length;
const detractors = scores.filter((value) => value <= 6).length;
const nps = Math.round(((promoters - detractors) / scores.length) * 100);
console.log(`${WAVE}: ${scores.length} people, ${promoters} promoters, ${detractors} detractors, NPS ${nps}`);Script menyimpan satu jawaban per responden karena orang kadang mengklik angka kedua setelah berubah pikiran. Ikiform tidak menggabungkan atau menolak kiriman berulang berdasarkan email. Pengulangan identik dalam 24 jam hanya menambah skor spam. Lakukan deduplikasi di tempat daftar itu disimpan, atau saat Anda mengekspor.
Pastikan berfungsi
- Buka
/nps?score=3&r=test_respondent_0001&wave=2026-q4. Angka 3 terpilih dan pertanyaannya berbunyi "What disappointed you most?" - Klik 9. Pertanyaannya berubah menjadi "What do you value most about it?"
- Buka tautan yang sama dengan
curl. Tidak ada yang baru di Submissions, karena tidak ada yang dikirim. - Tekan Kirim. Jawaban menampilkan
scoresebagai angka 9. - Jalankan
node nps.mjs 2026-q4. Hasilnya melaporkan satu orang dan satu promoter.
Hal yang sering menjebak
- Jangan terlalu sering menyurvei pelanggan yang sama. Tentukan interval, misalnya sekali per kuartal, dan simpan daftar responden di sisi Anda.
- Sampel kecil berayun liar. Dengan 20 jawaban, satu orang menggeser NPS sebesar 5 poin. Laporkan jumlah orang di samping skornya.
- Skor rendah layak dibalas. Kirim detractor ke chat tim Anda dengan relay webhook seperti peringatan skor rendah di pilar, memakai
score <= 6. - Template formulir survei menanyakan skor di dalam survei yang lebih panjang. Itu cocok untuk studi sekali jalan; pertanyaan NPS yang berdiri sendiri mendapat lebih banyak jawaban.
- Ikiform tidak mengirim email ke orang yang mengisi formulir. Email notifikasi hanya dikirim ke Anda dan tim, jadi tidak ada autoresponder, email konfirmasi, atau double opt-in. Kirim semua itu dari alat email Anda, dipicu oleh webhook.
Pemecahan masalah
| Masalah | Yang harus dilakukan |
|---|---|
422 dengan Must be at most 10, atau error bilangan bulat | Skornya berasal dari luar skala, misalnya URL yang diedit manual. Halaman hanya menerima 0 sampai 10 dari tautan; periksa tautan di template email Anda. |
422 yang menyebut wave | Tautan tidak membawa wave, atau nilainya tidak cocok dengan format seperti 2026-q4. Perbaiki template email, atau atur nilai default di script halaman. |
403 origin_not_allowed, atau setiap kiriman masuk ke spam | Domain halaman tidak ada di Allowed domains formulir. Tambahkan, ditambah localhost untuk uji lokal. Subdomain dari domain yang terdaftar diizinkan. |
429 rate_limited | Satu 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. |
Pertanyaan
Taruh sebelas tautan, 0 sampai 10, di email, masing-masing membuka halaman di situs Anda dengan skor di URL. Halaman memilih skor itu, mengajukan pertanyaan lanjutan, dan mencatat jawaban saat orang itu menekan Kirim.
Tidak. Rating berjalan dari 1 hingga maksimal 10, dan NPS butuh 0. Gunakan field number dengan min 0, max 10, dan integer true.
Ambil persentase jawaban yang bernilai 9 atau 10, kurangi dengan persentase yang bernilai 0 sampai 6, dan abaikan 7 dan 8 kecuali dalam total. Hasilnya berkisar dari minus 100 hingga 100.
Pemindai keamanan email membuka tautan di email masuk untuk memeriksanya. Mencatat saat klik akan menghitung kunjungan itu sebagai jawaban. Mencatat hanya saat Kirim menjaga angkanya tetap jujur.
Mentok di salah satu langkah, atau ingin panduan untuk situasi Anda? Email hello@ikiform.com.