Use your own HTML form
A plain form that posts to Waitlark works without JavaScript and lets you style everything yourself.
Prefer full control over the markup? Post a normal HTML form to Waitlark:
<form method="post" action="https://api.waitlark.com/v1/p/pk_yourproject/join">
<label for="email">Email address</label>
<input id="email" name="email" type="email" required>
<input type="hidden" name="lang" value="en">
<input type="hidden" name="placement" value="footer">
<div class="cf-turnstile" data-sitekey="YOUR-SITEKEY"></div>
<button>Join the waitlist</button>
</form>
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
After the post, Waitlark sends the visitor back to a page on your site with a 303 redirect. This works with JavaScript turned off.
Fields Waitlark reads
| Field | Meaning |
|---|---|
email | Required. |
lang | Language of the visitor, for the emails and pages they get. |
placement | Which form on the page, for example hero or footer. |
source | The page path, for example /pricing. |
referrer | The site the visitor came from. Waitlark stores only its name. |
utm_source, utm_medium, utm_campaign | Campaign tags from the link. |
cf-turnstile-response | The bot check. Added by Turnstile itself. |
website | Optional honeypot. Hide it from people; if a bot fills it in, nothing is stored. |
| your question keys | Answers to your signup questions, by key. |
Where visitors land
You set these pages per language on the project:
joined: after a successful signup.error: after a problem. The reason is added as?error=<code>, see Error codes.error_<code>: optional, a page for one specific problem, for exampleerror_invalid_email.confirmed: optional, after someone confirms their address.
Each page must be an https:// address. Without a joined page, Waitlark shows its own thank-you page in your project's colours.
A second signup with the same address lands on the same joined page as a new one. That way nobody can find out who is already on your list.
Updated 19 October 2026