Liste d'attente pour un nouveau SaaS9 min de lecture
Comment créer une page de liste d'attente pour une application mobile avant sa sortie sur l'App Store
Une liste d'attente avant lancement pour une app iOS ou Android qui demande le téléphone utilisé, envoie les testeurs iPhone vers TestFlight et remplit un test fermé Play.
Placez sur la landing page de votre app un formulaire de liste d'attente qui demande quel téléphone la personne utilise et si elle veut tester en avant-première. Envoyez les testeurs iPhone dans un groupe TestFlight avec un webhook et l'API App Store Connect, et chargez les testeurs Android dans un test fermé Google Play à partir d'un export. Le jour du lancement, envoyez à chaque groupe le lien vers sa boutique.
Avant qu'une app ne soit sur une boutique, il n'y a pas de bouton d'installation vers lequel envoyer les gens. Une liste d'attente sur votre propre landing page entretient leur intérêt d'ici là, et remplit un second rôle que les boutiques ne remplissent pas : trouver les testeurs dont vous avez besoin avant le lancement.
Ce qui change pour une application mobile
- Deux boutiques, deux listes. L'e-mail de lancement renvoie vers l'App Store ou Google Play, et les invitations de test passent par TestFlight ou un test fermé Play. Il vous faut connaître la plateforme de chaque personne pour envoyer le bon lien.
- Les testeurs doivent correspondre au compte de la boutique. TestFlight envoie une invitation par e-mail à n'importe quelle adresse. Un test fermé Play n'accepte que les comptes Google de sa liste : un testeur Android inscrit avec une adresse professionnelle ne peut donc pas installer le build.
- Google Play peut exiger des testeurs avant le lancement. Les comptes développeur personnels créés après le 13 novembre 2023 doivent mener un test fermé avec au moins 12 testeurs restés inscrits 14 jours d'affilée avant de pouvoir publier en production. Une liste d'attente est l'endroit d'où viennent ces 12 personnes.
- Les boutiques ont leurs propres outils d'avant-lancement. Ils valent la peine d'être utilisés à côté d'une liste d'attente, pas à sa place. Voir la comparaison ci-dessous.
| Item | Précommandes App Store ou pré-inscription Play | Votre propre liste d'attente |
|---|---|---|
| Nécessite une fiche sur la boutique | Oui, approuvée et prête | Non. Elle fonctionne dès le premier jour de la landing page |
| Ce que vous obtenez | Un compteur, et une notification de la boutique ou un téléchargement automatique à la sortie | L'e-mail, la plateforme et les réponses de chaque personne |
| Peut inviter des testeurs | Non | Oui, par e-mail vers TestFlight ou un test fermé Play |
| Limites | La pré-inscription Play reste désactivée pour les nouveaux comptes personnels tant que l'exigence de test n'est pas remplie | Vous envoyez vous-même l'e-mail de lancement |
Les champs d'une liste d'attente d'app
Demandez d'abord la plateforme, car elle change le sens du champ e-mail. Le modèle de téléphone est facultatif et vous indique sur quels appareils tester. La case bêta distingue les personnes qui veulent tester de celles qui veulent l'e-mail de lancement.
Aperçu
Exécute le validateur d'Ikiform dans votre navigateur. Rien n'est envoyé.
platform est obligatoire : chaque inscription atterrit donc dans une liste exploitable. Collez la définition dans l'onglet Fields du formulaire.Le formulaire
Le formulaire fonctionne en HTML simple sur n'importe quelle landing page. Le script fait deux petites choses : il présélectionne la plateforme d'après le navigateur du visiteur, et n'affiche l'indication sur le compte Google qu'aux utilisateurs Android.
<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>- La supposition ne fait que présélectionner un radio. Les gens peuvent la changer, et sans le script rien n'est sélectionné :
requiredles oblige alors à choisir. inputmode="email"etautocomplete="email"comptent ici plus qu'ailleurs : la plupart des visiteurs de la landing page d'une app sont sur téléphone.- Réglez Redirect after submit sur une page de remerciement qui explique la suite pour chaque plateforme. Pour une version du formulaire avec un framework, voir le guide principal et ajoutez ces champs.
Diriger les testeurs vers chaque boutique
- Un utilisateur d'iPhone qui coche la case bêta déclenche un webhook signé.
- Votre relais le vérifie et appelle l'API App Store Connect pour ajouter l'adresse à un groupe TestFlight.
- Apple envoie l'invitation TestFlight par e-mail dès qu'un build est disponible pour le groupe.
- Les testeurs Android sont collectés de la même façon, puis exportés en CSV et filtrés par plateforme.
- Vous collez les comptes Google dans la liste d'e-mails du test fermé dans la Play Console.
- Vous leur envoyez le lien d'inscription au test depuis votre outil d'e-mailing.
iPhone : ajouter des testeurs à TestFlight
Dans App Store Connect, créez un groupe de test externe et une clé d'API sous Users and Access › Integrations, avec le rôle App Manager ou Admin. Ajoutez ensuite un relais qui écoute le webhook submission.created d'Ikiform. Celui-ci est un route handler Next.js qui utilise jose pour signer le jeton d'Apple ; il tourne sur n'importe quel serveur doté de fetch.
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_KEYest le contenu du fichier.p8fourni par Apple, sauts de ligne compris.ASC_KEY_IDetASC_ISSUER_IDsont sur la même page.- Les jetons d'Apple durent au plus 20 minutes : le relais en signe donc un nouveau à chaque livraison.
- Un
409signifie qu'Apple a refusé la modification pour cause de conflit, souvent parce que l'adresse est déjà testeuse. Le relais le considère comme fait : si un testeur ne reçoit jamais d'invitation, vérifiez le groupe dans App Store Connect. Tout autre échec répond502, et Ikiform réessaie la livraison. - TestFlight autorise jusqu'à 10 000 testeurs externes par app. Le premier build donné à un groupe externe passe par la Beta App Review, et chaque build expire après 90 jours.
Ajoutez l'URL du relais sous Webhooks dans Ikiform et copiez le secret whsec_ dans IKIFORM_WEBHOOK_SECRET. Un espace de travail peut avoir 3 endpoints : celui-ci peut donc tourner à côté d'un relais qui alimente votre outil d'e-mailing.
Android : remplir un test fermé
L'API de publication de Google Play gère les testeurs des tests fermés via Google Groups, pas par adresses individuelles : ce côté est donc un export hebdomadaire. Exportez la liste avec Export CSV, filtrez-la dans un tableur sur platform = android et beta = true, et ajoutez les e-mails à la liste d'e-mails du test fermé sous Test and release › Testing › Closed testing › Manage track › Testers dans la Play Console. Envoyez ensuite à ces personnes le lien d'inscription au test depuis votre outil d'e-mailing.
Si vous visez l'exigence des 12 testeurs, invitez-en plus de 12. Les personnes qui se désinscrivent ou ne s'inscrivent jamais ne comptent pas, et les 14 jours exigent 12 testeurs inscrits pendant toute la période.
Le jour du lancement
Exportez toute la liste et répartissez-la par platform. Envoyez à chaque moitié un e-mail avec un seul lien de boutique. Les personnes qui ont choisi iPhone n'ont pas besoin du lien Play, et un seul e-mail avec deux badges perd des clics sur un petit écran. Si vous avez collecté device, comparez vos rapports de crash aux modèles indiqués avant d'envoyer.
Vérifiez que tout fonctionne
- Dans Allowed domains du formulaire, ajoutez le domaine de votre site, plus
localhostpendant le développement. Laissez vide pour accepter les envois de partout. - Ouvrez la page sur un téléphone. La bonne plateforme est présélectionnée, et sur Android l'indication sur le compte Google s'affiche.
- Envoyez en tant que testeur iPhone. La soumission affiche
platformàiphoneetbetaàtrue. - Ouvrez l'endpoint du relais sous Webhooks. La livraison affiche
succeeded, et l'adresse figure dans votre groupe TestFlight. - Envoyez en tant que testeur Android, exportez le CSV et vérifiez que la ligne ressort avec le filtre
platformréglé surandroid. - Envoyez avec le honeypot rempli,
_gotcha=bot. L'envoi reçoit quand même une réponse de succès, mais la soumission est stockée comme spam et n'envoie ni e-mail ni webhook.
Pièges
| Problème | Que faire |
|---|---|
Les livraisons du relais échouent avec 502 et Apple a répondu 401 | Le jeton est faux : vérifiez l'id de clé, l'id d'émetteur et que la clé privée a gardé ses sauts de ligne dans la variable d'environnement. |
| Un testeur a été ajouté mais n'a reçu aucun e-mail TestFlight | Le groupe n'a pas encore de build, ou le premier build est encore en Beta App Review. Les invitations partent dès qu'un build est disponible pour le groupe. |
| Un testeur Android ne peut pas ouvrir le lien d'inscription | L'adresse de la liste n'est pas le compte Google connecté sur le téléphone. Demandez-lui de se réinscrire avec ce compte. |
422 validation_failed | L'envoi ne correspond pas à la définition des champs du formulaire. error.fields nomme chaque champ et la raison. Faites correspondre le name de l'input à l'id du champ. |
| La soumission est dans le tableau de bord mais aucun e-mail ni webhook n'est arrivé | Elle a été stockée comme spam. Le spam n'envoie rien. Ouvrez-la sous le filtre Spam pour voir les raisons, et marquez-la comme non-spam pour envoyer son e-mail et ses webhooks. |
Questions
Elles n'ont pas le même rôle. Les précommandes et la pré-inscription Play exigent une fiche approuvée sur la boutique et vous donnent un compteur, pas des contacts. Une liste d'attente fonctionne dès le premier jour, vous donne l'e-mail et la plateforme de chaque personne, et vous permet d'inviter des testeurs.
Demandez-les sur votre liste d'attente. Une case bêta et une question sur la plateforme vous montrent qui a un téléphone Android et veut tester. Mettez leurs comptes Google dans la liste d'e-mails du test fermé et envoyez-leur le lien d'inscription.
Pas directement. Ikiform envoie un webhook signé pour chaque inscription, et un court relais que vous déployez ajoute l'adresse à un groupe TestFlight via l'API App Store Connect, comme montré ci-dessus.
Non. Ikiform envoie des e-mails à vous et à votre équipe, pas à l'expéditeur : il n'y a donc ni réponse automatique ni e-mail de confirmation. Envoyez un webhook à votre outil d'e-mailing et envoyez la confirmation depuis celui-ci.
Non, il n'y a pas d'offre gratuite. Les tests sont gratuits : vous pouvez envoyer 50 soumissions de test par mois depuis localhost avant de payer. Pour passer en production, Pro commence à 6 $/mois pour 500 soumissions, ou vous pouvez payer une seule fois 10 000 soumissions pour 49 $ ou 50 000 soumissions pour 149 $, avec des crédits qui n'expirent jamais.
Une étape vous bloque, ou vous voulez un guide pour votre cas ? Écrivez à hello@ikiform.com.