Formulario de suscripción a newsletter

Formulario de suscripción a newsletter6 min de lectura

Envía a beehiiv las suscripciones de tu propio formulario de newsletter

Conecta tu propio formulario de suscripción con beehiiv: un relay crea cada suscripción con el doble opt-in activado, la ubicación como fuente UTM y la página como referrer.

Preet SutharFundador, Ikiform

Envía tu propio formulario a Ikiform y apunta el webhook a un relay que llame al endpoint de crear suscripción de beehiiv. Envía double_opt_override: "on" para que beehiiv envíe la confirmación, pasa la ubicación del formulario como utm_source y la página como referring_site, y deja reactivate_existing en false para que una suscripción nunca deshaga en silencio una baja. Una llamada a la API por suscripción, con la clave guardada en el relay.

Qué cambia con beehiiv

La API de beehiiv se organiza en torno a publicaciones. Una suscripción es una dirección de email suscrita a una publicación, y se crea con un POST a /v2/publications/{publicationId}/subscriptions. Todo lo relativo a la suscripción viaja en esa única petición: si hay que confirmar, si se envía el email de bienvenida, de dónde vino el lector y los campos personalizados. No hay un paso aparte de etiqueta o formulario como en Kit.

beehiiv también informa de la captación en términos de UTM. Sus registros de suscripción llevan utm_source, utm_medium, utm_campaign y referring_site. Relaciona con ellos los campos de tu formulario, y cada suscriptor en beehiiv mostrará qué ubicación y qué artículo lo trajeron:

Cómo convierte el relay un envío de Ikiform en una suscripción de beehiivevento de Ikiformsuscripción de beehiivfields.emailemailfields.sourceutm_sourcemeta.referrerreferring_sitefields.first_namecustom_fields: First Namedouble_opt_override: "on"reactivate_existing: falseCómo convierte el relay un envío de Ikiform en una suscripción de beehiivevento de Ikiformsuscripción de beehiivfields.emailemailfields.sourceutm_sourcemeta.referrerreferring_sitefields.first_namecustom_fields:First Namedouble_opt_override:"on"reactivate_existing:false
  1. fields.email pasa a ser email.
  2. fields.source pasa a ser utm_source.
  3. meta.referrer pasa a ser referring_site.
  4. fields.first_name pasa a ser custom_fields: First Name.
  5. double_opt_override: "on" lo añade el relay.
  6. reactivate_existing: false lo añade el relay.
Los cuatro primeros vienen del evento de Ikiform. Los dos últimos son decisiones fijas que el relay toma para cada suscripción.

Configura beehiiv

  1. En beehiiv, abre Settings, luego API en Workspace Settings, y elige Create New API Key. Cópiala enseguida; beehiiv no volverá a mostrarla.
  2. En un plan de pago, limita la clave a la única publicación que alimenta el formulario. Una clave limitada a una publicación recibe 404 para cualquier otra, lo que limita el daño si se filtra.
  3. Busca el id de la publicación, el id con prefijo que la API de beehiiv usa en la ruta. El endpoint de la API que lista las publicaciones lo devuelve.
  4. Crea un campo personalizado llamado First Name si quieres guardar los nombres. beehiiv descarta los campos personalizados que todavía no existen.
  5. Configura los emails de doble opt-in y de bienvenida en los ajustes de la publicación. El relay los activa en cada petición; su contenido vive en beehiiv.
La página de precios de beehiiv incluye acceso a la API en todos los planes, con límites de frecuencia de la API más bajos en los planes más baratos. Su Send API, para enviar emails mediante la API, está limitada a planes superiores, pero este relay solo crea suscripciones y no la necesita.

El relay

Esto es una Netlify Function, que encaja con un sitio que ya está en Netlify: se ejecuta en tu propio dominio, junto al sitio estático, sin un servicio aparte. Instala @netlify/functions para los tipos y define las tres variables en los ajustes de entorno del sitio.

netlify/functions/beehiiv.mts
import type { Config } from "@netlify/functions";
import { verifyWebhook, WebhookVerificationError } from "@ikiform/sdk/webhooks";

export default async (request: Request) => {
  const payload = await request.text();
  let event;
  try {
    event = await verifyWebhook({
      payload,
      headers: request.headers,
      secret: Netlify.env.get("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 { email, first_name, consent, source } = event.data.fields;
  if (consent !== true || typeof email !== "string") return new Response("Skipped", { status: 200 });

  const publication = Netlify.env.get("BEEHIIV_PUBLICATION_ID");
  const answer = await fetch(`https://api.beehiiv.com/v2/publications/${publication}/subscriptions`, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${Netlify.env.get("BEEHIIV_API_KEY")}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      email,
      double_opt_override: "on",
      send_welcome_email: true,
      reactivate_existing: false,
      utm_source: typeof source === "string" ? source : "website",
      utm_medium: "signup_form",
      referring_site: event.data.meta.referrer ?? undefined,
      custom_fields: typeof first_name === "string" && first_name ? [{ name: "First Name", value: first_name }] : [],
    }),
  });

  if (answer.status === 429) {
    const reset = Number(answer.headers.get("ratelimit-reset"));
    const wait = reset ? Math.max(1, reset - Math.floor(Date.now() / 1000)) : 60;
    return new Response("beehiiv rate limit", { status: 503, headers: { "retry-after": String(wait) } });
  }
  if (!answer.ok) return new Response(`beehiiv answered ${answer.status}: ${await answer.text()}`, { status: 502 });
  return new Response(null, { status: 204 });
};

export const config: Config = {
  path: "/hooks/beehiiv",
};
  • double_opt_override: "on" envía el email de confirmación sea cual sea el valor por defecto de la publicación. Usa "not_set" para seguir el ajuste de la publicación, y nunca "off" en un formulario público.
  • send_welcome_email es false por defecto en la API. Ponlo en true si quieres que las suscripciones de la API reciban el email de bienvenida que reciben las del embed.
  • reactivate_existing: false también es el valor por defecto. Escríbelo explícitamente para que nadie lo cambie más adelante sin pensar; reactiva a quienes se dieron de baja.
  • beehiiv responde 200 con la suscripción, y su status empieza como validating mientras beehiiv comprueba la dirección, y luego pending hasta que el lector confirma.
  • Ante un 429, el relay lee el RateLimit-Reset de beehiiv, una hora Unix, y lo convierte en un retraso Retry-After para Ikiform.

La URL de la función es https://your-site.com/hooks/beehiiv. Añádela en Webhooks en Ikiform y copia el secreto whsec_ en IKIFORM_WEBHOOK_SECRET. La documentación de webhooks lista las reglas de URL, y tu propio servidor muestra cómo saltarte una entrega que ya has procesado.

Elegir los valores UTM

Los campos UTM de beehiiv son texto libre, así que decide los valores una vez y mantenlos consistentes, o los registros se dividirán en casi duplicados como footer y Footer. El input oculto source del formulario es el utm_source natural. Mantén fijo utm_medium, para poder distinguir cada suscripción de tus propios formularios de las páginas alojadas de beehiiv y de las importaciones:

UbicaciónInput sourceutm_sourceutm_medium
Footer del sitiofooterfootersignup_form
Final de un postpostpostsignup_form
Página de la newsletternewsletter-pagenewsletter-pagesignup_form

Si haces una campaña que enlaza a una página con el formulario, lee la campaña de la URL de la página en el relay. meta.referrer contiene la URL completa de la página, con la query string incluida cuando el navegador la envía, así que el relay puede copiar de ella un parámetro utm_campaign a la petición.

Límites de frecuencia por plan

beehiiv mide su límite por API key en ventanas fijas de 60 segundos, y el límite depende del plan. Cada suscripción es una petición:

Plan de beehiivPeticiones por minuto
Free30
Lite180
Pro500
Enterprise800, más bajo petición

Treinta por minuto basta para la mayoría de formularios de footer, pero un post de lanzamiento en una publicación gratuita puede superarlo. El 503 del relay hace que Ikiform espere y reintente en lugar de perder la suscripción. Los nombres y límites de los planes cambian, así que consulta la página de límites de frecuencia de beehiiv si el tuyo no aparece.

Errores comunes

  • Los nombres de los campos personalizados son exactos. beehiiv relaciona los campos personalizados por nombre y descarta los desconocidos con un aviso en la respuesta, no con un error. Una errata significa que los nombres desaparecen sin avisar.
  • referring_site puede estar vacío. meta.referrer es null cuando el navegador no envió referrer, y el relay omite el campo.
  • Suscriptores existentes. La documentación de beehiiv dice que la llamada crea o actualiza la suscripción, pero no qué cambia para un suscriptor activo. Prueba con tu propia dirección confirmada antes de poner el formulario en todas las páginas.
  • Las claves valen para todo el workspace por defecto. Una clave sin restricción de publicación puede acceder a todas las publicaciones del workspace. Limítala.
  • Los niveles de pago se quedan en beehiiv. Omite tier para que las suscripciones entren sin suscripción de pago. Las mejoras de plan ocurren en el propio checkout de beehiiv.

Comprueba que funciona

  1. Elige Send test en el endpoint en Ikiform. La entrega muestra 204 y beehiiv no recibe ninguna petición.
  2. Suscríbete desde tu página con una dirección tuya. La entrega muestra 204.
  3. En beehiiv, el suscriptor aparece como pendiente, con tu ubicación como fuente UTM y el artículo como sitio de referencia.
  4. Llega el email de doble opt-in. Confírmalo, y después llega el de bienvenida.
  5. Da de baja esa dirección en beehiiv y vuelve a suscribirte. El suscriptor sigue inactivo, porque reactivate_existing es false.

Preguntas

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