Formulaire d'inscription à la newsletter

Formulaire d'inscription à la newsletter6 min de lecture

Envoyer les inscriptions de votre propre formulaire de newsletter vers beehiiv

Reliez votre propre formulaire d'inscription à beehiiv : un relais crée chaque abonnement avec le double opt-in activé, l'emplacement comme source UTM et la page comme referrer.

Preet SutharFondateur, Ikiform

Envoyez votre propre formulaire à Ikiform et faites pointer le webhook vers un relais qui appelle l'endpoint de création d'abonnement de beehiiv. Envoyez double_opt_override: "on" pour que beehiiv envoie la confirmation, passez l'emplacement du formulaire en utm_source et la page en referring_site, et laissez reactivate_existing à false pour qu'une inscription n'annule jamais une désinscription en silence. Un seul appel d'API par inscription, avec la clé gardée dans le relais.

Ce qui change avec beehiiv

L'API de beehiiv est organisée autour des publications. Un abonnement, c'est une adresse e-mail abonnée à une publication, et vous le créez avec un seul POST vers /v2/publications/{publicationId}/subscriptions. Tout ce qui concerne l'inscription passe dans cette seule requête : faut-il confirmer, faut-il envoyer l'e-mail de bienvenue, d'où vient le lecteur, et les champs personnalisés. Il n'y a pas d'étape séparée de tag ou de formulaire comme dans Kit.

beehiiv suit aussi l'acquisition en termes UTM. Ses fiches d'abonnement portent utm_source, utm_medium, utm_campaign et referring_site. Faites correspondre les champs de votre formulaire à ceux-là, et chaque abonné dans beehiiv montre quel emplacement et quel article l'ont amené :

Comment le relais convertit une soumission Ikiform en abonnement beehiivÉvénement IkiformAbonnement beehiivfields.emaile-mailfields.sourceutm_sourcemeta.referrerreferring_sitefields.first_namecustom_fields : First Namedouble_opt_override: "on"reactivate_existing : falseComment le relais convertit une soumission Ikiform en abonnement beehiivÉvénement IkiformAbonnement beehiivfields.emaile-mailfields.sourceutm_sourcemeta.referrerreferring_sitefields.first_namecustom_fields :First Namedouble_opt_override:"on"reactivate_existing :false
  1. fields.email devient email.
  2. fields.source devient utm_source.
  3. meta.referrer devient referring_site.
  4. fields.first_name devient custom_fields: First Name.
  5. double_opt_override: "on" est ajouté par le relais.
  6. reactivate_existing: false est ajouté par le relais.
Les quatre premiers viennent de l'événement Ikiform. Les deux derniers sont des choix fixes que le relais applique à chaque inscription.

Configurer beehiiv

  1. Dans beehiiv, ouvrez Settings, puis API sous Workspace Settings, et choisissez Create New API Key. Copiez-la tout de suite ; beehiiv ne l'affichera plus.
  2. Sur une offre payante, limitez la clé à la seule publication qu'alimente le formulaire. Une clé limitée à une publication reçoit 404 pour toute autre publication, ce qui limite les dégâts en cas de fuite.
  3. Trouvez l'id de la publication, l'id préfixé qu'utilise l'API de beehiiv dans le chemin. L'endpoint de l'API qui liste les publications le renvoie.
  4. Créez un champ personnalisé nommé First Name si vous voulez stocker les prénoms. beehiiv ignore les champs personnalisés qui n'existent pas encore.
  5. Configurez les e-mails de double opt-in et de bienvenue dans les réglages de la publication. Le relais les active à chaque requête ; leur contenu vit dans beehiiv.
La page de tarifs de beehiiv indique un accès à l'API sur toutes les offres, avec des limites de débit plus basses sur les offres moins chères. Sa Send API, pour envoyer des e-mails via l'API, est réservée aux offres supérieures, mais ce relais ne fait que créer des abonnements et n'en a pas besoin.

Le relais

Voici une Netlify Function, adaptée à un site déjà sur Netlify : elle tourne sur votre propre domaine, à côté du site statique, sans service séparé. Installez @netlify/functions pour les types, et définissez les trois variables dans les réglages d'environnement du site.

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" envoie l'e-mail de confirmation quel que soit le réglage par défaut de la publication. Utilisez "not_set" pour suivre plutôt le réglage de la publication, et jamais "off" pour un formulaire public.
  • send_welcome_email vaut false par défaut dans l'API. Mettez-le à true si vous voulez que les inscriptions par API reçoivent l'e-mail de bienvenue que reçoivent les inscriptions par embed.
  • reactivate_existing: false est aussi la valeur par défaut. Écrivez-le explicitement pour que personne ne l'inverse plus tard sans réfléchir ; il réactive les personnes désinscrites.
  • beehiiv répond 200 avec l'abonnement, dont le status commence à validating pendant que beehiiv vérifie l'adresse, puis passe à pending jusqu'à la confirmation du lecteur.
  • Sur un 429, le relais lit le RateLimit-Reset de beehiiv, un temps Unix, et le convertit en délai Retry-After pour Ikiform.

L'URL de la fonction est https://your-site.com/hooks/beehiiv. Ajoutez-la sous Webhooks dans Ikiform et copiez le secret whsec_ dans IKIFORM_WEBHOOK_SECRET. La documentation des webhooks liste les règles d'URL, et votre propre serveur montre comment sauter une livraison déjà traitée.

Choisir les valeurs UTM

Les champs UTM de beehiiv sont du texte libre : fixez les valeurs une fois et gardez-les cohérentes, sinon les fiches se divisent en quasi-doublons comme footer et Footer. L'input masqué source du formulaire est le utm_source naturel. Gardez utm_medium fixe, pour distinguer chaque inscription venant de vos propres formulaires des pages hébergées de beehiiv et des imports :

EmplacementInput sourceutm_sourceutm_medium
Pied de page du sitefooterfootersignup_form
Fin d'un articlepostpostsignup_form
Page newsletternewsletter-pagenewsletter-pagesignup_form

Si vous lancez une campagne qui renvoie vers une page avec le formulaire, lisez la campagne dans l'URL de la page depuis le relais. meta.referrer contient l'URL complète de la page, paramètres d'URL compris quand le navigateur les envoie : le relais peut donc en copier un paramètre utm_campaign dans la requête.

Limites de débit par offre

beehiiv mesure sa limite par clé d'API sur des fenêtres fixes de 60 secondes, et la limite dépend de l'offre. Chaque inscription correspond à une requête :

Offre beehiivRequêtes par minute
Free30
Lite180
Pro500
Enterprise800, plus sur demande

Trente par minute suffisent pour la plupart des formulaires de pied de page, mais un article de lancement sur une publication gratuite peut dépasser ce seuil. Le 503 du relais fait attendre et réessayer Ikiform au lieu de perdre l'inscription. Les noms d'offres et les limites changent : consultez la page de beehiiv sur les limites de débit si la vôtre n'est pas listée.

Pièges

  • Les noms de champs personnalisés sont exacts. beehiiv associe les champs personnalisés par nom et ignore les inconnus avec un avertissement dans la réponse, pas une erreur. Une faute de frappe, et les prénoms disparaissent sans bruit.
  • referring_site peut être vide. meta.referrer vaut null quand le navigateur n'a pas envoyé de referrer, et le relais omet alors le champ.
  • Les abonnés existants. La documentation de beehiiv indique que l'appel crée ou met à jour l'abonnement, mais pas ce qui change pour un abonné actif. Testez avec votre propre adresse confirmée avant de mettre le formulaire sur chaque page.
  • Les clés valent pour tout l'espace de travail par défaut. Une clé sans restriction de publication peut atteindre toutes les publications de l'espace de travail. Limitez sa portée.
  • Les offres payantes restent dans beehiiv. Omettez tier pour que les inscriptions se fassent sans abonnement payant. Les passages à l'offre payante se font dans le checkout de beehiiv.

Vérifiez que tout fonctionne

  1. Choisissez Send test sur l'endpoint dans Ikiform. La livraison affiche 204 et beehiiv ne reçoit aucune requête.
  2. Abonnez-vous depuis votre page avec une adresse à vous. La livraison affiche 204.
  3. Dans beehiiv, l'abonné apparaît en attente, avec votre emplacement comme source UTM et l'article comme site référent.
  4. L'e-mail de double opt-in arrive. Confirmez, et l'e-mail de bienvenue suit.
  5. Désinscrivez cette adresse dans beehiiv et inscrivez-vous à nouveau. L'abonné reste inactif, car reactivate_existing vaut false.

Questions

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