Formulario de suscripción a newsletter

Formulario de suscripción a newsletter7 min de lectura

Doble opt-in para un formulario de newsletter hecho por ti

Ikiform no envía emails de confirmación, así que el doble opt-in se hace en tu herramienta de email: un relay añade cada suscripción como no confirmada y la herramienta envía el enlace.

Preet SutharFundador, Ikiform

Ikiform nunca envía email a quien se suscribe, así que el email de confirmación tiene que salir de la herramienta que envía tu newsletter. Un relay recibe el webhook firmado de Ikiform y añade al lector a esa herramienta como no confirmado, la herramienta le envía un enlace, y solo un clic lo convierte en suscriptor. Cada herramienta lo activa de una forma, y el relay nunca debería enviar una segunda confirmación a alguien que ya está suscrito.

Qué cambia aquí

Ikiform no envía email a la persona que rellena el formulario. Los emails de notificación van solo a ti y a tu equipo, así que no hay autorespuesta, email de confirmación ni doble opt-in. Envíalos desde tu herramienta de email, activados por un webhook. Con el embed de un proveedor, la confirmación es un ajuste del formulario del proveedor. Con tu propio formulario intervienen dos sistemas, y la confirmación le corresponde al que guarda la lista. El trabajo consiste en asegurarse de que cada suscripción llegue a esa herramienta en un estado que active su confirmación, y que no la active cuando no debe.

El doble opt-in es una máquina de estados dentro de la herramienta de email. El lector empieza sin confirmar, no puede recibir números y solo se convierte en suscriptor cuando hace clic. La parte de Ikiform termina cuando el relay responde 204.

La vida de una suscripción con doble opt-in, del formulario al suscriptor confirmadoformularioconsentimientomarcadoIkiformguarda, firmael webhookrelayañade como noconfirmadoherramientade emailenvía elenlaceconfirmadorecibe cadanúmerosin clicsigue sinconfirmar, sinnúmerosenvíowebhookAPIclicLa vida de una suscripción con doble opt-in, del formulario al suscriptor confirmadoformularioconsentimientomarcadoIkiformguarda, firma elwebhookrelayañade como noconfirmadoherramienta deemailenvía el enlaceconfirmadorecibe cadanúmerosin clicsigue sinconfirmar,sin númerosenvíowebhookAPIclic
  1. El lector marca la casilla de consentimiento y envía tu formulario, que envía a Ikiform.
  2. Ikiform guarda la suscripción y envía un webhook firmado a tu relay.
  3. El relay verifica la firma y añade al lector a la herramienta de email como no confirmado.
  4. La herramienta de email envía al lector un enlace de confirmación.
  5. Si hace clic, la herramienta lo marca como confirmado y le envía cada número.
  6. Si nunca hace clic, se queda sin confirmar y no recibe la newsletter.
Todo lo que pasa después del relay ocurre en la herramienta de email, incluido el texto del email de confirmación, la página que abre el enlace y los recordatorios.

Dónde se activa en cada herramienta

Cada herramienta tiene su propia idea de no confirmado, y su propia forma de convertir en uno a un nuevo suscriptor de la API. Si lo haces mal, los suscriptores se añaden como ya confirmados, sin ningún email:

HerramientaCómo recibe un email de confirmación una suscripción por APILa trampa
KitCrea el suscriptor con state: "inactive" y luego añádelo a un formulario con el incentive email activado. La documentación de formularios en bloque de Kit dice que esto envía el incentive email; prueba el endpoint individual con una dirección tuyaCrear un suscriptor usa por defecto state: "active", y el estado no se puede cambiar después con ese endpoint
MailerLiteActiva Double opt-in for API and integrations en los ajustes de suscripción. Envía también status: "unconfirmed", que MailerLite necesita antes de enviar email a un suscriptor existenteEnviar unconfirmed para una dirección que ya está activa le pide que vuelva a confirmar
beehiivEnvía double_opt_override: "on" al crear la suscripción, o "not_set" para usar el ajuste propio de la publicación"off" activa al suscriptor de inmediato, sin email

Prueba cada una con una dirección tuya antes de confiar en ella. Los ajustes de las herramientas cambian, y el email en sí se configura en la herramienta: su asunto, su texto y la página que abre el enlace.

Un relay que confirma una sola vez

Un relay simple pide una confirmación cada vez que llega un webhook. Dos casos hacen que eso esté mal: un lector que envía tres veces en un minuto recibe tres emails, y un bot que suscribe la dirección de una víctima mete tu confirmación en su bandeja de entrada cada vez que lo intenta. Este Cloudflare Worker pide a la herramienta como mucho una confirmación por dirección y día:

src/index.ts
import { verifyWebhook, WebhookVerificationError } from "@ikiform/sdk/webhooks";
import { addUnconfirmed } from "./tool";

export interface Env {
  IKIFORM_WEBHOOK_SECRET: string;
  TOOL_API_KEY: string;
  SEEN: KVNamespace;
}

const DAY = 86_400;

async function digest(text: string) {
  const bytes = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(text));
  return [...new Uint8Array(bytes)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
}

export default {
  async fetch(request: Request, env: Env) {
    if (request.method !== "POST") return new Response(null, { status: 405 });
    const payload = await request.text();
    let event;
    try {
      event = await verifyWebhook({ payload, headers: request.headers, secret: env.IKIFORM_WEBHOOK_SECRET });
    } catch (error) {
      if (error instanceof WebhookVerificationError) return new Response(error.reason, { status: 400 });
      throw error;
    }
    if (event.type !== "submission.created" || event.data.fields.consent !== true) {
      return new Response(null, { status: 204 });
    }

    const email = String(event.data.fields.email).trim().toLowerCase();
    const key = `confirm:${await digest(email)}`;
    if (await env.SEEN.get(key)) return new Response("Confirmation already requested today", { status: 200 });

    const answer = await addUnconfirmed(env, email, event.data.fields.first_name);
    if (answer.status === 429) {
      return new Response("Rate limited", { status: 503, headers: { "retry-after": answer.headers.get("retry-after") ?? "60" } });
    }
    if (!answer.ok) return new Response(`Email tool answered ${answer.status}`, { status: 502 });

    await env.SEEN.put(key, event.id, { expirationTtl: DAY });
    return new Response(null, { status: 204 });
  },
};
wrangler.jsonc
{
  "$schema": "node_modules/wrangler/config-schema.json",
  "name": "newsletter-relay",
  "main": "src/index.ts",
  "compatibility_date": "2026-10-01",
  "routes": [{ "pattern": "hooks.example.com", "custom_domain": true }],
  "kv_namespaces": [{ "binding": "SEEN", "id": "<your KV namespace id>" }]
}
  • addUnconfirmed en ./tool es la llamada a la herramienta de la tabla de arriba. Copia su cuerpo de la página de Kit, MailerLite o beehiiv.
  • La clave de KV es un SHA-256 de la dirección en minúsculas, así que el almacén nunca guarda la dirección en sí. Caduca al cabo de un día.
  • La clave solo se escribe después de que la herramienta acepte la petición. Si la herramienta falla, Ikiform reintenta y el reintento no queda bloqueado.
  • Responder 200 a una repetición le dice a Ikiform que la entrega fue correcta, así que no se reintenta, y el cuerpo explica el motivo en el registro de entregas.
  • El Worker se ejecuta en un dominio propio. Ikiform rechaza los hostnames workers.dev como URLs de webhook. La documentación de webhooks lista todas las reglas de URL y lo que significa cada respuesta, y tu propio servidor muestra un relay que guarda cada entrega una sola vez.
KV tiene consistencia eventual entre ubicaciones, así que dos entregas para la misma dirección en pocos segundos pueden pasar las dos. Para un email de confirmación es aceptable. Si necesitas una garantía estricta, guarda la clave en un Durable Object o en una base de datos con una columna única.

Qué debe decir el formulario

Un lector que ve "Gracias por suscribirte" y luego no encuentra nada en su carpeta de newsletters piensa que ha fallado. Dile qué pasa a continuación, en la página a la que llega:

  1. Configura la línea de éxito, o tu página de agradecimiento, para que diga que hay un email que abrir: "Casi listo. Abre el email que te hemos enviado y confirma tu dirección."
  2. Indica el remitente que deben buscar, y sugiere la carpeta de spam si no llega nada en unos minutos.
  3. En la herramienta de email, configura la página que abre el enlace de confirmación para que sea tu propia página de "Ya estás suscrito", así el recorrido termina en tu sitio.

La casilla de consentimiento del formulario y el email de confirmación hacen trabajos distintos. La casilla registra que alguien dijo que sí en tu página. El clic demuestra que la dirección pertenece a la persona que dijo que sí. La mayoría de listas quieren las dos cosas. La plantilla de formulario de newsletter tiene la casilla obligatoria.

Errores comunes

  • Suscriptores existentes. Alguien que ya confirmó se vuelve a suscribir desde otra página. No lo devuelvas a no confirmado; la página de MailerLite muestra un relay que primero busca la dirección.
  • Personas que se dieron de baja. Una suscripción no siempre da permiso para deshacer una baja. beehiiv solo reactiva cuando envías reactivate_existing: true, y MailerLite solo vuelve a suscribir con resubscribe: true. Envíalos solo cuando el formulario lo diga.
  • Escáneres de enlaces. Algunos filtros de correo de empresa abren los enlaces del correo entrante para comprobarlos. Si una herramienta confirma con una simple carga de página, un escáner puede confirmar una dirección en la que nadie hizo clic. Comprueba si la página de confirmación de tu herramienta pide pulsar un botón.
  • Entregabilidad. La confirmación es el primer email que recibe un lector de tu parte. Envíalo desde un dominio autenticado en tu herramienta, o acabará en spam y la suscripción nunca se completará.
  • Los no confirmados se acumulan. Todavía no son suscriptores. Decide en tu herramienta si envías un recordatorio, y después déjalos en paz.

Comprueba que funciona

  1. Envía el formulario con una dirección tuya. La página te dice que revises tu bandeja de entrada.
  2. Abre la entrega en Webhooks en Ikiform. Aparece como succeeded con el 204 del relay.
  3. Abre el suscriptor en tu herramienta de email. Está no confirmado, inactivo o pendiente, según la herramienta.
  4. Abre el email de confirmación y haz clic. El suscriptor pasa a estar activo o confirmado.
  5. Vuelve a enviar la misma dirección en menos de un día. La entrega muestra 200 con "Confirmation already requested today", y no llega un segundo email.
  6. Suscribe una dirección que ya está confirmada. Sigue confirmada y no recibe un nuevo email de confirmación.

Preguntas

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