Warteliste für ein neues SaaS8 Min. Lesezeit
So baust du vor dem App-Store-Launch eine Wartelisten-Seite für eine mobile App
Eine Pre-Launch-Warteliste für eine iOS- oder Android-App, die fragt, welches Handy jemand nutzt, iPhone-Tester zu TestFlight schickt und einen Play-Closed-Test füllt.
Setze ein Wartelisten-Formular auf die Landingpage deiner App, das fragt, welches Handy die Person nutzt und ob sie früh testen will. Schick iPhone-Tester mit einem Webhook und der App Store Connect API in eine TestFlight-Gruppe und lade Android-Tester aus einem Export in einen geschlossenen Test bei Google Play. Schreib am Launch-Tag jeder Gruppe den Link zu ihrem eigenen Store.
Bevor eine App in einem Store ist, gibt es keinen Installieren-Button, zu dem du Leute schicken kannst. Eine Warteliste auf deiner eigenen Landingpage hält ihr Interesse wach, bis es einen gibt, und erledigt eine zweite Aufgabe, die die Stores nicht übernehmen: Sie findet die Tester, die du vor dem Launch brauchst.
Was bei einer mobilen App anders ist
- Zwei Stores, zwei Listen. Die Launch-E-Mail verlinkt auf den App Store oder Google Play, und Testeinladungen laufen über TestFlight oder einen Play-Closed-Test. Du musst die Plattform jeder Person kennen, um die richtige zu senden.
- Tester müssen zum Konto des Stores passen. TestFlight schickt eine Einladung an jede Adresse. Ein Play-Closed-Test lässt nur die Google-Konten auf seiner Liste hinein, ein Android-Tester, der sich mit einer Arbeitsadresse anmeldet, kann den Build also nicht installieren.
- Google Play kann Tester vor dem Launch verlangen. Private Entwicklerkonten, die nach dem 13. November 2023 erstellt wurden, müssen einen geschlossenen Test mit mindestens 12 Testern durchführen, die 14 Tage am Stück dabeibleiben, bevor sie in der Produktion veröffentlichen können. Eine Warteliste ist der Ort, von dem diese 12 kommen.
- Die Stores haben eigene Pre-Launch-Werkzeuge. Es lohnt sich, sie neben einer Warteliste zu nutzen, nicht statt einer. Siehe den Vergleich unten.
| Item | App-Store-Vorbestellungen oder Play-Vorregistrierung | Deine eigene Warteliste |
|---|---|---|
| Braucht einen Store-Eintrag | Ja, freigegeben und bereit | Nein. Sie funktioniert ab dem ersten Tag der Landingpage |
| Was du bekommst | Eine Zahl und eine Store-Benachrichtigung oder einen automatischen Download zum Release | E-Mail, Plattform und Antworten jeder Person |
| Kann Tester einladen | Nein | Ja, per E-Mail zu TestFlight oder einem Play-Closed-Test |
| Grenzen | Die Play-Vorregistrierung bleibt für neue private Konten aus, bis die Testanforderung erfüllt ist | Du sendest die Launch-E-Mail selbst |
Felder für eine App-Warteliste
Frag zuerst nach der Plattform, weil sie ändert, was das E-Mail-Feld bedeutet. Das Handymodell ist optional und sagt dir, auf welchen Geräten du testen solltest. Die Beta-Checkbox trennt Leute, die testen wollen, von Leuten, die die Launch-E-Mail wollen.
Vorschau
Führt den Validator von Ikiform in deinem Browser aus. Es wird nichts gesendet.
platform ist Pflicht, jede Anmeldung landet also in einer Liste, mit der du arbeiten kannst. Füge die Definition im Tab Fields des Formulars ein.Das Formular
Das Formular funktioniert als einfaches HTML auf jeder Landingpage. Das Skript tut zwei kleine Dinge: Es wählt die Plattform anhand des Browsers vor und zeigt den Hinweis zum Google-Konto nur Android-Nutzern.
<form id="app-waitlist" action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="post">
<fieldset>
<legend>Which phone do you use?</legend>
<label><input type="radio" name="platform" value="iphone" required> iPhone</label>
<label><input type="radio" name="platform" value="android"> Android</label>
</fieldset>
<label for="email">Email</label>
<input id="email" name="email" type="email" autocomplete="email" inputmode="email" required>
<p id="email-hint" hidden>Use the Google account you sign in to Google Play with.</p>
<label for="first_name">First name</label>
<input id="first_name" name="first_name" autocomplete="given-name" maxlength="60">
<label for="device">Phone model</label>
<input id="device" name="device" maxlength="80" placeholder="iPhone 15, Pixel 8">
<label><input type="checkbox" name="beta" value="true"> Invite me to test the app before launch</label>
<input name="_gotcha" type="text" tabindex="-1" autocomplete="off" hidden>
<button>Join the waitlist</button>
</form>
<script>
const form = document.getElementById("app-waitlist");
const agent = navigator.userAgent;
const guess = /iPhone|iPad/.test(agent) ? "iphone" : /Android/.test(agent) ? "android" : null;
if (guess) form.querySelector(`[name="platform"][value="${guess}"]`).checked = true;
const hint = () => {
document.getElementById("email-hint").hidden = form.platform.value !== "android";
};
form.addEventListener("change", hint);
hint();
</script>- Die Vermutung wählt nur ein Radio vor. Die Leute können es ändern, und ohne das Skript ist nichts ausgewählt,
requiredzwingt sie also zur Wahl. inputmode="email"undautocomplete="email"zählen hier mehr als irgendwo sonst: Die meisten Besucher der Landingpage einer App sind am Handy.- Setze Redirect after submit auf eine Dankeseite, die sagt, was für jede Plattform als Nächstes passiert. Für eine Framework-Version des Formulars siehe die Hauptanleitung und füge diese Felder hinzu.
Tester an jeden Store leiten
- Ein iPhone-Nutzer, der die Beta-Checkbox anhakt, löst einen signierten Webhook aus.
- Dein Relay verifiziert ihn und ruft die App Store Connect API auf, um die Adresse einer TestFlight-Gruppe hinzuzufügen.
- Apple sendet die TestFlight-Einladung, sobald für die Gruppe ein Build verfügbar ist.
- Android-Tester werden genauso gesammelt, dann als CSV exportiert und nach Plattform gefiltert.
- Du fügst die Google-Konten in der Play Console in die E-Mail-Liste des geschlossenen Tests ein.
- Du schickst ihnen aus deinem E-Mail-Tool den Opt-in-Link des Tests.
iPhone: Tester zu TestFlight hinzufügen
Erstelle in App Store Connect eine externe Testgruppe und unter Users and Access › Integrations einen API-Schlüssel mit der Rolle App Manager oder Admin. Füge dann ein Relay hinzu, das auf Ikiforms Webhook submission.created hört. Dieses hier ist ein Next.js-Route-Handler und nutzt jose, um Apples Token zu signieren; es läuft auf jedem Server, der fetch hat.
import { verifyWebhook, WebhookVerificationError } from "@ikiform/sdk/webhooks";
import { importPKCS8, SignJWT } from "jose";
async function appStoreToken() {
const key = await importPKCS8(process.env.ASC_PRIVATE_KEY!, "ES256");
return new SignJWT({})
.setProtectedHeader({ alg: "ES256", kid: process.env.ASC_KEY_ID!, typ: "JWT" })
.setIssuer(process.env.ASC_ISSUER_ID!)
.setAudience("appstoreconnect-v1")
.setIssuedAt()
.setExpirationTime("15m")
.sign(key);
}
export async function POST(request: Request) {
const payload = await request.text();
try {
const event = await verifyWebhook({ payload, headers: request.headers, secret: process.env.IKIFORM_WEBHOOK_SECRET! });
if (event.type !== "submission.created") return new Response(null, { status: 204 });
const { email, first_name, platform, beta } = event.data.fields;
if (platform !== "iphone" || beta !== true) return new Response(null, { status: 204 });
const response = await fetch("https://api.appstoreconnect.apple.com/v1/betaTesters", {
method: "POST",
headers: { authorization: `Bearer ${await appStoreToken()}`, "content-type": "application/json" },
body: JSON.stringify({
data: {
type: "betaTesters",
attributes: { email: String(email), firstName: first_name ? String(first_name) : undefined },
relationships: { betaGroups: { data: [{ type: "betaGroups", id: process.env.ASC_BETA_GROUP_ID! }] } },
},
}),
});
if (response.ok || response.status === 409) return new Response(null, { status: 204 });
return new Response(`App Store Connect answered ${response.status}`, { status: 502 });
} catch (error) {
if (error instanceof WebhookVerificationError) return new Response(error.reason, { status: 400 });
throw error;
}
}ASC_PRIVATE_KEYist der Inhalt der.p8-Datei, die Apple dir gibt, mit Zeilenumbrüchen.ASC_KEY_IDundASC_ISSUER_IDstehen auf derselben Seite.- Apples Tokens dürfen höchstens 20 Minuten gelten, das Relay signiert also pro Zustellung ein frisches.
- Ein
409heißt, Apple hat die Änderung als Konflikt abgelehnt, oft weil die Adresse schon Tester ist. Das Relay behandelt das als erledigt; wenn ein Tester also nie eine Einladung bekommt, prüfe die Gruppe in App Store Connect. Jeder andere Fehler antwortet mit502, damit Ikiform die Zustellung wiederholt. - TestFlight erlaubt bis zu 10.000 externe Tester pro App. Der erste Build, den du einer externen Gruppe gibst, durchläuft die Beta App Review, und jeder Build läuft nach 90 Tagen ab.
Füge die URL des Relays in Ikiform unter Webhooks hinzu und kopiere das whsec_-Secret in IKIFORM_WEBHOOK_SECRET. Ein Workspace kann 3 Endpunkte haben, das hier kann also neben einem Relay laufen, das dein E-Mail-Tool füttert.
Android: einen geschlossenen Test füllen
Die Publishing-API von Google Play verwaltet Tester geschlossener Tests über Google Groups, nicht über einzelne Adressen, diese Seite ist also ein wöchentlicher Export. Exportiere die Liste mit Export CSV, filtere sie in einer Tabelle auf platform = android und beta = true und füge die E-Mails in der Play Console unter Test and release › Testing › Closed testing › Manage track › Testers zur E-Mail-Liste des geschlossenen Tests hinzu. Schick diesen Leuten dann aus deinem E-Mail-Tool den Opt-in-Link des Tests.
Wenn du die Anforderung von 12 Testern erfüllen willst, lade mehr als 12 ein. Leute, die sich abmelden oder nie zustimmen, zählen nicht, und die 14 Tage brauchen die ganze Zeit 12 Tester, die zugestimmt haben.
Launch-Tag
Exportiere die ganze Liste und teile sie nach platform auf. Schick jeder Hälfte eine E-Mail mit einem Store-Link. Wer iPhone gewählt hat, braucht den Play-Link nicht, und eine einzelne E-Mail mit zwei Badges verliert auf einem kleinen Bildschirm Taps. Wenn du device gesammelt hast, gleich vor dem Versand deine Absturzberichte mit den Modellen ab, die die Leute angegeben haben.
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. - Öffne die Seite auf einem Handy. Die richtige Plattform ist vorausgewählt, und auf Android erscheint der Hinweis zum Google-Konto.
- Sende als iPhone-Tester ab. Die Einsendung zeigt
platformalsiphoneundbetaalstrue. - Öffne den Endpunkt des Relays unter Webhooks. Die Zustellung zeigt
succeeded, und die Adresse steht in deiner TestFlight-Gruppe. - Sende als Android-Tester ab, exportiere die CSV und prüfe, dass die Zeile mit
platformaufandroidherausgefiltert wird. - 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 |
|---|---|
Die Zustellungen des Relays scheitern mit 502, und Apple hat 401 geantwortet | Das Token ist falsch: Prüfe die Key-ID, die Issuer-ID und dass der Private Key in der Umgebungsvariable seine Zeilenumbrüche behalten hat. |
| Ein Tester wurde hinzugefügt, hat aber keine TestFlight-E-Mail bekommen | Die Gruppe hat noch keinen Build, oder der erste Build ist noch in der Beta App Review. Einladungen gehen raus, sobald ein Build für die Gruppe verfügbar ist. |
| Ein Android-Tester kann den Opt-in-Link nicht öffnen | Die Adresse auf der Liste ist nicht das Google-Konto, das auf dem Handy angemeldet ist. Bitte die Person, sich mit diesem Konto erneut anzumelden. |
422 validation_failed | Der Post passt nicht zur Felddefinition des Formulars. error.fields nennt jedes Feld und den Grund. Gleiche den name des Eingabefelds an die Feld-ID an. |
| Die Einsendung ist im Dashboard, aber keine E-Mail und kein Webhook kam an | Sie wurde als Spam gespeichert. Spam löst nichts aus. Öffne sie unter dem Filter Spam, um die Gründe zu sehen, und markiere sie als kein Spam, um ihre E-Mail und Webhooks zu senden. |
Fragen
Beide erledigen unterschiedliche Aufgaben. Vorbestellungen und die Play-Vorregistrierung brauchen einen freigegebenen Store-Eintrag und geben dir eine Zahl, keine Kontakte. Eine Warteliste funktioniert ab dem ersten Tag, gibt dir E-Mail und Plattform jeder Person und lässt dich Tester einladen.
Frag auf deiner Warteliste danach. Eine Beta-Checkbox und eine Plattform-Frage zeigen dir, wer ein Android-Handy hat und testen will. Setz ihre Google-Konten auf die E-Mail-Liste des geschlossenen Tests und schick ihnen den Opt-in-Link.
Nicht direkt. Ikiform sendet für jede Anmeldung einen signierten Webhook, und ein kurzes Relay, das du deployst, fügt die Adresse über die App Store Connect API einer TestFlight-Gruppe hinzu, wie oben gezeigt.
Nein. Ikiform schickt E-Mails an dich und dein Team, nicht an den Absender, es gibt also keinen Autoresponder und keine Bestätigungs-E-Mail. Sende einen Webhook an dein E-Mail-Tool und verschicke die Bestätigung von dort.
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.