Warteliste für ein neues SaaS6 Min. Lesezeit
So fügst du jeder Landingpage ein Wartelisten-Formular in reinem HTML hinzu
Eine komplette Wartelisten-Seite in reinem HTML ohne Build, die ohne JavaScript funktioniert, nach dem Laden ein Danke inline zeigt und bei Bedarf zurückfällt.
Schreib ein normales HTML-Formular, das die E-Mail an deinen Ikiform-Endpunkt sendet und auf eine Dankeseite weiterleitet, damit es auf jedem Host ganz ohne JavaScript funktioniert. Füge dann ein kleines Skript hinzu, das dasselbe Formular mit fetch sendet, das Danke inline zeigt und an den einfachen Post zurückgibt, wann immer das Skript nicht fertig werden kann, etwa wenn die Menschlichkeitsprüfung aktiv ist.
Eine Wartelisten-Seite braucht kein Framework, keinen Build-Schritt und keinen Server. Vier statische Dateien und ein Formular-Backend reichen, und die Seite lädt schneller als alles, was ein Baukasten exportiert. Diese Seite baut das Ganze Schicht für Schicht, sodass jede Schicht für sich funktioniert.
Worauf es ohne Build-Schritt ankommt
- Das Formular ist die Integration. Ein einfaches
<form>mit eineractionist die ganze Verbindung zu Ikiform. Kein Paket, kein API-Schlüssel, nichts zu kompilieren. - JavaScript ist ein Upgrade, keine Voraussetzung. Die Seite sollte Anmeldungen sammeln, wenn das Skript blockiert, langsam oder kaputt ist. Jede Schicht unten baut auf der vorherigen auf und fällt auf sie zurück.
- Das Skript darf niemanden festhalten. Wenn
fetchscheitert oder Ikiform eine Menschlichkeitsprüfung verlangt, diefetchnicht ausführen kann, gibt das Skript das Formular an den Browser zurück, der es auf normalem Weg sendet. - Hosting geht überall. GitHub Pages, Netlify, Cloudflare Pages, ein S3-Bucket oder ein Shared Host liefern diese Dateien so aus, wie sie sind.
| Schicht | Was sie hinzufügt | Wenn sie fehlt |
|---|---|---|
| HTML-Formular | Sendet die E-Mail, leitet zu thanks.html weiter | Nichts funktioniert, deshalb kommt es zuerst |
| CSS | Eine lesbare Seite im hellen und dunklen Modus | Ein schlichtes, aber funktionierendes Formular |
| Skript | Danke inline, Feldfehler, kein Seitenwechsel | Der einfache Post und die Weiterleitung |
- Ohne JavaScript sendet der Browser das Formular, Ikiform leitet mit 303 auf deine _redirect-URL weiter, und der Besucher sieht thanks.html.
- Ist das Skript geladen, sendet es mit fetch und verlangt JSON. Ikiform antwortet mit 201 oder einem Fehler, und das Skript zeigt das Ergebnis auf derselben Seite.
- Wenn fetch scheitert oder Ikiform mit challenge_required antwortet, ruft das Skript form.submit() auf.
- Dieser einfache Post führt bei Bedarf Ikiforms Prüfseite aus und endet auf thanks.html.
Die Dateien
Die Seite
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Acme is almost here</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<main>
<h1>Acme is almost here</h1>
<p>Invoices that chase themselves. Leave your email and we'll invite you first.</p>
<form id="waitlist" action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="post">
<label for="email">Email</label>
<div class="row">
<input id="email" name="email" type="email" autocomplete="email" required placeholder="you@company.com">
<button>Join the waitlist</button>
</div>
<input type="hidden" name="_redirect" value="https://example.com/thanks.html">
<input name="_gotcha" type="text" tabindex="-1" autocomplete="off" hidden>
<p class="message" role="status" aria-live="polite"></p>
</form>
</main>
<script src="waitlist.js" defer></script>
</body>
</html>_redirectschickt den Browser nach einem einfachen Post zuthanks.html. Es funktioniert nur für einehttps:-URL auf einer der Allowed domains des Formulars, füge deine Domain also dort hinzu. Redirect after submit in den Einstellungen des Formulars tut dasselbe ohne das versteckte Eingabefeld.- Das Eingabefeld
_gotchaist der Honeypot. Menschen sehen es nie; Bots, die jedes Eingabefeld ausfüllen, werden als Spam gespeichert. aria-live="polite"lässt Screenreader die Meldungen des Skripts ansagen, ohne den Fokus zu verschieben.- Das Skript-Tag nutzt
defer, es läuft also, nachdem das Formular existiert, und blockiert nie das Zeichnen der Seite.
Die Erweiterung
const form = document.getElementById("waitlist");
const message = form.querySelector(".message");
const button = form.querySelector("button");
const key = crypto.randomUUID();
form.addEventListener("submit", async (event) => {
event.preventDefault();
button.disabled = true;
message.textContent = "Joining…";
try {
const response = await fetch(form.action, {
method: "POST",
headers: { Accept: "application/json", "Idempotency-Key": key },
body: new FormData(form),
});
const result = await response.json();
if (result.ok) {
form.replaceChildren(Object.assign(document.createElement("p"), {
textContent: "You're on the list. We'll email you on launch day.",
role: "status",
}));
return;
}
if (result.error.code === "challenge_required") {
form.submit();
return;
}
const wait = response.headers.get("Retry-After");
message.textContent = wait
? `Too many tries. Wait ${wait} seconds and try again.`
: result.error.fields?.email?.[0] ?? result.error.message;
} catch {
form.submit();
return;
}
button.disabled = false;
});Accept: application/jsonlässt Ikiform mit JSON statt mit einer Weiterleitung antworten, damit das Skript das Ergebnis an Ort und Stelle zeigen kann.- Der Idempotenzschlüssel wird einmal pro Seitenaufruf erzeugt. Ein Doppelklick oder ein erneuter Versuch nach einer langsamen Antwort speichert eine Anmeldung.
challenge_requiredheißt, die Spamprüfung des Formulars steht auf Ikiform undfetchhat kein Token gesendet.form.submit()sendet auf die einfache Art, was Ikiforms Prüfseite und dann die Dankeseite zeigt. Es löst dassubmit-Event nicht erneut aus, es gibt also keine Schleife.- Ein Netzwerkfehler nimmt denselben Fallback. War Ikiform nicht erreichbar, zeigt der einfache Post den eigenen Fehler des Browsers, was immer noch ehrlicher ist als ein hängender Button.
- Ein
429liestRetry-Afterund sagt, wie lange zu warten ist.
Die Dankeseite
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>You're on the list</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<main>
<h1>You're on the list</h1>
<p>We'll email you the day Acme opens. Nothing before that.</p>
<p><a href="/">Back to the page</a></p>
</main>
</body>
</html>Die Styles
body { margin: 0; font: 16px/1.5 system-ui, sans-serif; color: #111; background: #fff; }
main { max-width: 34rem; margin: 0 auto; padding: 18vh 1rem 4rem; }
h1 { font-size: 2.25rem; line-height: 1.1; margin: 0 0 0.75rem; }
label { display: block; font-weight: 600; margin: 1.5rem 0 0.375rem; }
.row { display: flex; flex-wrap: wrap; gap: 0.5rem; }
input[type="email"] { flex: 1 1 14rem; font: inherit; padding: 0.625rem 0.75rem; border: 1px solid #ccc; border-radius: 0.5rem; }
button { font: inherit; padding: 0.625rem 1rem; border: 0; border-radius: 0.5rem; background: #111; color: #fff; cursor: pointer; }
button:disabled { opacity: 0.6; cursor: progress; }
.message { min-height: 1.5em; margin: 0.5rem 0 0; }
@media (prefers-color-scheme: dark) {
body { color: #eee; background: #111; }
input[type="email"] { background: #1b1b1b; color: inherit; border-color: #444; }
button { background: #eee; color: #111; }
}example.com liegt, passe _redirect und den Link zurück an. Ikiform ignoriert ein _redirect, dem es nicht folgen kann, und zeigt stattdessen seine eigene gehostete Dankeseite, eine Abweichung kostet also nie eine Anmeldung.Deployen und testen
Leg die vier Dateien in einen Ordner und lade ihn auf einen beliebigen statischen Host hoch. Füge dann die Domain des Hosts unter Allowed domains hinzu: zum Beispiel username.github.io, your-site.netlify.app oder deine eigene Domain. Solange du lokal arbeitest, füge auch localhost hinzu; liefere den Ordner mit einem beliebigen statischen Server aus, denn eine als file://-URL geöffnete Seite sendet keinen Origin.
Prüfen, ob es funktioniert
- Füge unter Allowed domains des Formulars die Domain deiner Site hinzu, plus
localhost, während du entwickelst. Lass das Feld leer, um Posts von überall anzunehmen. - Schalte im Browser JavaScript aus und melde dich an. Du landest auf
thanks.html. - Schalte es wieder ein und melde dich erneut an. Das Formular wird durch die Dankeszeile ersetzt, ohne die Seite zu verlassen.
- Setze Spam check auf Ikiform und melde dich noch einmal an. Die Seite wechselt zur Prüfung, dann zu
thanks.html. - Öffne Submissions im Dashboard. Die neue Einsendung ist da, mit jedem Feld, das du gesendet hast.
- Sende einen Post mit ausgefülltem Honeypot,
_gotcha=bot. Er bekommt trotzdem eine Erfolgsantwort, aber die Einsendung wird als Spam gespeichert und löst weder E-Mail noch Webhook aus.
Stolperfallen
| Problem | Was zu tun ist |
|---|---|
| Der Browser landet auf der Dankeseite von Ikiform statt auf deiner | _redirect wird ignoriert, außer seine Domain steht unter Allowed domains und es ist eine https:-URL. Füge die Domain hinzu oder setze stattdessen Redirect after submit in den Einstellungen des Formulars. |
403 origin_not_allowed, oder jeder Post landet im Spam | Die Domain der Seite steht nicht unter Allowed domains des Formulars. Füge sie hinzu, plus localhost für lokale Tests. Subdomains einer eingetragenen Domain sind erlaubt. |
| Posts von einer als Datei geöffneten Seite werden abgelehnt oder als Spam markiert | Eine file://-Seite sendet keinen Origin. Liefere den Ordner mit einem lokalen statischen Server aus und füge localhost zu Allowed domains hinzu. |
| Die Dankeszeile erscheint nie, aber Anmeldungen kommen an | Das Skript wurde nicht geladen: Prüfe den Pfad im src-Attribut oder ob der Host .js-Dateien ausliefert. Der einfache Post funktioniert weiterhin, deshalb kommen Anmeldungen an. |
402 test_limit_reached | Der Workspace hat keinen Tarif und hat seine 50 kostenlosen localhost-Tests diesen Monat aufgebraucht. Wähle einen Tarif oder nutze Send test im Dashboard. |
Die Doku zu HTML-Formularen listet jedes reservierte Feld auf, und die Wartelisten-Vorlage erzeugt eine Version mit Name und Rolle. Export der Liste und die Launch-E-Mail stehen in der Hauptanleitung.
Fragen
Ja. Ein einfaches HTML-Formular sendet die E-Mail an deinen Ikiform-Endpunkt, und Ikiform leitet den Browser auf deine Dankeseite weiter. JavaScript fügt nur die Inline-Meldung hinzu.
Überall, wo statische Dateien ausgeliefert werden: GitHub Pages, Netlify, Cloudflare Pages, S3 oder ein Shared Host. Das Formular sendet an Ikiform, der Host führt also nie Code aus.
Ikiform antwortet mit 403 challenge_required. Das Skript in dieser Anleitung fängt das ab und sendet das Formular auf die einfache Art, was die Prüfseite und dann deine Dankeseite zeigt.
Nein. Ikiform hat keine gehosteten Formularseiten. Du setzt das Formular auf deine eigene Site, in jedem Baukasten oder Framework, und richtest es auf deinen Ikiform-Endpunkt aus.
Nein, es gibt keinen kostenlosen Tarif. Testen ist kostenlos: Du kannst 50 Testeinsendungen pro Monat von localhost senden, bevor du zahlst. Für den Livebetrieb startet Pro bei $6/Monat für 500 Einsendungen, oder du zahlst einmalig 10.000 Einsendungen für $49 oder 50.000 Einsendungen für $149, mit Guthaben, das nie verfällt.
Hängst du bei einem Schritt fest oder willst eine Anleitung für deinen Fall? Schreib an hello@ikiform.com.