Formulario de feedback para un sitio web o una app

Formulario de feedback para un sitio web o una app7 min de lectura

Haz una encuesta NPS en tu propio sitio, del enlace en el email a la puntuación

Haz una encuesta NPS con una puntuación de 0 a 10 en el email, una pregunta de seguimiento en tu propia página que cambia según la puntuación y un script que calcula el NPS.

Preet SutharFundador, Ikiform

Pon once enlaces, del 0 al 10, en el email de la encuesta, cada uno apuntando a una página de tu sitio con la puntuación y un token opaco del encuestado en la URL. La página preselecciona la puntuación, hace una pregunta de seguimiento que depende de ella y no registra nada hasta que la persona pulsa Enviar. Guarda la puntuación en un campo numérico de 0 a 10 y calcula el NPS como el porcentaje de 9 y 10 menos el porcentaje de 0 a 6.

Qué cambia en el NPS

El NPS hace una sola pregunta con una escala fija: qué probabilidad hay de que nos recomiendes, del 0 al 10. Tres detalles lo diferencian de la valoración de 1 a 5 de la guía principal:

  • La escala empieza en 0. El campo rating de Ikiform va de 1 a 10 como máximo, así que no puede guardar un 0. El NPS usa un campo number con min: 0, max: 10 e integer: true, guardado como número.
  • Suele enviarse por email. Los clientes de email no envían formularios ni ejecutan scripts de forma fiable, así que el email lleva enlaces y el formulario vive en tu sitio. Ikiform no tiene páginas de formulario alojadas.
  • Las máquinas hacen clic en los enlaces de los emails. Muchos escáneres de seguridad del correo abren todos los enlaces de un mensaje para revisarlos. Si abrir un enlace registrara una puntuación, recogerías puntuaciones de escáneres. La página solo registra cuando una persona pulsa Enviar.
Cómo cada franja de puntuaciones NPS tiene su propia pregunta de seguimiento y cuenta para el resultado0 a 6¿Qué te decepcionómás?detractorse resta7 u 8¿Qué haría faltapara que fuera un10?pasivosolo cuenta en el total9 o 10¿Qué es lo que másvaloras?promotorse sumapuntuaciónla pregunta de seguimientocuenta comoCómo cada franja de puntuaciones NPS tiene su propia pregunta de seguimiento y cuenta para el resultado0 a 6¿Qué tedecepcionómás?detractorse resta7 u 8¿Quéharíafaltaparaquefueraun 10?pasivosolocuenta enel total9 o 10¿Qué eslo quemásvaloras?promotorse sumapuntuaciónla preguntadeseguimientocuenta como
  1. Una puntuación de 0 a 6 pregunta qué le decepcionó y cuenta como detractor.
  2. Un 7 u 8 pregunta qué haría falta para un 10 y solo cuenta para el total.
  3. Un 9 o 10 pregunta qué valora más y cuenta como promotor.
  4. El NPS es el porcentaje de promotores menos el porcentaje de detractores, de menos 100 a 100.
La pregunta cambia con la puntuación porque la respuesta útil también cambia. El motivo de un detractor es un problema que arreglar; el de un promotor es texto para tu página de inicio.

Los campos

Vista previa

Ejecuta el validador de Ikiform en tu navegador. No se envía nada.

Prueba con una puntuación de 11 o 7.5: Ikiform rechaza ambas. También se rechaza si falta wave, así que cada respuesta pertenece a una ronda de la encuesta.
CampoPor qué
scorenumber, de 0 a 10, solo números enteros. Se guarda como número
reasonLa pregunta de seguimiento. Opcional, porque una puntuación sola también cuenta
respondentUn token opaco que generas y envías a cada persona. Se relaciona con el cliente en tu propia base de datos
waveQué ronda, como 2026-q4. Te permite comparar trimestres sin filtros de fecha

No pongas el email ni el id de cuenta del cliente en el enlace. Las URL acaban en el historial del navegador, en logs de proxies y en emails reenviados. Un token aleatorio de 16 caracteres o más te dice quién respondió y no le dice nada a nadie más.

El email de la encuesta

Construye la fila de enlaces con las etiquetas de combinación de tu herramienta de email, o genérala en el código que envía el email. Esta función devuelve el HTML para un encuestado:

nps-email.js
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>`;
}

Limita el email a la pregunta y la fila de números. Una introducción larga empuja la escala fuera de la pantalla en los móviles, y la mayoría de respuestas vienen de gente que hace clic en un número sin hacer scroll.

La página de destino

Ponlo en /nps de tu sitio. Dibuja la escala de 0 a 10, preselecciona la puntuación del enlace, pone la pregunta de seguimiento para esa puntuación y envía con fetch solo cuando la persona pulsa Enviar. Si cambia la puntuación en la página, la pregunta cambia con ella.

nps.html
<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>
La página también funciona sin enlace: quien abre /nps directamente ve la escala sin nada seleccionado. Su respuesta se rechaza porque falta wave, salvo que definas un valor por defecto, lo que deja las visitas sueltas fuera de tus números.

Calcula la puntuación

Lee todas las respuestas de una ronda con el SDK, quédate con la última respuesta de cada encuestado y aplica la fórmula. Ejecútalo con una clave secreta en IKIFORM_SECRET_KEY:

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

El script se queda con una respuesta por encuestado porque a veces la gente hace clic en un segundo número tras cambiar de opinión. Ikiform no fusiona ni rechaza envíos repetidos por email. Una repetición idéntica en 24 horas solo suma a la puntuación de spam. Elimina duplicados donde vive la lista, o al exportar.

Comprueba que funciona

  1. Abre /nps?score=3&r=test_respondent_0001&wave=2026-q4. El 3 está seleccionado y la pregunta dice "What disappointed you most?"
  2. Haz clic en el 9. La pregunta cambia a "What do you value most about it?"
  3. Abre el mismo enlace con curl. No aparece nada nuevo en Submissions, porque no se envió nada.
  4. Pulsa Enviar. La respuesta muestra score como el número 9.
  5. Ejecuta node nps.mjs 2026-q4. Informa de una persona y un promotor.

Errores comunes

  • No encuestes al mismo cliente con demasiada frecuencia. Elige un intervalo, como una vez por trimestre, y guarda la lista de encuestados en tu lado.
  • Las muestras pequeñas oscilan mucho. Con 20 respuestas, una persona mueve el NPS 5 puntos. Indica el número de personas junto a la puntuación.
  • Las puntuaciones bajas merecen respuesta. Envía a los detractores al chat de tu equipo con un relay de webhook como la alerta de puntuación baja de la guía principal, usando score <= 6.
  • La plantilla de formulario de encuesta hace la pregunta de la puntuación dentro de una encuesta más larga. Eso encaja con un estudio puntual; una pregunta NPS suelta obtiene más respuestas.
  • Ikiform no envía emails a la persona que rellena el formulario. Los emails de notificación van solo a ti y a tu equipo, así que no hay respuesta automática, email de confirmación ni doble opt-in. Envíalos desde tu herramienta de email, activada por un webhook.

Solución de problemas

ProblemaQué hacer
422 con Must be at most 10, o un error de número enteroLa puntuación vino de otro sitio que no es la escala, como una URL editada a mano. La página solo acepta del 0 al 10 desde el enlace; revisa los enlaces de tu plantilla de email.
422 que menciona waveEl enlace no llevaba wave, o no coincide con valores del estilo de 2026-q4. Arregla la plantilla de email o pon un valor por defecto en el script de la página.
403 origin_not_allowed, o todos los envíos acaban en spamEl dominio de la página no está en Allowed domains del formulario. Añádelo, y localhost para las pruebas locales. Los subdominios de un dominio de la lista están permitidos.
429 rate_limitedUn visitante envió más de lo que permite el límite de frecuencia del formulario. Standard permite 5 por minuto por visitante. Espera lo que indique Retry-After, o elige Relaxed o Custom para formularios que envían desde una IP compartida.

Preguntas

¿Te atascaste en un paso o quieres una guía para tu caso? Escribe a hello@ikiform.com.