# Como montar uma página de lista de espera para um app mobile antes do lançamento na App Store

> Uma lista de espera pré-lançamento para um app iOS ou Android que pergunta qual celular a pessoa usa, manda testadores de iPhone ao TestFlight e preenche um teste fechado do Play.

Publicado em 2026-10-25 · https://ikiform.com/pt-br/guides/waitlist/mobile-app

Coloque um formulário de lista de espera na landing page do seu app que pergunta qual celular a pessoa usa e se ela quer testar antes. Mande os testadores de iPhone para um grupo do TestFlight com um webhook e a API do App Store Connect, e carregue os testadores de Android num teste fechado do Google Play a partir de uma exportação. No dia do lançamento, mande a cada grupo o link da loja dele.

Antes de um app estar numa loja, não existe botão de instalar para onde mandar as pessoas. Uma lista de espera na sua própria landing page mantém o interesse delas até existir, e faz um segundo trabalho que as lojas não fazem: encontra os testadores de que você precisa antes do lançamento.

## O que muda para um app mobile

- **Duas lojas, duas listas.** O e-mail de lançamento leva à App Store ou ao Google Play, e os convites de teste passam pelo TestFlight ou por um teste fechado do Play. Você precisa saber a plataforma de cada pessoa para mandar o certo.
- **Os testadores precisam bater com a conta da loja.** O TestFlight manda um convite por e-mail para qualquer endereço. Um teste fechado do Play só aceita as contas Google que estão na lista dele, então um testador de Android que se inscreve com um endereço de trabalho não consegue instalar o build.
- **O Google Play pode exigir testadores antes do lançamento.** Contas pessoais de desenvolvedor criadas depois de 13 de novembro de 2023 precisam rodar um teste fechado com pelo menos 12 testadores que continuem inscritos por 14 dias seguidos antes de poder publicar em produção. Uma lista de espera é de onde vêm esses 12.
- **As lojas têm as próprias ferramentas de pré-lançamento.** Vale usá-las junto com uma lista de espera, não no lugar dela. Veja a comparação abaixo.

|   | Pré-venda na App Store ou pré-registro no Play | Sua própria lista de espera |
| --- | --- | --- |
| Precisa de página na loja | Sim, aprovada e pronta | Não. Funciona desde o primeiro dia da landing page |
| O que você recebe | Uma contagem, e uma notificação da loja ou download automático no lançamento | O e-mail, a plataforma e as respostas de cada pessoa |
| Pode convidar testadores | Não | Sim, por e-mail para o TestFlight ou um teste fechado do Play |
| Limites | O pré-registro do Play fica desligado para contas pessoais novas até o requisito de testes ser cumprido | Você mesmo envia o e-mail de lançamento |

## Campos para uma lista de espera de app

Pergunte a plataforma primeiro, porque ela muda o que o campo de e-mail significa. O modelo do celular é opcional e diz em quais aparelhos testar. O checkbox do beta separa quem quer testar de quem quer o e-mail de lançamento.

Formulário: App waitlist

- **E-mail** (`email`, email, obrigatório)
- **Primeiro nome** (`first_name`, text)
- **Qual celular você usa?** (`platform`, radio, obrigatório)
- **Modelo do celular** (`device`, text)
- **Quero ser convidado para testar o app antes do lançamento** (`beta`, checkbox)

O radio `platform` é obrigatório, então toda inscrição cai numa lista com a qual você consegue agir. Cole a definição na aba **Fields** do formulário.

## O formulário

O formulário funciona como HTML simples em qualquer landing page. O script faz duas coisinhas: pré-seleciona a plataforma a partir do navegador do visitante e mostra a dica da conta Google só para usuários de Android.

`index.html`:

```html
<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>
```

- O palpite só pré-seleciona um radio. As pessoas podem mudar, e sem o script nada vem selecionado, então o `required` as obriga a escolher.
- `inputmode="email"` e `autocomplete="email"` importam aqui mais do que em qualquer lugar: a maioria dos visitantes da landing page de um app está no celular.
- Defina **Redirect after submit** com uma página de agradecimento que diga o que acontece em seguida para cada plataforma. Para uma versão do formulário com framework, veja o [guia principal](https://ikiform.com/pt-br/guides/waitlist.md#form) e adicione estes campos.

## Direcione os testadores para cada loja

Diagrama: Como os testadores de iPhone e Android chegam ao beta de cada loja

1. Um usuário de iPhone que marca o checkbox do beta dispara um webhook assinado.
2. Seu relay o verifica e chama a API do App Store Connect para adicionar o endereço a um grupo do TestFlight.
3. A Apple envia o convite do TestFlight por e-mail quando o grupo tem um build disponível.
4. Os testadores de Android são coletados do mesmo jeito, depois exportados como CSV e filtrados por plataforma.
5. Você cola as contas Google na lista de e-mails do teste fechado no Play Console.
6. Você manda para eles o link de inscrição do teste pela sua ferramenta de e-mail.

A Apple tem uma API para testadores; os testes fechados do Google Play são gerenciados no Play Console ou por Google Groups, então o lado Android é uma exportação semanal.

### iPhone: adicione testadores ao TestFlight

No App Store Connect, crie um grupo de teste externo e uma chave de API em **Users and Access** › **Integrations**, com a função App Manager ou Admin. Depois adicione um relay que escuta o webhook `submission.created` do Ikiform. Este é um route handler do Next.js e usa `jose` para assinar o token da Apple; ele roda em qualquer servidor que tenha `fetch`.

`app/api/testflight/route.ts`:

```ts
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_KEY` é o conteúdo do arquivo `.p8` que a Apple fornece, com as quebras de linha. `ASC_KEY_ID` e `ASC_ISSUER_ID` estão na mesma página.
- Os tokens da Apple podem durar no máximo 20 minutos, então o relay assina um novo a cada entrega.
- Um `409` significa que a Apple recusou a mudança como conflito, muitas vezes porque o endereço já é testador. O relay trata isso como concluído, então se um testador nunca receber convite, confira o grupo no App Store Connect. Qualquer outra falha responde `502`, para o Ikiform tentar a entrega de novo.
- O TestFlight permite até 10.000 testadores externos por app. O primeiro build que você dá a um grupo externo passa pelo Beta App Review, e cada build expira depois de 90 dias.

Adicione a URL do relay em **Webhooks** no Ikiform e copie o segredo `whsec_` para `IKIFORM_WEBHOOK_SECRET`. Um workspace pode ter 3 endpoints, então isto pode rodar ao lado de um relay que alimenta a sua ferramenta de e-mail.

### Android: preencha um teste fechado

A API de publicação do Google Play gerencia os testadores de testes fechados por Google Groups, não por endereços avulsos, então este lado é uma exportação semanal. Exporte a lista com **Export CSV**, filtre numa planilha por `platform` = `android` e `beta` = `true` e adicione os e-mails à lista de e-mails do teste fechado em **Test and release** › **Testing** › **Closed testing** › **Manage track** › **Testers** no Play Console. Depois envie a essas pessoas o link de inscrição do teste pela sua ferramenta de e-mail.

Se você está cumprindo o requisito de 12 testadores, convide mais de 12. Quem sai ou nunca se inscreve não conta, e os 14 dias exigem 12 testadores inscritos o tempo todo.

> O Ikiform não envia e-mail para quem preenche o formulário. Os e-mails de notificação vão só para você e sua equipe, então não há resposta automática, e-mail de confirmação nem double opt-in. Envie esses e-mails pela sua ferramenta de e-mail, disparados por um [webhook](https://ikiform.com/pt-br/docs/webhooks.md). O TestFlight manda o próprio convite, então os testadores de iPhone recebem notícias da Apple. Os testadores de Android só recebem notícias suas.

## Dia do lançamento

Exporte a lista inteira e divida por `platform`. Mande a cada metade um e-mail com um único link de loja. Quem escolheu iPhone não precisa do link do Play, e um único e-mail com dois selos perde toques numa tela pequena. Se você coletou `device`, confira seus relatórios de crash com os modelos que as pessoas listaram antes de enviar.

## Confira se funciona

1. Em **Allowed domains** do formulário, adicione o domínio do seu site, mais `localhost` enquanto desenvolve. Deixe vazio para aceitar envios de qualquer lugar.
2. Abra a página num celular. A plataforma certa vem pré-selecionada, e no Android aparece a dica da conta Google.
3. Envie como testador de iPhone. O envio mostra `platform` como `iphone` e `beta` como `true`.
4. Abra o endpoint do relay em **Webhooks**. A entrega mostra `succeeded`, e o endereço aparece no seu grupo do TestFlight.
5. Envie como testador de Android, exporte o CSV e confirme que a linha aparece ao filtrar com `platform` definido como `android`.
6. Envie com o honeypot preenchido, `_gotcha=bot`. Ele ainda recebe uma resposta de sucesso, mas o envio é armazenado como spam e não dispara e-mail nem webhook.

## Pegadinhas

| Problema | O que fazer |
| --- | --- |
| As entregas do relay falham com `502` e a Apple respondeu `401` | O token está errado: confira o key id, o issuer id e se a chave privada manteve as quebras de linha na variável de ambiente. |
| Um testador foi adicionado, mas não recebeu e-mail do TestFlight | O grupo ainda não tem build, ou o primeiro build ainda está no Beta App Review. Os convites saem quando um build fica disponível para o grupo. |
| Um testador de Android não consegue abrir o link de inscrição | O endereço na lista não é a conta Google conectada no celular. Peça para a pessoa se inscrever de novo com essa conta. |
| `422 validation_failed` | O envio não corresponde à definição de campos do formulário. `error.fields` aponta cada campo e o motivo. Faça o `name` do input bater com o id do campo. |
| O envio está no painel, mas nenhum e-mail ou webhook chegou | Ele foi armazenado como spam. Spam não envia nada. Abra-o no filtro **Spam** para ver os motivos e marque-o como não spam para enviar o e-mail e os webhooks dele. |

## Perguntas

### Preciso de uma lista de espera se a App Store tem pré-venda?

Elas fazem trabalhos diferentes. A pré-venda e o pré-registro do Play precisam de uma página aprovada na loja e dão uma contagem, não contatos. Uma lista de espera funciona desde o primeiro dia, dá o e-mail e a plataforma de cada pessoa e permite convidar testadores.

### Como encontro 12 testadores para o requisito de teste fechado do Google Play?

Peça na sua lista de espera. Um checkbox de beta e uma pergunta sobre a plataforma mostram quem tem um celular Android e quer testar. Coloque as contas Google dessas pessoas na lista de e-mails do teste fechado e mande o link de inscrição.

### O Ikiform consegue adicionar testadores ao TestFlight automaticamente?

Não diretamente. O Ikiform envia um webhook assinado para cada inscrição, e um relay curto que você publica adiciona o endereço a um grupo do TestFlight pela API do App Store Connect, como mostrado acima.

### O Ikiform pode enviar e-mail para quem preencheu o formulário?

Não. O Ikiform envia e-mail para você e sua equipe, não para quem enviou, então não há resposta automática nem e-mail de confirmação. Envie um webhook para sua ferramenta de e-mail e mande a confirmação de lá.

### O Ikiform é gratuito?

Não, não há plano gratuito. Testar é grátis: você pode enviar 50 envios de teste por mês a partir de localhost antes de pagar. Para entrar no ar, o Pro começa em US$ 6/mês para 500 envios, ou você pode pagar uma vez 10.000 envios por US$ 49 ou 50.000 envios por US$ 149, com créditos que nunca expiram.

## Mais guias

- [Lista de espera para um novo SaaS](https://ikiform.com/pt-br/guides/waitlist.md): Monte uma lista de espera pré-lançamento na sua própria landing page: o formulário, proteção contra spam, duplicados, e-mails de confirmação e uma exportação limpa no dia do lançamento.
- [Inscrição para beta com triagem](https://ikiform.com/pt-br/guides/waitlist/beta-signup.md): Um formulário de candidatura ao beta com perguntas de triagem que o servidor exige, e um script que pontua os candidatos e escolhe cada turma da lista.
- [Lista para lançamento no Product Hunt](https://ikiform.com/pt-br/guides/waitlist/product-hunt.md): Colete uma lista semanas antes do Product Hunt, marque cada inscrição pelo canal e envie o e-mail do dia do lançamento em duas ondas, no ritmo da virada do horário do Pacífico.
- [Lista de espera em HTML puro](https://ikiform.com/pt-br/guides/waitlist/html.md): Uma página de lista de espera completa em HTML puro, sem build, que funciona com o JavaScript desligado, mostra um agradecimento na própria página quando carrega e tem plano B quando precisa.
- [Lista de espera com Next.js](https://ikiform.com/pt-br/guides/waitlist/nextjs.md): Uma lista de espera no App Router do Next.js: uma server action que encaminha as inscrições com chave secreta, useActionState, agradecimento otimista e limite por visitante.
- [Lista de espera no Framer](https://ikiform.com/pt-br/guides/waitlist/framer.md): Duas formas de coletar inscrições na lista de espera no Framer: o formulário do Framer com webhook para o Ikiform, ou um code component que mantém os limites por visitante e as verificações de spam.
