Embeds
Embeds let you put a SupDesk form directly on your own website. Visitors join your waitlist, message you, or sign up for a beta without ever leaving your site.
Looking for a chat bubble instead of a form? Live chat has its own loader (
chat.js) and its own snippet — see Live Chat.
Three forms can be embedded:
| Form | What it does | Requires |
|---|---|---|
waitlist | Collects waitlist signups | Waitlist enabled |
contact | Opens a conversation in your project’s inbox | Private messaging Pro |
beta | Public sign-up for one beta program | Beta enabled, program active with public sign-up on |
Adding an embed
Each form’s snippet is generated for you in the console — copy it and paste it into your own page where you want the form to appear:
- Waitlist — the project’s Waitlist section, under the settings card
- Contact — the project’s Settings page, under Contact form embed
- Beta — the beta program’s page, under Embed
A snippet looks like this:
<script src="https://acme.supdesk.app/embed.js"
data-supdesk="contact"
data-title="Contact Acme" data-height="520" async></script>
<noscript>
<iframe src="https://acme.supdesk.app/embed/contact" width="100%" height="520"
style="border:0" title="Contact Acme"></iframe>
</noscript>The script inserts the form where the tag sits and resizes it as the form
changes height — for example when validation errors appear, or when it
collapses into a short confirmation after a submission. The <noscript> block
is a plain iframe, so the form still works for visitors with JavaScript
disabled.
Everything is served from your own portal domain. If you have a
custom domain the console gives you snippets on
that domain; otherwise they use your *.supdesk.app subdomain.
Custom domains and root domains
Your custom domain and the origin your snippet points at must share the same root domain for the embed’s frame to talk to the loader. The console always generates the snippet with your active portal origin, so a snippet copied after your custom domain is set up needs no thought here: both the script and the form are served from your custom domain, same origin.
The case to watch is a snippet you copied before adding a custom domain.
Requests to your old origin are redirected to the custom domain, and the loader
accepts that redirect only when the two share a root domain — for example a
portal subdomain of feedback.apibot.dev and a custom domain of
www.apibot.dev both live on apibot.dev. If your custom domain is on a
different root entirely, the redirect is cross-domain and the embed will not
work: re-copy the snippet from the console after your custom domain is active.
Attributes
| Attribute | Required | Description |
|---|---|---|
data-supdesk | yes | Which form to embed: waitlist, contact, or beta |
data-program | beta only | The beta program’s slug |
data-title | no | Accessible title for the frame. Defaults to SupDesk form |
data-height | no | Starting height in pixels before the first resize. Defaults to 360 |
data-ref | no | Waitlist referral code to credit the signup to |
You can put more than one embed on a page — give each its own <script> tag.
Content Security Policy
If your own site sends a Content-Security-Policy header, allow your portal
origin in two directives, or the browser will block the embed:
script-src https://acme.supdesk.app;
frame-src https://acme.supdesk.app;Use your custom domain here if your snippets use one. Nothing else needs to be allowed — the embed loads no third-party scripts into your page and makes no network requests of its own.
Spam protection
Embedded forms use the same protections as your portal: they are rate limited per visitor and per project, and if you have configured Turnstile for the project, the challenge appears inside the embed too.
Because your Turnstile key is registered against your own domain, and embeds are served from that same domain, your key works in the embed with no extra setup.
Privacy and sign-in
Embedded forms never read or write a portal sign-in session — browsers do not send those cookies to a frame on someone else’s page, by design. Every embed is instead email-first: the visitor submits an email address and receives a link by email.
That has one consequence worth knowing when you place an embed: the visitor finishes the flow in a normal browser tab, not inside your page.
- Waitlist — the signup is recorded immediately; the email carries their position and personal referral link
- Beta — the email carries the accept link that enrolls them
- Contact — the message reaches your inbox immediately; the email is their receipt and lets them view your replies
Waitlist entries created through an embed are recorded with a source of
embed, so you can tell them apart from portal signups in the entries table
and in CSV exports.
What visitors see
The embed renders only the form itself — no portal header, footer, or navigation. It picks up your project’s brand color, so it inherits your accent without any styling work on your side.
Embedded pages are not indexed by search engines; your public portal pages are the canonical, indexable versions.
Legacy waitlist snippet
Before the script loader existed, the waitlist embed was a bare iframe pointing
at /waitlist/embed:
<iframe src="https://acme.supdesk.app/waitlist/embed" width="100%" height="360"
style="border:0" title="Waitlist"></iframe>This keeps working — you do not need to change anything. Replacing it with
the current snippet gets you automatic resizing; the fixed height on the old
iframe is the only real drawback.