Newsletter-Anmeldeformular

Newsletter-Anmeldeformular6 Min. Lesezeit

Anmeldungen aus deinem eigenen Newsletter-Formular an beehiiv senden

Verbinde dein eigenes Anmeldeformular mit beehiiv: Ein Relay legt jedes Abo mit aktivem Double Opt-in an, mit der Platzierung als UTM-Quelle und der Seite als Referrer.

Preet SutharGründer, Ikiform

Sende dein eigenes Formular an Ikiform und richte den Webhook auf ein Relay aus, das den Endpunkt von beehiiv zum Anlegen von Abos aufruft. Sende double_opt_override: "on", damit beehiiv die Bestätigung mailt, übergib die Platzierung des Formulars als utm_source und die Seite als referring_site und lass reactivate_existing auf false, damit eine Anmeldung nie stillschweigend eine Abmeldung rückgängig macht. Ein API-Aufruf pro Anmeldung, mit dem Key im Relay.

Was bei beehiiv anders ist

Die API von beehiiv ist um Publikationen herum aufgebaut. Ein Abo ist eine E-Mail-Adresse, die eine Publikation abonniert, und du legst es mit einem POST an /v2/publications/{publicationId}/subscriptions an. Alles zur Anmeldung steckt in diesem einen Request: ob bestätigt werden soll, ob die Willkommens-E-Mail gesendet wird, woher der Leser kam und benutzerdefinierte Felder. Es gibt keinen separaten Tag- oder Formularschritt wie bei Kit.

beehiiv berichtet die Akquise außerdem in UTM-Begriffen. Seine Abo-Datensätze tragen utm_source, utm_medium, utm_campaign und referring_site. Bilde die Felder deines Formulars darauf ab, und jeder Abonnent in beehiiv zeigt, welche Platzierung und welcher Artikel ihn gebracht hat:

Wie das Relay eine Ikiform-Einsendung auf ein beehiiv-Abo abbildetIkiform-EventAbo bei beehiivfields.emailE-Mailfields.sourceutm_sourcemeta.referrerreferring_sitefields.first_namecustom_fields: First Namedouble_opt_override: "on"reactivate_existing: falseWie das Relay eine Ikiform-Einsendung auf ein beehiiv-Abo abbildetIkiform-EventAbo bei beehiivfields.emailE-Mailfields.sourceutm_sourcemeta.referrerreferring_sitefields.first_namecustom_fields:First Namedouble_opt_override:"on"reactivate_existing:false
  1. fields.email wird zu email.
  2. fields.source wird zu utm_source.
  3. meta.referrer wird zu referring_site.
  4. fields.first_name wird zu custom_fields: First Name.
  5. double_opt_override: "on" ergänzt das Relay.
  6. reactivate_existing: false ergänzt das Relay.
Die ersten vier stammen aus dem Ikiform-Event. Die letzten zwei sind feste Entscheidungen, die das Relay bei jeder Anmeldung trifft.

beehiiv einrichten

  1. Öffne in beehiiv Settings, dann API unter Workspace Settings, und wähle Create New API Key. Kopiere ihn sofort; beehiiv zeigt ihn nicht noch einmal.
  2. Beschränke den Key in einem bezahlten Tarif auf die eine Publikation, die das Formular füttert. Ein auf eine Publikation beschränkter Key bekommt für jede andere Publikation 404, was den Schaden begrenzt, falls er geleakt wird.
  3. Finde die ID der Publikation, die mit Präfix versehene ID, die die API von beehiiv im Pfad nutzt. Der Endpunkt der API, der Publikationen auflistet, gibt sie zurück.
  4. Lege ein benutzerdefiniertes Feld namens First Name an, wenn du Vornamen speichern willst. beehiiv verwirft benutzerdefinierte Felder, die noch nicht existieren.
  5. Richte die Double-Opt-in- und Willkommens-E-Mails in den Einstellungen der Publikation ein. Das Relay schaltet sie pro Request ein; ihr Inhalt liegt in beehiiv.
Die Preisseite von beehiiv listet API-Zugang in jedem Tarif, mit niedrigeren API-Rate-Limits in günstigeren Tarifen. Seine Send API, zum Versenden von E-Mails über die API, ist höheren Tarifen vorbehalten, aber dieses Relay legt nur Abos an und braucht sie nicht.

Das Relay

Das ist eine Netlify Function, die zu einer Site passt, die schon auf Netlify liegt: Sie läuft auf deiner eigenen Domain, neben der statischen Site, ohne separaten Dienst. Installiere @netlify/functions für die Typen und setze die drei Variablen in den Umgebungseinstellungen der 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" sendet die Bestätigungs-E-Mail unabhängig vom Standard der Publikation. Nutze "not_set", um stattdessen der Einstellung der Publikation zu folgen, und nie "off" für ein öffentliches Formular.
  • send_welcome_email ist in der API standardmäßig false. Setze es auf true, wenn API-Anmeldungen die Willkommens-E-Mail bekommen sollen, die Embed-Anmeldungen bekommen.
  • reactivate_existing: false ist ebenfalls der Standard. Schreib es aus, damit es später niemand gedankenlos umstellt; es reaktiviert Leute, die sich abgemeldet haben.
  • beehiiv antwortet mit 200 und dem Abo, und sein status beginnt als validating, während beehiiv die Adresse prüft, und ist dann pending, bis der Leser bestätigt.
  • Bei 429 liest das Relay beehiivs RateLimit-Reset, eine Unix-Zeit, und macht daraus eine Retry-After-Verzögerung für Ikiform.

Die URL der Function ist https://your-site.com/hooks/beehiiv. Füge sie unter Webhooks in Ikiform hinzu und kopiere das whsec_-Secret in IKIFORM_WEBHOOK_SECRET. Die Webhook-Doku listet die URL-Regeln, und dein eigener Server zeigt, wie du eine bereits verarbeitete Zustellung überspringst.

UTM-Werte wählen

Die UTM-Felder von beehiiv sind Freitext, also leg die Werte einmal fest und halte sie konsistent, sonst zerfallen die Datensätze in Beinahe-Duplikate wie footer und Footer. Der versteckte source-Input des Formulars ist das natürliche utm_source. Halte utm_medium fest, damit sich jede Anmeldung aus deinen eigenen Formularen von beehiivs gehosteten Seiten und von Importen unterscheiden lässt:

PlatzierungInput sourceutm_sourceutm_medium
Footer der Sitefooterfootersignup_form
Ende eines Beitragspostpostsignup_form
Newsletter-Seitenewsletter-pagenewsletter-pagesignup_form

Fährst du eine Kampagne, die auf eine Seite mit dem Formular verlinkt, lies die Kampagne im Relay aus der Seiten-URL. meta.referrer enthält die vollständige URL der Seite, inklusive Query-String, wenn der Browser ihn sendet, sodass das Relay einen utm_campaign-Parameter daraus in den Request kopieren kann.

Rate-Limits nach Tarif

beehiiv misst sein Limit pro API-Key in festen Fenstern von 60 Sekunden, und das Limit hängt vom Tarif ab. Jede Anmeldung ist ein Request:

Tarif bei beehiivRequests pro Minute
Free30
Lite180
Pro500
Enterprise800, auf Anfrage mehr

Dreißig pro Minute reichen für die meisten Footer-Formulare, aber ein Launch-Beitrag auf einer kostenlosen Publikation kann darüber gehen. Das 503 des Relays lässt Ikiform warten und es erneut versuchen, statt die Anmeldung zu verwerfen. Tarifnamen und Limits ändern sich, also prüf die Seite zum Rate-Limiting von beehiiv, wenn deiner nicht gelistet ist.

Stolperfallen

  • Namen benutzerdefinierter Felder sind exakt. beehiiv ordnet benutzerdefinierte Felder nach Namen zu und verwirft unbekannte mit einer Warnung in der Antwort, nicht mit einem Fehler. Ein Tippfehler heißt, dass Vornamen still verloren gehen.
  • referring_site kann leer sein. meta.referrer ist null, wenn der Browser keinen Referrer gesendet hat, und das Relay lässt das Feld weg.
  • Bestehende Abonnenten. Laut Doku von beehiiv legt der Aufruf das Abo an oder aktualisiert es, aber nicht, was sich für einen aktiven Abonnenten ändert. Teste mit deiner eigenen bestätigten Adresse, bevor du das Formular auf jede Seite setzt.
  • Keys gelten standardmäßig für den ganzen Workspace. Ein Key ohne Beschränkung auf eine Publikation erreicht jede Publikation im Workspace. Beschränke ihn.
  • Bezahlte Stufen bleiben in beehiiv. Lass tier weg, damit Anmeldungen ohne bezahltes Abo beitreten. Upgrades passieren im eigenen Checkout von beehiiv.

Prüfen, ob es funktioniert

  1. Wähle Send test am Endpunkt in Ikiform. Die Zustellung zeigt 204, und beehiiv bekommt keinen Request.
  2. Abonniere von deiner Seite mit einer Adresse, die dir gehört. Die Zustellung zeigt 204.
  3. In beehiiv erscheint der Abonnent als ausstehend, mit deiner Platzierung als UTM-Quelle und dem Artikel als verweisender Site.
  4. Die Double-Opt-in-E-Mail kommt an. Bestätige sie, und die Willkommens-E-Mail folgt.
  5. Melde diese Adresse in beehiiv ab und melde dich erneut an. Der Abonnent bleibt inaktiv, weil reactivate_existing false ist.

Fragen

Hängst du bei einem Schritt fest oder willst eine Anleitung für deinen Fall? Schreib an hello@ikiform.com.