Formulaire de feedback pour un site ou une application

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

Recueillir des demandes de fonctionnalités que vous pouvez compter, classer et suivre

Un formulaire de demande de fonctionnalité qui demande le problème plutôt que la solution, range les demandes par thème, compte les personnes et non les lignes, et les prévient quand c'est livré.

Preet SutharFondateur, Ikiform

Demandez ce que la personne essaie de faire et comment elle s'y prend aujourd'hui, pas quelle fonctionnalité elle veut, et exigez un e-mail pour la prévenir quand c'est livré. Stockez chaque demande dans une table via webhook, regroupez les demandes par thème et classez les thèmes selon le nombre de personnes différentes bloquées. Quand un thème est livré, écrivez à tous ceux qui l'ont demandé.

Ce qui change avec les demandes de fonctionnalités

Un signalement de bug est clos quand il est corrigé. Une demande de fonctionnalité est un point de données : une personne parmi beaucoup d'autres qui décrit le même manque avec d'autres mots. Trois conséquences en découlent :

  • Les gens décrivent des solutions. « Ajoutez un bouton CSV » peut vouloir dire « mon comptable a besoin des factures du mois dernier ». Demandez le besoin, et vous pourrez choisir une meilleure solution que celle demandée.
  • Le même besoin arrive de nombreuses fois. Ikiform stocke chaque envoi et ne fusionne pas les répétitions, et de toute façon deux personnes utilisent rarement les mêmes mots. C'est vous qui regroupez les demandes, par thème, et comptez les personnes distinctes.
  • La valeur est dans le suivi. Dire à quelqu'un « vous l'avez demandé, on l'a fait » est la meilleure raison de poser la question. Il faut pour cela un e-mail sur chaque demande, donc ce formulaire l'exige.
Comment une demande de fonctionnalité devient un thème compté et un e-mail de lancementdemandeenvoyéeproblème,domaine,impact,e-maillignedansvotretableclé : iddesoumissioncorrespondà unthème ?vousl'étiquetezchaquesemainethème+ 1personnesdistinctes,bloquéesd'abordthèmelivréécrire àtous lesdemandeursnouveauthèmecommenceà unepersonnewebhookouibuildnonComment une demande de fonctionnalité devient un thème compté et un e-mail de lancementdemande envoyéeproblème, domaine,impact, e-mailligne dans votretableclé : id de soumissioncorrespond àun thème ?vousl'étiquetezchaque semainethème + 1personnes distinctes,bloquées d'abordthème livréécrire à tous lesdemandeursnouveauthèmecommence àune personnewebhookouibuildnon
  1. Quelqu'un décrit ce qu'il essaie de faire, choisit un domaine et un impact, et laisse son e-mail.
  2. Un relais de webhook insère la demande dans votre base de données, une fois par id de soumission.
  3. Chaque semaine, vous attribuez un thème aux nouvelles demandes, à la main ou avec un motif.
  4. Si elle correspond à un thème existant, ce thème compte une personne de plus.
  5. Sinon, elle crée un nouveau thème.
  6. Quand un thème est livré, vous sélectionnez tous ses e-mails et envoyez un seul message.
Le classement se fait en personnes par thème, pas en demandes brutes. Un client qui demande cinq fois reste un seul client.

Demander le problème

Aperçu

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

Quelle importance cela a-t-il ?

Nous vous écrirons quand ce sera livré, ou si nous avons une question.

problem exige au moins 30 caractères, ce qui transforme « dark mode svp » en une phrase avec une raison.
ChampPourquoi ce champ
problemLe besoin, avec leurs mots. De loin le champ le plus utile
workaroundIndique à quel point c'est pénible. « Je le recopie à la main dans un tableur » est un signal fort
areaUn premier tri grossier, pour étiqueter dans la facturation et non dans tout le reste
impactDistingue les clients bloqués des curieux, formulé en conséquences que les gens peuvent juger
emailObligatoire. Sans lui, impossible de les prévenir ou de poser une question

Laissez de côté tout champ de priorité ou de vote. Chacun marque sa propre demande comme prioritaire, et le nombre de personnes par thème est un meilleur vote que n'importe quel bouton.

Le formulaire

Le formulaire n'a besoin d'aucun script : il envoie et redirige. Réglez Redirect after submit sur une page qui explique la suite. Pour une version qui reste sur la page dans votre framework, reprenez le code du formulaire du guide principal et remplacez-y les champs par ceux-ci.

feature-request.html
<form action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="post">
  <label for="problem">What are you trying to do?</label>
  <textarea id="problem" name="problem" rows="5" required minlength="30"
    placeholder="Send last month's invoices to our accountant in one go"></textarea>
  <label for="workaround">How do you do it today?</label>
  <textarea id="workaround" name="workaround" rows="3"></textarea>
  <label for="area">Which part of the product?</label>
  <select id="area" name="area" required>
    <option value="billing">Billing and invoices</option>
    <option value="reports">Reports</option>
    <option value="team">Team and permissions</option>
    <option value="integrations">Integrations and API</option>
    <option value="other">Something else</option>
  </select>
  <fieldset>
    <legend>How much does it matter?</legend>
    <label><input type="radio" name="impact" value="blocking" required /> It stops us using the product for something</label>
    <label><input type="radio" name="impact" value="slow" /> It costs us time every week</label>
    <label><input type="radio" name="impact" value="nice" /> It would be nice</label>
  </fieldset>
  <label for="email">Email</label>
  <input id="email" name="email" type="email" required />
  <input name="_gotcha" type="text" tabindex="-1" autocomplete="off" hidden />
  <button>Send request</button>
</form>

Stocker les demandes via webhook

Le tableau de bord et l'export CSV suffisent pour les premières dizaines de demandes. Dès que vous étiquetez des thèmes et comptez les personnes chaque semaine, une table est plus pratique. Créez-en une dans Postgres :

schema.sql
create table feature_requests (
  submission_id text primary key,
  area text not null,
  impact text not null,
  problem text not null,
  workaround text,
  email text not null,
  theme text,
  created_at timestamptz not null
);

Ajoutez ensuite dans Ikiform un endpoint de webhook qui pointe vers cette route. Elle tourne sur n'importe quel hébergeur Node avec le package pg, et votre propre serveur détaille le même principe :

app/api/feature-requests/route.ts
import { verifyWebhook, WebhookVerificationError } from "@ikiform/sdk/webhooks";
import { Pool } from "pg";

const pool = new Pool({ connectionString: process.env.DATABASE_URL });

const INSERT = `insert into feature_requests (submission_id, area, impact, problem, workaround, email, created_at)
values ($1, $2, $3, $4, $5, lower($6), $7)
on conflict (submission_id) do nothing`;

export async function POST(request: Request) {
  const payload = await request.text();
  let event;
  try {
    event = await verifyWebhook({
      payload,
      headers: request.headers,
      secret: process.env.IKIFORM_WEBHOOK_SECRET!,
    });
  } catch (error) {
    if (error instanceof WebhookVerificationError) return new Response(error.reason, { status: 400 });
    throw error;
  }
  if (event.type !== "submission.created") return new Response(null, { status: 204 });

  const { problem, workaround, area, impact, email } = event.data.fields;
  await pool.query(INSERT, [
    event.data.submission_id,
    area,
    impact,
    problem,
    workaround ?? null,
    email,
    event.data.created_at,
  ]);
  return new Response(null, { status: 204 });
}
  • verifyWebhook rejette tout ce qui n'est pas signé avec le secret whsec_ de votre endpoint.
  • on conflict (submission_id) do nothing rend les nouvelles tentatives sans risque. Ikiform renvoie une livraison échouée avec la même soumission, et la deuxième insertion ne fait rien.
  • Une erreur de base de données lève une exception, la route répond 500 et Ikiform réessaie plus tard. Vous ne perdez pas de demandes pendant un redémarrage de la base.
  • L'e-mail est mis en minuscules à l'arrivée, pour que le comptage des personnes distinctes fonctionne.
Ikiform ne fusionne ni ne rejette les soumissions répétées par e-mail. Une répétition identique dans les 24 heures ne fait qu'augmenter le score de spam. Dédupliquez là où vit la liste, ou à l'export.

Étiqueter et classer

Étiqueter les nouvelles demandes

Une fois par semaine, lisez les lignes sans étiquette et donnez un thème à chacune. Les motifs gèrent les cas évidents ; lisez le reste vous-même, car les demandes intéressantes ne correspondent à aucun motif.

tag.sql
update feature_requests
set theme = 'invoice-export'
where theme is null
  and area = 'billing'
  and problem ilike any (array['%export%', '%accountant%', '%download%']);

Classer les thèmes

Ceci classe les thèmes selon le nombre de demandes qui se disent bloquées, puis selon le nombre de personnes différentes qui les ont faites :

ranking.sql
select coalesce(theme, 'untagged') as theme,
       count(*) as requests,
       count(distinct email) as people,
       count(*) filter (where impact = 'blocking') as blocking
from feature_requests
group by 1
order by blocking desc, people desc;
  1. Lisez en entier les textes problem des trois premiers thèmes avant de concevoir quoi que ce soit.
  2. Regardez les contournements. Souvent, un petit changement supprime le plus gênant.
  3. Mettez le classement en regard de votre plan ; il montre la demande, pas ce qu'il est juste de construire.

Boucler la boucle

Quand un thème est livré, récupérez tous ceux qui l'ont demandé :

notify.sql
select distinct email
from feature_requests
where theme = 'invoice-export';

Envoyez un court e-mail depuis votre outil d'e-mailing ou votre propre boîte, qui dit ce qui est sorti avec un lien. Ikiform n'envoie pas d'e-mail à la personne qui remplit le formulaire. Les e-mails de notification vont uniquement à vous et à votre équipe : il n'y a donc ni réponse automatique, ni e-mail de confirmation, ni double opt-in. Envoyez-les depuis votre outil d'e-mailing, déclenché par un webhook. C'est pareil ici : l'e-mail de lancement vient de vous, pas d'Ikiform.

Vérifiez que tout fonctionne

  1. Envoyez une demande avec un problème de 10 caractères. Ikiform répond 422 en nommant problem.
  2. Envoyez une vraie demande. Elle apparaît sous Submissions et comme une ligne dans feature_requests.
  3. Sous Webhooks, renvoyez la livraison. La table n'a toujours qu'une ligne pour cette soumission.
  4. Envoyez deux fois avec le même e-mail en changeant la casse. La requête de classement compte une seule personne.

Pièges

  • Un tableau de feedback public, comme Canny, ajoute le vote et une page de statut publique. Si vous voulez que les clients voient les demandes des autres, c'est le meilleur outil ; cette configuration garde les demandes privées.
  • Les demandes qui contiennent plusieurs liens peuvent être notées comme spam. Vérifiez le filtre Spam chaque semaine tant que le volume est faible.
  • Si vous ajoutez plus tard une option à area, ajoutez-la d'abord à la définition. Une valeur non listée est refusée.
  • Stockez ce dont vous avez besoin, rien de plus. Une table de demandes avec des e-mails, ce sont des données personnelles ; indiquez-le dans votre politique de confidentialité et supprimez les lignes dont vous n'avez plus besoin.

Dépannage

ProblèmeQue faire
Des lignes manquent dans la tableOuvrez l'endpoint sous Webhooks. Un 400 signifie que le secret est faux ; un 500 avec une erreur de base de données signifie que l'insertion a échoué et qu'Ikiform réessaie.
422 validation_failedL'envoi ne correspond pas à la définition des champs du formulaire. error.fields nomme chaque champ et la raison. Faites correspondre le name de l'input à l'id du champ.
La soumission est dans le tableau de bord mais aucun e-mail ni webhook n'est arrivéElle a été stockée comme spam. Le spam n'envoie rien. Ouvrez-la sous le filtre Spam pour voir les raisons, et marquez-la comme non-spam pour envoyer son e-mail et ses webhooks.

Questions

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