Skip to article
How-to guides

How to Add a Waitlist Form to Your Website (No-Code, Any Platform)

TL;DR: Adding a waitlist form to your website takes two lines of code you can paste anywhere: one <script> in your page's head, one <div> where you want the form. That's it, on any platform: Webflow, WordPress, Squarespace, Framer, Carrd, Shopify, or plain HTML. The important part isn't the paste. It's making sure the form has a referral loop, position tracking, and a proper success page, which a native contact form can't do. This guide covers the universal embed with LaunchList (free for 100 contacts), every other way to place the form (popup with exit-intent, time or scroll triggers, your own form markup, React, no-JavaScript, the REST API), per-platform setup, styling, any-identity fields, spam protection, webhooks and the MCP server, and the mistakes that quietly kill signups.

A waitlist form is the single most important element on your pre-launch site: it's the thing that turns a visitor into a lead, and (done right) each lead into more leads. The good news: you don't need a developer, and you don't need to rebuild your site. You need one snippet and the right settings.

The two-minute version

Every no-code waitlist tool works roughly the same way. With LaunchList, pre-launch waitlist software for founders, you sign up free (no card; the Free plan holds 100 contacts), which creates your project and a waitlist form for you. Then open Embed & API → Your website, choose what your site is built with, and copy the Inline snippet. It has two parts:

1. The loader script, once, in your site's <head>:

<script src="https://embed.getlaunchlist.com/v1/embed.js" async></script>

2. The form, wherever you want it to appear:

<!-- frm_8Kd2Qm4Rp9 is an example ID; the copy button inserts your real one -->
<div data-launchlist-form="frm_8Kd2Qm4Rp9"></div>

That renders a live signup form on your page. Every person who submits joins your waitlist and runs the same pipeline: they're deduplicated against your existing contacts, given a trust verdict (real or likely fake), sent a confirmation email if double opt-in is on (it is by default for waitlist forms), and handed a personal referral link and queue position on their own status page. No backend, no database, no code beyond those two lines. The rest of this guide is about doing it well: on your specific platform, styled to your brand, with the growth mechanics tuned.

One snippet, any platform Paste the same embed anywhere. The referral mechanics come with it. YOUR SITE Webflow WordPress Squarespace Framer · Carrd · Shopify Plain HTML ONE EMBED <script src="embed.js"> <div data- launchlist-form> Your waitlist Unique referral link Queue position Referral leaderboard Confirmation email Trust check on every signup

Every way to place the form

The inline snippet above is the default. The same form can also go on your site in any of these ways, and every one runs the same pipeline (dedupe, trust verdict, confirmation email, referral credit) on every plan, Free included:

Method What you add Use it when
Inline <div data-launchlist-form="frm_..."> plus the loader The form sits in a section of your page
Popup on click data-launchlist-popup="frm_..." on any button or link A "Join the waitlist" button in your nav or hero
Popup on exit, time or scroll The popup attribute plus data-trigger="exit", "time" or "scroll" You want to catch visitors who read but didn't join
Enhance your own form data-launchlist-enhance="frm_..." on a <form> you built The form has to match your design system exactly
React, Vue, Svelte LaunchList.mount('#el', { form: 'frm_...' }) Single-page apps that render after load
No JavaScript A plain <form action=".../f/frm_.../submit"> A CMS that strips script tags
REST API POST https://api.getlaunchlist.com/v1/contacts with an API key The signup happens in your own backend or app
MCP The capture_signup tool from Claude, ChatGPT, Cursor or another MCP client An AI agent is adding people to the list for you

Each is covered below. Pick one placement per page; mixing them on one site is fine, because they all feed one deduplicated list.

Why a native form isn't enough

Most website builders ship a form element: Webflow forms, a WordPress contact plugin, Squarespace's form block. They'll capture an email. But a pre-launch waitlist form needs mechanics a generic form doesn't have:

Feature Native site form Dedicated waitlist form
Email capture ✅ ✅
Unique referral link per signup ❌ ✅
Queue position tracking ❌ ✅
Referral leaderboard ❌ ✅
Reward milestones ❌ ✅
Fraud / spam detection ❌ ✅
Email validation ❌ ✅
Confirmation email Limited ✅ Built-in

Without a referral mechanic, your form is a plain email list: you pay for every signup individually and none of them bring a friend. With one, each signup can bring two to five more; it's how Dropbox grew from 100,000 to 4 million users in 15 months. That's the whole reason to embed a purpose-built form instead of using the native one. (For the deeper why, see what is a waitlist landing page? and the referral program guide.)

First decision: embed on your site, or use a hosted page?

There are two no-code paths. Pick based on whether you already have a site:

  • Embed the form on your existing site (this guide's focus). You keep your domain and design; the form renders inside your page. Best if you already have a landing page or brand site.
  • Use a hosted launch page: a standalone URL the tool hosts for you, no site required. On LaunchList every project comes with one, built in a block editor from finished sections (or drafted by AI from a description), at your-slug.launchlist.page or on your own domain from the Collect plan. Best if you don't have a site yet or want the fastest path. If you want a whole page rather than just a form, follow how to create a waitlist landing page.

The trade-offs (SEO, brand trust, iteration speed) are laid out in hosted page vs embedded widget. The rest of this guide covers the embed path, and you can use both: the same form on a hosted page and on your site feeds one list, deduplicated.

Step-by-step: add the waitlist form to any site

Step 1: Create the waitlist and copy your snippet

Sign up free. Your project, a waitlist form and a launch page already exist when you land, so there's nothing to create. Open Embed & API → Your website, choose your platform under What is your site built with?, pick the form if you have more than one, and copy the Inline snippet. The value in data-launchlist-form is your form's public ID. It's safe to publish: it identifies the form but grants no access to your audience.

While you're in the dashboard, glance at Audience → Referrals & rewards. Referrals are already on (every signup gets a link), and that's where you decide what a referral is worth and, from the Collect plan, which rewards people unlock. One setting matters for embeds: under Settings, choose where referral links land. Point them at your own site (rather than the hosted page) and the friends your signups bring arrive on the page with your embedded form. The referral code is stored in their browser for 90 days, along with any UTM parameters, so they still credit the referrer if they browse around and sign up later from a different page.

Step 2: Add the loader to your site's head

Paste this once, globally, so the form can load on every page. It loads asynchronously (async), so it won't hold up your page:

<script src="https://embed.getlaunchlist.com/v1/embed.js" async></script>

Where the "head" lives depends on your platform (next section). If your platform has no head slot, the snippet works with the script sitting right next to the <div>, and a repeated loader is harmless.

Step 3: Place the form

Drop this wherever the form should appear: your hero, a section, a footer.

<div data-launchlist-form="frm_8Kd2Qm4Rp9"></div>

Use the ID from your own snippet. There's no height to set: the form sizes itself to its fields and fills the width of whatever container it sits in, so control the width from your layout.

Step 4: Test it

Turn on Test mode under Project settings → General first, so practice signups stay out of your real list and your contact count. Then open your published page in a private/incognito window, submit a test address, confirm the confirmation email arrives, click your referral link from the status page, and check the position updates. The signup should appear under Audience within a second. Do this on your phone too: most pre-launch traffic (Twitter/X, Reddit, Indie Hackers) is mobile-first. Switch test mode off when you're done.

Platform-specific setup (head + embed)

The two lines are identical everywhere; only where you paste them changes. Here's the short version per platform, with links to the full walkthroughs:

  • Webflow: drag an Embed element where the form goes and paste the snippet; for several forms, put the loader once under Site Settings → Custom Code → Head Code. Prefer the form you designed in Webflow? Add data-launchlist-enhance as a custom attribute on the Form Block and LaunchList takes over submission while your styling stays. Both work on the free Starter plan. Full guide: Webflow waitlist setup.
  • WordPress: no plugin needed. Add a Custom HTML block and paste the snippet, or enqueue the loader once site-wide from your child theme and use just the <div> in each block. If your host strips <script> tags, use the no-JavaScript form below. Full guide: WordPress waitlist setup.
  • Squarespace: add a Code block in HTML mode for the form; for several forms, put the loader in Settings → Advanced → Code Injection → Header. Custom code needs the Business plan or above; on a Personal plan, link a button to your hosted page instead. The editor shows a placeholder, so check the live site. Full guide: add a waitlist to Squarespace.
  • Framer: insert an Embed component, set Type to HTML, paste the snippet, and set its height to Fit Content so the form isn't clipped.
  • Carrd: add an Embed element with Type set to Code (Carrd strips scripts from Text embeds). Works on Carrd's free plan.
  • Shopify: add a Custom Liquid section in the theme editor, including on your coming-soon password page. Don't paste it into a Page's body HTML, which strips the script.
  • React, Next.js, Vue or Svelte: load the script once in your app shell, render an empty element, and call window.LaunchList.mount('#waitlist', { form: 'frm_...' }) after it's in the DOM.

Step-by-step docs for each of these, plus plain HTML, are in every way to add LaunchList to your site. If your platform has any way to add custom HTML (and almost all do), you can add the waitlist form. No plugin marketplace required.

Style the form to match your brand

The form renders inside a shadow root, which isolates it in both directions: your site's CSS can't reach in and break it, and its styles can't leak out into your page. That's what makes it safe to drop onto a site you don't fully control, and it means you don't style it with CSS on your side. Instead, set your colors, font, corner radius and button style once in your Brand settings in LaunchList, and every form and every embed on every site follows. Forms also follow light and dark mode automatically, taking the scheme from the page they sit on.

Width comes from the container: put the <div> in a column as wide as you want the form to be.

If the form has to match your design system pixel for pixel, keep your own form instead and enhance it (see "Keep your own form" below). You keep your markup and CSS; LaunchList handles the behavior.

Collecting more than an email

For the highest conversion, ask for email only; every extra field measurably lowers signups. When you genuinely need more (name, company, use case), add fields under Forms and every embed updates itself, with no markup changes on your side. The builder has short and long text, choices and dropdowns, ratings and NPS, dates, consent and more, with per-field width, conditional logic and multi-step forms. Two features worth knowing:

  • Hidden fields record where a signup came from without asking. A hidden field's key doubles as a URL parameter, so ?invite_batch=wave2 on the link you share lands in that column.
  • Any identity. Email is never required. Choose in the form builder what identifies a signup:
Identity Good for Worth knowing
Email Most launches The only identity that can be verified by a double opt-in click and receive broadcasts
Phone Mobile-first and messaging audiences No SMS sending; contacts start as Unknown in Contact Trust until other checks add evidence
Username Communities, games, Discord or X audiences Starts as Unknown in Contact Trust, like phone
Wallet address Web3 launches and allowlists There's a dedicated wallet field type; ownership isn't proven by signature
A custom field An existing customer ID or invite number Any field you define becomes the key
Anonymous Surveys and polls No identity at all; answers still land in Forms → Answers

Whatever identity you choose, add an optional email field if you'll want to email people later, because broadcasts and the confirmation email need an address. The builder's 20 field types also include phone, URL, number, date and time, select, multi-select, radio, checkbox, yes/no and consent, plus heading and divider for layout, all on every plan.

If you need richer answers, ask them after signup with a survey on the status page rather than adding them to the form.

Track signups in your analytics

LaunchList's own analytics counts every signup, whichever channel it came through, and shows how many came through referrals and how many confirmed, each compared with the period before. The loader also captures the UTM parameters and referral code a visitor arrived with and stores them with the signup, so you can see which campaigns and links produced it. To send the conversion to GA4 or another tool, you have two options:

  • A thank-you page you control. In the form's success settings, choose Your own URL instead of the status page, and fire your analytics conversion on that page. UTM parameters pass through, so attribution survives. The trade-off: signups land on your page instead of their status page, so put the referral link there or link to it.
  • A webhook. Add a webhook endpoint under Embed & API → Developers → Webhooks and subscribe to signup.created (or contact.verified, if you only want to count confirmed signups). Payloads are signed and retried, and you can forward them to your analytics or CRM server-side, or to Zapier, Make or n8n.

Advanced: keep your own form, or skip JavaScript

The inline embed suits most sites. Three other ways to place the same form, all running the same pipeline:

Keep your own form. If you need total control of the markup, add one attribute to a form you already built. LaunchList takes over submission, live format validation, a one-tap fix for email domain typos, inline error messages, referral attribution and success routing. Match each input's name to the field key shown in the form builder (for a simple waitlist, email), and keep the loader in your head:

<form data-launchlist-enhance="frm_8Kd2Qm4Rp9">
  <input type="email" name="email" placeholder="you@example.com" required>
  <button type="submit">Join the waitlist</button>
</form>

No JavaScript at all. For a CMS that strips scripts, a plain HTML form can post straight to the capture endpoint, and the server redirects to the status page or your own URL. Copy the exact action from Embed & API → Your website rather than typing it:

<form action="https://embed.getlaunchlist.com/f/frm_8Kd2Qm4Rp9/submit" method="POST">
  <input type="email" name="email" required>
  <input type="hidden" name="_channel" value="html">
  <button type="submit">Join the waitlist</button>
</form>

Two catches: on its own, a native form can't read the ?ref= in the URL, so add the loader anywhere on the site if you can (it finds the form and injects the referral code without taking it over); and set the form's success behavior to the status page or your own URL, because an inline message has nowhere to redirect to.

From your server. If the signup happens in your backend, post it to the REST API instead (example below). One call returns the referral code, the live queue position and the trust verdict.

This is the "advanced" path. Most people never need it; the inline embed already handles styling, custom fields and referrals.

Open the form in a popup, on click or automatically

A popup needs no extra script: the loader that renders inline forms also handles popups. On click, put the attribute on any button you already have:

<button data-launchlist-popup="frm_8Kd2Qm4Rp9">Join the waitlist</button>

<!-- side panel instead of a centered modal -->
<a href="#" data-launchlist-popup="frm_8Kd2Qm4Rp9" data-variant="slideover">Get early access</a>

To open it without a click, add data-trigger to an element carrying the popup attribute. The dashboard's snippet generator only writes click buttons, so these are attributes you add by hand:

<!-- exit intent: desktop pointer leaves through the top of the window -->
<div data-launchlist-popup="frm_8Kd2Qm4Rp9" data-trigger="exit"></div>

<!-- 10 seconds after the page loads (default 5) -->
<div data-launchlist-popup="frm_8Kd2Qm4Rp9" data-trigger="time" data-delay="10"></div>

<!-- after 60% of the page has been scrolled (default 50), at most once every 14 days -->
<div data-launchlist-popup="frm_8Kd2Qm4Rp9" data-trigger="scroll" data-scroll="60" data-cap="14"></div>

Each visitor sees an automatic popup at most once per cap window (7 days by default), and never again once they've signed up. Exit intent has no touch equivalent, so on mobile pair it with a time or scroll trigger. For your own logic, LaunchList.popup('frm_8Kd2Qm4Rp9').open() opens the same popup from code.

Add social proof beside the form

The same loader renders social-proof widgets, on every plan. Save one under Embed & API → Your website → Widgets and paste its element next to the form:

<div data-launchlist-widget="counter" data-project="acme" data-label="founders already in"></div>

The kinds: a live signup counter, the referral leaderboard, a milestone ladder showing the rewards people can reach, a countdown to your launch date, and a "What's new" feed of your published updates. They never show personal data: people on the leaderboard appear as masked monograms. Leave the counter off until the number helps you.

What happens to every signup: Contact Trust and spam protection

An embed on a public site will attract bots and people gaming the referral queue. LaunchList checks every submission before it counts, on every plan:

  • At the door: rate limits per form, per IP and globally; a honeypot field and a two-second time trap; a disposable-domain list plus an MX lookup; IP reputation and device fingerprint reuse. Each submission is scored into allow, hold or block. Strictness is Off, Relaxed, Balanced or Strict under Project settings → Privacy & spam, where you can also turn on Turnstile, reCAPTCHA or hCaptcha with your own keys (off by default).
  • One verdict per contact: Verified (proved they own the address), Valid (passive checks pass), Unknown (not enough evidence yet), Risky (held for review) or Fake (a hard failure confirmed by a second, independent signal). You can filter and sort the audience by it, and override any verdict.
  • Held, not deleted: suspicious signups are stored but kept out of your audience, leaderboard and bill until you approve or block them.
  • Referral credit that holds up: a referral only counts once the friend verifies, after self-referral, per-IP (3 by default) and velocity (20 an hour by default) checks, and the credit is taken back if the friend later turns out to be fake, for example when three or more signups are found sharing one device.

Connect the form to the rest of your stack: webhooks, API and MCP

Webhooks. Under Embed & API → Developers → Webhooks, add an HTTPS endpoint and subscribe to any of 27 events (or * for all): signup.created, contact.verified, referral.made, reward.granted, invite.redeemed, survey.completed and more. Deliveries are retried 7 times over about two and a half days, logged for 90 days, and can be replayed or sent as a test. The Free plan includes one endpoint; paid plans are unlimited. There are no native Zapier, Make or Slack apps for this yet, so point a "Webhooks by Zapier" catch hook, a Make or n8n webhook, or a Slack incoming webhook at it. Every request is signed; verify it before you trust it:

// Header: LaunchList-Signature: t=1754039051,v1=5f8d2c...
import crypto from "node:crypto";

function verify(rawBody, header, secret) {
  let t = 0;
  const signatures = [];
  for (const part of header.split(",")) {
    const [key, value] = part.trim().split("=");
    if (key === "t") t = Number(value);
    if (key === "v1") signatures.push(value); // two during a secret rotation
  }
  if (!t || Math.abs(Date.now() / 1000 - t) > 300) return false; // 5-minute tolerance
  const key = secret.replace("whsec_", ""); // the prefix is not part of the key
  const expected = crypto.createHmac("sha256", key).update(`${t}.${rawBody}`).digest("hex");
  return signatures.includes(expected);
}

REST API. If the signup happens in your own backend, create the contact directly. Keys start with llk_ and are created under Embed & API → Developers → API keys with only the scopes you need. One call runs the full pipeline and returns the referral code, live position and trust verdict; the Idempotency-Key makes retries safe:

curl https://api.getlaunchlist.com/v1/contacts \
  -H "Authorization: Bearer $LAUNCHLIST_KEY" \
  -H "Idempotency-Key: signup_8f3a2b" \
  -H "Content-Type: application/json" \
  -d '{"project": "prj_7Qk2mN4pR8", "email": "ada@example.com", "referred_by": "SARAH42"}'

The API has 53 operations (contacts, tags, segments, invitations, imports, broadcasts, automations, projects, forms) described by a public OpenAPI 3.1 spec at api.getlaunchlist.com/v1/openapi.json, on every plan, at 60 requests a minute on Free and up to 1,000 on the Grow plan.

MCP server. Connect Claude, ChatGPT, Cursor, VS Code, Windsurf or another MCP client under Embed & API → AI assistants, with OAuth (you approve one workspace on a consent screen) or a scoped API key. The server exposes 35 tools, including capture_signup (the same pipeline as the form), search_audience, get_contact (with live position) and get_audience_stats. Agents can't delete contacts or mint keys, every action is logged, and you can revoke an agent under Account → Security → Authorized agents.

Best practices for a waitlist form that converts

The form works in two minutes. Making it convert comes down to a few rules:

  1. Email only, above the fold. One field, one button, no scrolling to find it.
  2. A button that says what happens. "Join the waitlist" beats "Submit."
  3. Make the referral loop worth something. Referrals are on from the first signup; decide what a referral earns and add a reward ladder. This is the difference between a list that grows itself and one that doesn't. See milestones & rewards.
  4. Show a real success state. After signup, show queue position + share link, not a generic "thanks." That's the viral moment, and it's what the status page does by default.
  5. Send a good confirmation email. Plain, human, and repeat the share link. Templates in waitlist email templates that get opened.
  6. Don't fake social proof. "Join 40 early users" beats an invented "10,000+." A live counter widget beside the form (one more <div>) shows your real total once it's worth showing.

If your form is live but signups are flat, work through why is my waitlist not converting?. The fix is almost always the headline or the CTA, not the form itself.

Frequently asked questions

How do I add a waitlist form to my website for free?

Create a free waitlist with a tool like LaunchList (free for your first 100 contacts, no card), copy the two-line embed from Embed & API → Your website (one <script> in your site's head, one <div> where the form should go) and publish. No code beyond pasting those lines, and it works on any platform that allows custom HTML.

Can I add a waitlist form without any coding?

Yes. Pasting an embed snippet into a custom-code or HTML block isn't coding, and every major website builder (Webflow, WordPress, Squarespace, Framer, Carrd, Shopify) has a slot for it. If you'd rather not touch your site at all, use a hosted launch page instead: a standalone URL with no site required.

What's the difference between a waitlist form and a regular contact form?

A contact form just stores an email. A waitlist form adds the growth mechanics: a unique referral link per signup, queue position, a leaderboard, reward milestones, and spam and fake-signup checks. Those mechanics are what let a waitlist grow through referrals instead of paid traffic alone.

Will the waitlist form slow down my site?

Not meaningfully. The loader is small and loads asynchronously (async), so it doesn't block your page from rendering, and the form renders in a shadow root so it can't fight your CSS. Always verify on your specific template with a tool like PageSpeed Insights.

Can I put the waitlist form in a popup or modal?

Yes, without building a modal yourself. Add data-launchlist-popup="frm_..." to any button and clicking it opens the form in an overlay; add data-variant="slideover" for a side panel instead. To open it automatically, add data-trigger="exit", "time" or "scroll"; each visitor sees it at most once a week by default and never after signing up. For custom logic, call LaunchList.popup('frm_...').open().

How do I add the form to more than one page?

Load the script once site-wide (in the head), then add the <div> on any page where you want the form. The same waitlist collects signups from every placement, and someone who signs up twice is one contact, not two. Referral links work from any page too: the code is stored when a visitor arrives, so they can browse around and sign up later.

Can people join my waitlist without an email address?

Yes. A LaunchList form can identify signups by phone number, username, wallet address or a custom field, or run anonymously, on every plan. Add an optional email field if you want to email them later, since broadcasts need an address.

How do I send waitlist signups to Slack, Zapier or my CRM?

Use a webhook. LaunchList signs every webhook with HMAC-SHA256, covers 27 event types such as signup.created, and retries 7 times over about two and a half days; point it at a Slack incoming webhook, Zapier, Make, n8n or your own server. There are no native Slack or Zapier apps yet.


Add your waitlist form today

Two lines, any platform, live in minutes, with referral links, queue positions, a leaderboard, a trust verdict on every signup, and confirmation email included. LaunchList is free for your first 100 contacts with no card, and paid plans start at $9 a month on the Collect plan, which adds rewards, your own domain and email campaigns.

Start free → or see pricing. Rather not embed? Every project also comes with a hosted launch page.

Related reading:

Keep reading

Start building your product waitlist.

Create your page, collect your first signups, and grow from there.

No credit card needed