Formulaire de feedback pour un site ou une application

Formulaire de feedback pour un site ou une application6 min de lecture

Recueillir le feedback des bêta-testeurs build après build

Un formulaire de feedback bêta avec un lien personnel par testeur et par build, deux échelles de notation et un résumé hebdomadaire qui montre si chaque build s'est amélioré.

Preet SutharFondateur, Ikiform

Donnez à chaque testeur un lien personnel qui porte un code testeur opaque et le numéro de build, pour que le formulaire sache qui répond et sur quel build sans le demander. Demandez à quoi ils ont utilisé le build, deux notes de 1 à 5 pour la stabilité et l'utilité, et ce qui les a bloqués. Comparez ensuite les builds, pas les réponses individuelles, pour voir si chaque version a fait bouger les chiffres.

Ce qui change avec le feedback bêta

Le feedback public vient d'inconnus, une seule fois. Le feedback bêta vient du même petit groupe de personnes, encore et encore, sur un logiciel qui change chaque semaine. Une réponse isolée compte moins que la tendance : le build 1.4.0 a-t-il paru plus stable que le 1.3.0 aux mêmes personnes ? Il faut pour cela deux choses qu'un formulaire de feedback normal n'a pas : qui a répondu, et sur quel build.

Demander aux testeurs de taper leur e-mail et leur numéro de version échoue en pratique. Ils oublient la version, la tapent mal ou écrivent « la dernière ». Les deux vont donc dans le lien que vous envoyez, et la page les remplit.

La boucle hebdomadaire du feedback bêta, d'un nouveau build au suivantlebuild1.4.0sortverslegroupebêtae-maild'invitationunlienpartesteurletesteurrépondcodeetbuildpré-remplissynthèseparbuildmoyennes,testeurs,manquebuild1.5.0corrigelesprincipauxblocages?t=…&build=APILa boucle hebdomadaire du feedback bêta, d'un nouveau build au suivantle build 1.4.0 sortvers le groupe bêtae-mail d'invitationun lien par testeurle testeur répondcode et build pré-remplissynthèse par buildmoyennes, testeurs, manquebuild 1.5.0corrige les principaux blocages?t=…&build=API
  1. Un nouveau build est distribué au groupe bêta.
  2. Un script génère un lien par testeur avec son code et le numéro de build, et vous les envoyez par e-mail.
  3. Le testeur ouvre le lien. La page remplit les champs masqués du testeur et du build et affiche le build concerné.
  4. Un script de synthèse lit chaque réponse via l'API et fait la moyenne des notes par build.
  5. Les blocages des notes les plus basses deviennent la liste des corrections du build suivant.
Comparez les colonnes, pas les lignes. La mauvaise semaine d'un testeur, c'est du bruit ; une baisse dans tout le groupe, c'est une régression.

Les champs

Aperçu

Exécute le validateur d'Ikiform dans votre navigateur. Rien n'est envoyé.

Vous a-t-il paru stable ?
Vous a-t-il été utile ?
Si vous ne pouviez plus l'utiliser, que ressentiriez-vous ?
tester et build sont des inputs masqués remplis depuis le lien. Leurs motifs rejettent tout ce qui ne vient pas d'une vraie invitation.
ChampPourquoi
testerUn code aléatoire de 10 caractères. Permet de suivre une personne d'un build à l'autre sans mettre son e-mail dans une URL
buildRelie chaque note à une version. Le motif n'accepte que des versions comme 1.4.0
triedCe qu'ils ont réellement fait. Sans cela, les notes sont difficiles à interpréter
stability, usefulnessDeux champs rating, de 1 à 5. Séparés, car un build stable de la mauvaise chose reste la mauvaise chose
would_missÀ quel point ils seraient déçus sans. Une part croissante de « Très » est le signe le plus fort que la bêta fonctionne
blockersFacultatif, et c'est de là que vient la liste des corrections

Gardez une simple liste d'e-mails de testeurs dans testers.txt. Ce script attribue à chacun un code stable la première fois qu'il le voit, enregistre la correspondance dans testers.json et écrit un lien d'invitation par testeur pour le build indiqué. Commencez testers.json avec {}.

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

Envoyez le CSV via le publipostage de votre outil d'e-mailing, ou collez les liens à la main pour un petit groupe. Gardez testers.json privé : c'est le seul endroit où un code renvoie à une personne.

La page de feedback

Placez ceci sur une page /beta/feedback de votre site. Elle lit le code et le build depuis le lien, refuse d'afficher le formulaire sans eux et envoie de façon classique. Réglez Redirect after submit sur une page de remerciement. Cela fonctionne sur n'importe quel hébergeur statique ou créateur de sites qui autorise un 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>
Toute personne qui a le lien d'un testeur peut répondre à sa place. C'est acceptable pour une bêta : les codes sont aléatoires, le groupe est petit et une réponse bizarre se remarque. N'utilisez pas le code pour donner accès à quoi que ce soit.

Comparer les builds

Le tableau de bord affiche les réponses une par une. Pour comparer les builds, lisez-les toutes avec le SDK et regroupez par build. Lancez ceci avec une clé secrète dans 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)}%`,
  })),
);

Les notes arrivent sous forme de nombres, donc les moyennes ne demandent aucun parsing. Affichez le nombre de testeurs à côté de chaque moyenne : un build avec trois réponses ne se compare pas honnêtement à un build qui en a trente.

Vérifiez que tout fonctionne

  1. Lancez node links.mjs 1.4.0 et ouvrez l'un des liens. Le formulaire affiche "Feedback for build 1.4.0".
  2. Ouvrez la page sans les paramètres d'URL. Seul le message d'invitation s'affiche.
  3. Envoyez une réponse, puis changez build en latest dans les outils de développement du navigateur et envoyez à nouveau. Ikiform répond 422 avec "Use a version like 1.4.0".
  4. Lancez summary.mjs. Le tableau affiche le build 1.4.0 avec un testeur et vos deux notes.

Pièges

  • Les groupes bêta testent souvent depuis un même bureau, qui partage une IP. La limite Standard les compte ensemble : choisissez donc Relaxed, 20 par minute et par visiteur, pour ce formulaire.
  • Les bêtas mobiles sur TestFlight permettent déjà aux testeurs d'envoyer un feedback avec capture d'écran à App Store Connect. Utilisez-le pour les bugs d'écran et ce formulaire pour les questions hebdomadaires.
  • Posez les mêmes questions chaque semaine. Changer la formulation casse la comparaison entre les builds.
  • Les testeurs répondent de moins en moins au fil de la bêta. Gardez le formulaire à quelques minutes, et remerciez les gens par leur nom dans les notes de version.
  • Ikiform ne fusionne pas les réponses répétées. Si un testeur répond deux fois pour un même build, gardez la plus récente dans votre synthèse.

Dépannage

ProblèmeQue faire
422 avec "Open the link from your invite email"La valeur tester ne correspond pas au motif, généralement parce que le lien a été coupé dans un client e-mail. Renvoyez le lien.
429 rate_limitedUn visiteur a envoyé plus que ce que permet la limite de débit du formulaire. Standard autorise 5 envois par minute et par visiteur. Attendez la durée de Retry-After, ou choisissez Relaxed ou Custom pour les formulaires qui envoient depuis une seule IP partagée.
403 origin_not_allowed, ou tous les envois finissent en spamLe domaine de la page n'est pas dans les Allowed domains du formulaire. Ajoutez-le, plus localhost pour les tests en local. Les sous-domaines d'un domaine listé sont autorisés.

Questions

Une étape vous bloque, ou vous voulez un guide pour votre cas ? Écrivez à hello@ikiform.com.