# Cómo añadir un formulario de lista de espera a un sitio de Webflow

> Apunta un Form Block de Webflow a Ikiform, etiqueta los registros por origen con un campo oculto y conserva el estado de éxito de Webflow con un script breve para todos los formularios.

Publicado el 2026-10-25 · https://ikiform.com/es/guides/waitlist/webflow

Conserva el Form Block que diseñaste en Webflow y cambia su action por tu endpoint de Ikiform con el método POST. Añade un input oculto `ref` y un honeypot en un Code Embed, y luego pega un script para todo el sitio que envía cada formulario de lista de espera con `fetch`, rellena `ref` desde el enlace y muestra el bloque de éxito propio de Webflow con el email de la persona.

Webflow es muy bueno con la página y correcto con el formulario. Su gestión nativa de formularios guarda los envíos y te avisa por email, pero limita cuántos conserva según el plan del sitio y no puede etiquetar un registro con la campaña de la que vino. Una action personalizada resuelve ambas cosas sin salir del Designer.

## Qué cambia en Webflow

- **Una action personalizada le quita el formulario a Webflow.** El navegador envía directamente a Ikiform, así que Webflow nunca ve el registro: no está en los envíos de formularios de Webflow, Webflow no envía ningún email y no consume nada del cupo de formularios de tu plan.
- **Los bloques de éxito y de error de Webflow dejan de funcionar.** Solo aparecen cuando Webflow gestionó el envío. Sin un script, los visitantes llegan a la página de agradecimiento de Ikiform o a tu URL de **Redirect after submit**.
- **No hay elemento de input oculto.** Los campos ocultos y el honeypot van en un **Code Embed** dentro del formulario, que necesita un plan de sitio de pago, igual que el código personalizado.
- **En el Designer no se ejecuta nada.** Las actions personalizadas y los scripts solo funcionan en el sitio publicado, así que prueba en tu dominio de staging `webflow.io`.

Diagrama: Un formulario de lista de espera de Webflow antes y después de una action personalizada

1. Por defecto, el Form Block envía a Webflow, que guarda el registro contra el cupo de tu plan y muestra el bloque de éxito.
2. Con una action personalizada, el mismo Form Block apunta a Ikiform.
3. El script detiene el envío normal, rellena el campo ref desde el enlace y envía con fetch.
4. Ikiform guarda el registro, te avisa por email y envía webhooks, y luego responde 201.
5. El script oculta el formulario y muestra el bloque de éxito de Webflow con el email de la persona.

El diseño se queda en Webflow. Solo cambia adónde van los datos.

## Configura el Form Block

1. Selecciona el formulario y abre **Settings**. Quita **Webflow** y **Email notifications** en **Send to**, añade **Custom action**, introduce `https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx`, elige **POST** y guarda.
2. Selecciona el input del email y pon `email` en su **Name**. Webflow rellena los nombres a partir de las etiquetas, así que si no obtendrías `Email` o `Email 2`, que Ikiform trata como un campo distinto.
3. Borra cualquier elemento reCAPTCHA. Ikiform no lo verifica, y con una definición de campos su valor `g-recaptcha-response` se rechaza como campo desconocido.
4. Arrastra un **Code Embed** dentro del formulario, junto al botón, y pega los dos inputs de abajo.
5. Configura **Redirect after submit** en los ajustes del formulario de Ikiform con una página de agradecimiento que hayas publicado en Webflow. Ahí llega la gente si el script no se ejecuta.

`Code Embed dentro del formulario`:

```html
<input type="hidden" name="ref" value="webflow">
<input name="_gotcha" type="text" tabindex="-1" autocomplete="off" hidden>
```

Añade la definición de campos en la pestaña **Fields** de Ikiform con `email` obligatorio y `ref` como campo `text` opcional con `max_length` 40. Cualquier otro nombre enviado, como un input `Name` que se quedó, recibe entonces un `422`, lo que te descubre un input mal etiquetado en la primera prueba.

## El script para todo el sitio

Pega esto en **Site settings** › **Custom code** › **Footer code**, para que cubra el formulario del hero, el del footer y cualquier página que añadas después. Solo toca los formularios cuya action empieza por `https://ikiform.com/f/`.

`Código del footer`:

```html
<script>
  const params = new URLSearchParams(location.search);
  const ref = (params.get("ref") || params.get("utm_source") || "").toLowerCase().replace(/[^a-z0-9_-]/g, "").slice(0, 40);
  const key = crypto.randomUUID();

  document.querySelectorAll('form[action^="https://ikiform.com/f/"]').forEach((form, index) => {
    const wrapper = form.closest(".w-form");
    const done = wrapper?.querySelector(".w-form-done");
    const fail = wrapper?.querySelector(".w-form-fail");
    const button = form.querySelector('[type="submit"]');
    const source = form.querySelector('[name="ref"]');
    if (source && ref) source.value = ref;

    form.addEventListener("submit", async (event) => {
      event.preventDefault();
      const label = button.value;
      button.disabled = true;
      button.value = button.dataset.wait || "Joining";
      fail.style.display = "none";
      try {
        const response = await fetch(form.action, {
          method: "POST",
          headers: { Accept: "application/json", "Idempotency-Key": `${key}-${index}` },
          body: new FormData(form),
        });
        const result = await response.json();
        if (result.ok) {
          const email = form.querySelector('[name="email"]').value;
          const line = done.querySelector("div") ?? done;
          line.textContent = `You're on the list. We'll write to ${email} on launch day.`;
          form.style.display = "none";
          done.style.display = "block";
          return;
        }
        const wait = response.headers.get("Retry-After");
        const message = wait ? `Lots of signups right now. Try again in ${wait} seconds.` : result.error.fields?.email?.[0] ?? result.error.message;
        (fail.querySelector("div") ?? fail).textContent = message;
      } catch {
        (fail.querySelector("div") ?? fail).textContent = "Couldn't reach the server. Try again.";
      }
      fail.style.display = "block";
      button.disabled = false;
      button.value = label;
    });
  });
</script>
```

- `?ref=` o `?utm_source=` en el enlace rellena todos los inputs ocultos `ref` de la página. Sin ninguno de los dos, se conserva el valor puesto en el embed, así que ponlo por formulario, como `hero` y `footer`, para ver cuál convierte.
- La clave de idempotencia se crea una vez por carga de página y lleva un sufijo por formulario. Un doble clic guarda un solo registro; un segundo registro desde otro formulario de la página sigue contando.
- El bloque de éxito de Webflow recibe una línea con el email de la persona, lo que detecta erratas: la gente nota `gmial.com` cuando se lo devuelven escrito.
- El botón muestra el texto de **Loading** que configuraste en el Designer mientras el envío está en curso.
- Un `429` muestra cuánto esperar, a partir de la cabecera `Retry-After` de Ikiform, en lugar de un fallo genérico.

> El script envía con `fetch`, así que deja desactivada la verificación antispam del formulario. Con la verificación activa, Ikiform responde `403 challenge_required` y aparece el bloque de error. Si necesitas la verificación, prescinde del script; el envío normal la ejecuta sin código.

### Dominios permitidos

| Dónde se ejecuta el formulario | Añadir a Allowed domains |
| --- | --- |
| Staging | `your-site.webflow.io` |
| Tu dominio personalizado | `example.com`, que cubre `www.example.com` |
| El Designer | Nada. Nunca envía desde ahí |

Nunca añadas `webflow.io` solo; coincidiría con todos los sitios de Webflow. La [guía de Webflow de la documentación](https://ikiform.com/es/docs/guides/webflow.md) cubre los mismos ajustes para un formulario de contacto, y la [guía principal](https://ikiform.com/es/guides/waitlist.md#confirm) muestra cómo reenviar los registros a tu herramienta de email.

## Comprueba que funciona

1. Publica en tu dominio de staging `webflow.io`.
2. En **Allowed domains** del formulario, añade el dominio de tu sitio, y `localhost` mientras desarrollas. Déjalo vacío para aceptar envíos desde cualquier sitio.
3. Abre la página con `?ref=test` y regístrate. El bloque de éxito de Webflow muestra tu email, y el envío en Ikiform tiene `ref` en `test`.
4. Regístrate otra vez desde el formulario del footer sin query string. `ref` toma el valor del embed de ese formulario.
5. Desactiva JavaScript y envía. Llegas a tu página de agradecimiento de Webflow.
6. Revisa la bandeja de entrada de cada destinatario de las notificaciones. Cada uno recibe un email con los campos, y **Reply** responde a quien envió el formulario cuando este tiene un campo `email`.
7. Envía con el honeypot relleno, `_gotcha=bot`. Sigue recibiendo una respuesta de éxito, pero el envío se guarda como spam y no manda email ni webhook.

## Problemas habituales

| Problema | Qué hacer |
| --- | --- |
| `404 not_found` después de enviar | **Method** está en GET, así que el navegador abrió el endpoint como un enlace. Ponlo en POST y vuelve a publicar. |
| `422` con Unknown field `Email` o `g-recaptcha-response` | El **Name** de un input no coincide con la definición, o queda un elemento reCAPTCHA en el formulario. Cambia el nombre del input a `email` o quita el elemento. |
| El script no hace nada | Estás en el Designer, el sitio no tiene plan de pago o **Action** tiene un espacio. Prueba en el sitio publicado. |
| `403 challenge_required` | La verificación antispam del formulario está en **Ikiform** y un envío con `fetch` no llevaba token. Consigue uno con `challenge(formId)` de `@ikiform/sdk` antes de cada envío, o desactiva la verificación. |
| `403 origin_not_allowed`, o todos los envíos acaban en spam | El dominio de la página no está en los **Allowed domains** del formulario. Añádelo, y también `localhost` para las pruebas locales. Los subdominios de un dominio de la lista están permitidos. |

## Preguntas

### ¿Los registros de lista de espera enviados a Ikiform cuentan para el límite de envíos de formularios de Webflow?

No. Con una action personalizada el navegador envía directamente a Ikiform, así que Webflow nunca recibe el envío. No aparece en los envíos de formularios de Webflow y no consume el cupo de tu plan.

### ¿Cómo añado un campo oculto a un formulario de Webflow?

Webflow no tiene un elemento de input oculto. Pon un Code Embed dentro del formulario con un input de tipo hidden. Code Embed necesita un plan Site de pago o un Workspace Core, Growth, Agency o Freelancer.

### ¿Puedo conservar el mensaje de éxito de Webflow con una action personalizada?

Sí, con un script. Webflow solo muestra su bloque de éxito cuando gestionó el envío, así que el script envía con fetch y muestra el bloque él mismo, como en el ejemplo de arriba.

### ¿Puede Ikiform enviar un email a la persona que envió el formulario?

No. Ikiform te envía emails a ti y a tu equipo, no a quien envía el formulario, así que no hay respuesta automática ni email de confirmación. Envía un webhook a tu herramienta de email y manda la confirmación desde allí.

## Más guías

- [Lista de espera para un nuevo SaaS](https://ikiform.com/es/guides/waitlist.md): Crea una lista de espera previa al lanzamiento en tu propia landing page: el formulario, el antispam, los duplicados, los emails de confirmación y una exportación limpia el día del lanzamiento.
- [Lista de espera en Framer](https://ikiform.com/es/guides/waitlist/framer.md): Dos formas de recoger registros de lista de espera en Framer: el formulario de Framer con un webhook a Ikiform, o un code component que conserva los límites por visitante y el antispam.
- [Lista de espera en Carrd](https://ikiform.com/es/guides/waitlist/carrd.md): Recoge registros de lista de espera en una página de Carrd: un formulario Send to URL en Pro Plus con seguimiento UTM, o un formulario HTML incrustado con honeypot en Pro Standard.
- [Lista de espera en HTML puro](https://ikiform.com/es/guides/waitlist/html.md): Una página de lista de espera completa en HTML puro y sin build que funciona con JavaScript desactivado, muestra un agradecimiento en línea cuando carga y recurre a un plan B cuando hace falta.
- [Lista para lanzar en Product Hunt](https://ikiform.com/es/guides/waitlist/product-hunt.md): Reúne una lista semanas antes de Product Hunt, etiqueta cada registro por canal y envía el email del lanzamiento en dos tandas según el reinicio en hora del Pacífico.
- [Registro a una beta con filtro](https://ikiform.com/es/guides/waitlist/beta-signup.md): Un formulario de solicitud para una beta con preguntas de filtro que aplica el servidor, y un script que puntúa a los candidatos y elige cada grupo de la lista.
