Formulário de feedback para um site ou app7 min de leitura
Colete pedidos de funcionalidades que você consegue contar, priorizar e responder
Um formulário de pedido de funcionalidade que pergunta pelo problema em vez da solução, armazena pedidos por tema, conta pessoas, não linhas, e avisa quando sair.
Pergunte o que a pessoa está tentando fazer e como faz isso hoje, não qual funcionalidade ela quer, e exija um e-mail para poder avisá-la quando sair. Armazene cada pedido numa tabela via webhook, agrupe os pedidos em temas e priorize os temas por quantas pessoas diferentes estão bloqueadas. Quando um tema sair, mande e-mail para todos que pediram.
O que muda nos pedidos de funcionalidades
Um relato de bug está resolvido quando é corrigido. Um pedido de funcionalidade é um dado: uma de muitas pessoas descrevendo a mesma lacuna com palavras diferentes. Daí vêm três coisas:
- As pessoas descrevem soluções. "Adicionem um botão de CSV" pode querer dizer "meu contador precisa das faturas do mês passado". Pergunte pela tarefa, e você pode escolher uma solução melhor do que a pedida.
- A mesma necessidade chega muitas vezes. O Ikiform armazena todo envio e não junta repetições, e duas pessoas raramente usam as mesmas palavras de qualquer forma. Você mesmo agrupa os pedidos, por tema, e conta pessoas distintas.
- O valor está no retorno. Dizer a alguém "você pediu, nós fizemos" é o melhor motivo para perguntar. Isso exige um e-mail em todo pedido, então este formulário o torna obrigatório.
- Alguém descreve o que está tentando fazer, escolhe uma área e um impacto e deixa um e-mail.
- Um relay de webhook insere o pedido no seu banco de dados, uma vez por id de envio.
- Toda semana você marca os pedidos novos com um tema, à mão ou com um padrão.
- Se ele se encaixa num tema existente, esse tema agora tem mais uma pessoa por trás.
- Se não, ele começa um tema novo.
- Quando um tema sai, você seleciona todos os e-mails dele e envia uma única mensagem.
Pergunte pelo problema
Prévia
Roda o validador do Ikiform no seu navegador. Nada é enviado.
problem tem um mínimo de 30 caracteres, o que transforma "modo escuro pfv" numa frase com um motivo.| Campo | Por que está aí |
|---|---|
problem | A tarefa a ser feita, nas palavras da pessoa. De longe o campo mais útil |
workaround | Mostra o quanto dói. "Copio à mão para uma planilha" é um sinal forte |
area | Uma primeira triagem grosseira, para você marcar dentro de cobrança, não no meio de tudo |
impact | Separa clientes bloqueados de curiosos, formulado como resultados que as pessoas sabem avaliar |
email | Obrigatório. Sem ele você não consegue fechar o ciclo nem fazer uma pergunta |
Deixe de fora um campo de prioridade ou de voto. Todo mundo marca o próprio pedido como alta prioridade, e a contagem de pessoas por tema é um voto melhor que qualquer botão.
O formulário
O formulário não precisa de script: ele envia e redireciona. Defina Redirect after submit para uma página que diga o que acontece em seguida. Para uma versão que fica na página no seu framework, pegue o código do formulário do guia principal e troque pelos campos abaixo.
<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>Armazene os pedidos via webhook
O painel e a exportação CSV funcionam para as primeiras dezenas de pedidos. Quando você estiver marcando temas e contando pessoas toda semana, uma tabela é mais fácil. Crie uma no Postgres:
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
);Depois adicione um endpoint de webhook no Ikiform apontando para esta rota. Ela roda em qualquer host Node com o pacote pg, e seu próprio servidor cobre o mesmo padrão com mais detalhes:
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 });
}verifyWebhookrejeita tudo o que não foi assinado com o secretwhsec_do seu endpoint.on conflict (submission_id) do nothingtorna as novas tentativas seguras. O Ikiform reenvia uma entrega que falhou com o mesmo envio, e o segundo insert não faz nada.- Um erro no banco de dados lança uma exceção, a rota responde
500e o Ikiform tenta de novo depois. Você não perde pedidos durante um restart do banco. - O e-mail é convertido para minúsculas na entrada, então a contagem de pessoas distintas funciona.
Marque e priorize
Marque os pedidos novos
Uma vez por semana, leia as linhas sem tema e dê um tema a cada uma. Padrões resolvem os óbvios; leia o resto você mesmo, porque os pedidos interessantes não batem com um padrão.
update feature_requests
set theme = 'invoice-export'
where theme is null
and area = 'billing'
and problem ilike any (array['%export%', '%accountant%', '%download%']);Priorize os temas
Isto ordena os temas por quantos pedidos dizem estar bloqueados e depois por quantas pessoas diferentes pediram:
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;- Leia por inteiro os textos de
problemdos três primeiros temas antes de desenhar qualquer coisa. - Olhe as alternativas que as pessoas usam. Muitas vezes uma pequena mudança remove a pior parte.
- Pese a prioridade contra o seu plano; ela mostra demanda, não o que é certo construir.
Feche o ciclo
Quando um tema sair, puxe todos que pediram por ele:
select distinct email
from feature_requests
where theme = 'invoice-export';Envie um e-mail curto pela sua ferramenta de e-mail ou da sua própria caixa de entrada, dizendo o que saiu e com um link. O Ikiform não envia e-mail para quem preenche o formulário. Os e-mails de notificação vão só para você e sua equipe, então não há resposta automática, e-mail de confirmação nem double opt-in. Envie isso pela sua ferramenta de e-mail, disparada por um webhook. O mesmo vale aqui: o e-mail de lançamento vem de você, não do Ikiform.
Confira se funciona
- Envie um pedido com um problema de 10 caracteres. O Ikiform responde
422apontandoproblem. - Envie um pedido real. Ele aparece em Submissions e como uma linha em
feature_requests. - Em Webhooks, reenvie a entrega. A tabela continua com uma única linha para esse envio.
- Envie duas vezes com o mesmo e-mail em maiúsculas e minúsculas diferentes. A consulta de prioridade conta uma pessoa.
Pegadinhas
- Um quadro público de feedback, como o Canny, adiciona votação e uma página pública de status. Se você quer que os clientes vejam os pedidos uns dos outros, essa é a ferramenta melhor; esta configuração mantém os pedidos privados.
- Pedidos com vários links podem ser pontuados como spam. Confira o filtro Spam toda semana enquanto o volume for baixo.
- Se você adicionar uma opção de
areadepois, adicione-a primeiro na definição. Um valor que não está na lista é recusado. - Armazene o que você precisa e nada mais. Uma tabela de pedidos com e-mails é dado pessoal; diga isso no seu aviso de privacidade e apague as linhas de que não precisa mais.
Solução de problemas
| Problema | O que fazer |
|---|---|
| Linhas faltando na tabela | Abra o endpoint em Webhooks. Um 400 significa que o secret está errado; um 500 com erro de banco de dados significa que o insert falhou e o Ikiform está tentando de novo. |
422 validation_failed | O envio não corresponde à definição de campos do formulário. error.fields aponta cada campo e o motivo. Faça o name do input bater com o id do campo. |
| O envio está no painel, mas nenhum e-mail ou webhook chegou | Ele foi armazenado como spam. Spam não envia nada. Abra-o no filtro Spam para ver os motivos e marque-o como não spam para enviar o e-mail e os webhooks dele. |
Perguntas
O que a pessoa está tentando fazer, como faz isso hoje, qual parte do produto isso envolve, o quanto importa e um e-mail. Perguntar pelo problema em vez da funcionalidade dá espaço para encontrar uma solução melhor.
Conte com eles e conte pessoas, não linhas. Marque cada pedido com um tema e priorize os temas por e-mails distintos. O Ikiform armazena todos os envios e não junta repetições.
Não só com um formulário. Um formulário mantém os pedidos privados; um quadro público como o Canny adiciona votação. Contar pessoas distintas por tema dá um equivalente privado.
Guarde o e-mail junto com cada pedido, selecione todos os e-mails do tema que saiu e envie uma única mensagem pela sua ferramenta de e-mail. O Ikiform não envia e-mail para quem preencheu o formulário.
Travou em algum passo ou quer um guia para o seu caso? Envie um e-mail para hello@ikiform.com.