QueueUp / docs

Install the widget

Drop the embed widget on any HTML page in under a minute.

The embed widget is a single web component, <queueup-form>. Include the script once, drop the tag wherever you want a sign-up form, and you’re done.

Quickest install (Web Component)

  1. Open your waitlist’s setup page in the dashboard.
  2. Scroll to Embed, pick the Web Component tab.
  3. Click Copy to grab the snippet.
  4. Paste it into your page.

The copied snippet looks roughly like this:

<link rel="modulepreload" href="https://cdn.getqueueup.com/sdk/v1/widget.js" fetchpriority="high">
<script type="module" src="https://cdn.getqueueup.com/sdk/v1/widget.js" fetchpriority="high"></script>

<queueup-form
  waitlist-id="wl_abc123"
  theme='{"brand_color":"#f97316","text_color":"#000000","border_radius":6,"layout":"stacked","button_label":"Join waitlist","placeholder":"[email protected]"}'
  style="display:block;min-height:96px"
></queueup-form>

The script tag can live anywhere in the document. <head> is fine, end of <body> is fine. type="module" makes the script non-blocking and deferred by default, so it never holds back your page from rendering. Three things make the form feel native:

  • The <link rel="modulepreload"> hint starts the bundle download in parallel with HTML parsing, so the script is already cached by the time the parser reaches the tag.
  • fetchpriority="high" raises the download priority so the bundle isn’t queued behind images and other late-discovery resources.
  • The inline min-height reserves the form’s vertical footprint, so the page doesn’t shift when the widget upgrades. Use 64px for layout: "inline" and 96px for layout: "stacked".

The submit logic loads on demand the first time someone submits the form, keeping the initial download small. The widget warms that chunk in the background after mount, so the click itself feels instant. You can add the <queueup-form> tag in as many places as you want; one waitlist can have many embeds on the same page.

Attributes

AttributeRequiredDescription
waitlist-idyesThe ID of the waitlist (wl_...). Visible at the top of the setup page.
themenoInline JSON of theme tokens. Drop or set to "none" to render with system defaults. See Customize for the token reference.
layoutno"stacked" or "inline". Overrides the layout token inside theme. Useful when you want to keep one saved theme but render the form differently in different spots.
modenoSet to "headless" to skip the default stylesheet. See Customize → Headless mode.
prefill-emailnoPre-fills the email input. Handy when your page already knows who the visitor is (e.g. a logged-in dashboard). The user can still edit before submitting.
referral-codenoExplicit 6-character referral code. Overrides any ?queueup_ref= value picked up from the page URL.
auto-refnoSet to "off" to opt out of reading ?queueup_ref= from window.location. Defaults to on.
success-redirectnoSet to "status" to navigate to the hosted status page after a successful signup. See Referrals.
api-basenoOverride the API origin the widget talks to. Defaults to the QueueUp public API. Set only if you are self-hosting or pointing the widget at a staging environment.

The widget reads ?queueup_ref= from the page URL on every mount and forwards a valid 6-character code with the signup. The query key is namespaced so it does not collide with your own ?ref= tracking. Invalid codes (wrong length, lowercase, non-alphanumeric) are dropped silently. See Referrals for the full flow.

Choosing an integration mode

The dashboard offers three snippets. Pick based on how much control you need:

ModeWhen to use
Web Component (default)The simplest install. Drop one tag and walk away.
SDK ClientWhen you need programmatic control: submitting from your own form, listening for events, batching submissions. The dashboard auto-selects this if Proof of Work or Challenge is enabled.
Simple HTML + FetchA bare fetch() example for static pages without JavaScript frameworks.

SDK Client

<script src="https://cdn.getqueueup.com/sdk/v1/queueup.iife.js"></script>
<script>
  const client = new QueueUpClient({
    waitlistId: "wl_abc123",
  });

  document.querySelector("#queueup-form").addEventListener("submit", async (e) => {
    e.preventDefault();
    const email = e.target.elements.email.value;
    await client.subscribe(email);
  });
</script>

The client handles the abuse pipeline transparently. It receives a 428 response for Proof of Work or Challenge, solves it, and retries before resolving the promise.

Simple HTML + Fetch

<form id="queueup-form">
  <input name="email" type="email" required />
  <button>Join</button>
</form>

<script>
  document.getElementById("queueup-form").addEventListener("submit", async (e) => {
    e.preventDefault();
    const email = e.target.email.value;
    const res = await fetch(
      "https://api.getqueueup.com/v1/public/waitlists/wl_abc123/subscribers",
      {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ email }),
      }
    );
    if (res.status === 202) alert("Thanks!");
    else alert("Couldn't sign up. Try again.");
  });
</script>

Verifying it works

After installing, submit a test email through the widget. The subscriber appears immediately on the waitlist’s detail page under the Subscribers tab.

If you don’t see it, open your browser’s network tab and look for the POST .../subscribers request:

  • 202 is success. Refresh the dashboard.
  • 404 typically means the request’s Origin header isn’t on the waitlist’s allowlist. Open Setup → Origins and add the missing host. The match is exact (protocol + host + port), so every subdomain you embed on needs its own entry.
  • 400 means the email failed validation.
  • 429 means you’ve hit the per-IP throttle. Wait a minute and retry.

For the full status-code reference, see Subscribe endpoint.

Updates and versioning

The CDN URL for the widget is stable. You paste it once and forget about it.

  • /sdk/v1/widget.js and /sdk/v1/queueup.iife.js are the canonical paths for the v1 widget. They serve the latest v1 build at all times. Bugfixes and backward-compatible improvements roll out silently. Your embedded snippet picks them up on the next page load, with no action from you.
  • The browser caches the widget aggressively, so end-users almost never wait on a network request to load it. New builds propagate within roughly one page-load after deploy.

If your theme changes, you do need to re-copy the snippet to embed the new theme tokens. The dashboard surfaces an Out of date banner to remind you. That’s the only situation where re-copying the snippet matters.

Next: customize

The widget defaults look reasonable, but the real value is matching your brand. Head to Customize for the full theme and CSS reference.