Capture leads from your own website
Add your site to Raion Hub, allow-list the addresses your forms live on, then either drop in our widget or point a form you already have at our webhook. Every submission arrives as a lead, tagged to the form it came from. Allow about 20 minutes, plus whatever it takes to get one line of code onto your site.
This is the one integration with nothing to log into and no permission gate — every member of your workspace can see the Website forms card.
Before you start
- Someone who can paste one line of HTML into your site, just before the closing
</body>tag. If that is not you, do steps 1 to 5 and send them the snippet - The exact addresses your forms are served from — every domain and
subdomain, with the right
http://orhttps://. Getting this list wrong is the single most common reason submissions are refused - Your plan sets a limit on how many websites you can add. The app tells you if you reach it
Steps
Open Website forms
In the sidebar, under Automation, click Integrations, then click the Website forms card.
With nothing added yet the body reads Capture leads from your website — Connect a site to get an embed id and a domain allowlist. Drop in our widget or point an existing form at the webhook — every submission lands as a lead, tagged to its form.
Add your website
Click Add your first website. Once you have one site, the way to add another is Add Website in the top bar, or the + button on a phone.
The dialog is Add a website, with two fields:
- Display name (optional) — what you want to call this site inside Raion Hub. Leave it blank and the site is listed by its domain instead; you can name it later.
- First allowed domain — the address your form is served from, for example
https://example.com. You can add more afterwards, and you will need to if your forms sit on more than one address.
Only the domain is required — the name is for your own benefit
Press Add website. A bare example.com is accepted and tidied up to
https://example.com for you; anything the checker cannot make sense of is
refused before it is sent, with the reason underneath the field — see
domain rules.
Check the site’s Connection card
The new site is selected and its own column opens on the right. The first card there is named after the site and carries the two things worth knowing about:
- Embed ID (client_id) — read-only, generated for you, with a copy button. Your site sends this in the X-Client-Id header. This is the id that appears in the snippet you are about to copy, and it is safe to publish: it only works from the domains you allow-list.
- Capture leads from this site — the switch that decides whether submissions are accepted at all. Leave it on. Paused sites reject submissions with 403 — config is kept.
Your sites are listed on the left; the selected one's cards fill the column on the right
If you left the name blank, this card shows Not set — showing your domain and a Rename button, which swaps in a text field. ↵ saves, Esc cancels.
Allow-list every domain your form is served from
Open the Allowed domains card — Submissions are only accepted from these origins (Origin / Referer header). Type each address into the field and press Add (or ↵). The pill in the card’s header counts what you have used out of the limit: 3 / 20.
Add the apex domain, the www version, and any landing-page domains — each one separately
The card prints its own matching rule, and it is worth reading twice: Matched on scheme + host, case-insensitive, trailing slash ignored — e.g. https://acme.com covers /contact but not http:// or a subdomain.
https://acme.com does not cover https://www.acme.com, and http://
does not cover https://. Every subdomain and every scheme is a separate
entry. This is the cause of almost every “it returns 403” report, so add the
apex domain, the www version, and any landing-page domains now rather than
debugging it later.
Copy the snippet
Open the Send us leads card — Drop in the widget, or point an existing form
at the webhook. There are two methods, and the card opens on Webhook / API,
not the widget.
| Method | Use it when |
|---|---|
| Webhook / API | Point any existing form/backend at this endpoint — no widget needed. You get a curl command to copy the shape of |
| Embed widget | Paste this once before </body> — it auto-captures your lead forms, no per-form setup needed. You get one <script> tag |
For the widget, switch to Embed widget first, then press the copy button on the snippet. The addresses inside it are filled in for you.
The card opens on Webhook / API — switch to Embed widget before you copy
Either way, one rule governs what we accept: Payload needs a formId and at least one of email / phone in data. Extra fields auto-map to your lead fields.
Taking the webhook route instead? Skip to point an existing form at the webhook.
Paste it before </body>
Paste the snippet into your site’s HTML, immediately before the closing </body>
tag, on every page that carries a form. The four attributes it arrives with:
| Attribute | What it is for |
|---|---|
data-client-id | Required. Your embed id. Safe to expose; it only works from your allow-listed domains. |
data-api-base | Required. The Raion address the loader posts to — already filled in for you |
data-raion-auto | Captures forms that look like lead forms, meaning they have an email or phone field. Use data-raion-auto="all" for every form, or remove the attribute to capture only forms you tag yourself |
defer | Required, so the loader runs after your form exists |
The loader is additive by default: it sends us a copy and lets your own form submit as it always did, so nothing about your existing setup changes. There is more on tagging individual forms in widget options worth knowing.
The card also holds a Full widget setup guide you can open, which is the same five steps you are following here.
Find the form and give it a lead source
Now load one of your form’s pages in a browser. Then come back to Raion Hub and open the Forms & field mapping card — Forms appear from a page view (schema-on-bind) or the first submission. Map each to a lead source, then map its fields.
If it is not there yet, submit the form once for real and check again. Until a form arrives, the card reads No forms yet.
Each form that has arrived is a block with its name — or the id your developer gave it — and a Lead source picker. Pick the source its leads should land with, or choose + Create new lead source and type a name into the field that replaces the dropdown. It confirms with Form mapped.
An amber Auto pill means the form has no lead source yet. That is not an error — those leads still arrive, under the source the payload names, which defaults to one called Widget. Setting a source is how you take control of that.
Map its fields
Open the Map fields disclosure inside the form’s block. Each field the form sent is a row: its label, a state pill, a dropdown for the field it should fill, and an Ignore toggle.
Suggested is a guess, not a setting — Accept confirms, and Save is what actually stores it
| Pill | What it means |
|---|---|
| Confirmed | You chose or accepted this. It wins on every submission from now on |
| Suggested | We guessed it. It is not saved — the row says Suggested - confirm or change |
| Unmapped | Nothing chosen yet |
| Ignored | Dropped on arrival. The row’s dropdown goes inactive |
Work down the rows, then press Accept to confirm the suggestions in one go and Save to store them. Both are needed — Accept alone confirms nothing to the server, and it confirms only the rows that already have a field chosen, so the number on the button can be larger than the number it changes. Anything still Unmapped needs a field picking by hand.
It confirms with Field mapping saved. Only field types we can actually fill are offered in the dropdowns, so action buttons and file fields are not in the list.
Confirm leads are arriving
Submit your form for real, from the live page.
The Activity card is the readout — Ingest counts — dedupe + delivery health. Four tiles: Total, Processed, Duplicates, Failed, with a Refresh button to re-read them. A submission that worked lands in Processed and appears in your leads within a few seconds, with the lead source you chose.
If it lands in Failed, or nothing arrives at all, work through if something goes wrong.
Point an existing form at the webhook
If you would rather not add a script to your site, keep the Send us leads card
on Webhook / API and copy that snippet instead. It is a POST to our ingest
address carrying:
- a
Content-Typeheader X-Client-Id, holding your embed idOrigin, holding one of your allow-listed domains- a JSON body with a
formIdand at least one ofemailorphoneinsidedata
Everything else you send is matched to your lead fields automatically, and you can tighten that up afterwards under Forms & field mapping. On this route a form appears in that card after its first submission, so send one test entry to bring it into the list.
The addresses in the snippet belong to your deployment, so copy them from the card rather than from anywhere else.
Widget options worth knowing
From the Full widget setup guide on the Send us leads card:
Attribute on your <form> | What it does |
|---|---|
data-raion-form | Pins a stable id for the form, so it stays the same form in Raion Hub across redesigns |
data-raion-ignore | Skips that form entirely |
data-raion-prevent | Lets the widget own the submit, instead of sending a copy alongside your own form’s submission |
Two more things from the guide:
- Fields are read by their
name, and a form needs at least anemailor aphoneto be captured at all. - The loader adds a hidden
_hp_checkhoneypot field. Bots that fill it in are dropped, and a real visitor never sees it.
If your forms appear after a page change — a single-page app, or a form that
mounts in a modal — the guide’s own instruction is to call window.raion?.scan()
after the route change so the loader binds the new forms.
Stamp a fixed value on every lead
Inside Map fields there is a second editor, Preset values — Fill CRM fields this form doesn’t ask for — every lead from it gets these. It is how a form with three fields can still produce a lead with a branch, a campaign or a channel filled in.
Press Add field, choose the field, and set the value. The control you get for the value depends on the field: a searchable option picker for a dropdown, a date picker for a date, Yes/No for a yes-no field, a number box for a number or currency, and a plain text box for anything else. Before you have chosen a field it reads Pick a field first.
- Changing the field clears the value, because the new field may not accept the old one.
- One preset per field. A field another row is using drops out of the other dropdowns.
- Save stays unavailable while any row is incomplete — no field chosen, or a blank value.
The card carries the one thing people misread as a bug: A submitted value wins. If the form ever sends one of these fields, the visitor’s answer is kept and the preset is skipped for that lead. A preset is a default, not an override.
Pause a site without deleting it
Turn Capture leads from this site off, or use Pause capture in the site’s ⋮ menu in the left rail. The site then shows an amber Paused pill and its dot turns amber.
Pausing takes effect immediately and on our side: submissions are refused with a
403 and nothing is queued up for later. Your configuration — embed id,
domains, mappings, presets — is untouched, and Resume capture puts it straight
back to work.
That menu also holds Copy embed ID, which saves opening the site to get at it.
Server-to-server posting, and the secret key
Open Advanced & danger zone — the card is collapsed until you press Show. Its own guide opens with the important part: Most people don’t need this. If you embed the widget or post from the browser, the embed id + your allow-listed domain is all the auth you need. The secret key is only for server-to-server posting, where there’s no browser Origin to check.
If you do need it:
- Press Generate secret. The value appears once, under New secret generated — copy it now, with a copy button. This is the only time it’s shown — store it in your server’s environment now. We keep only a hash of it.
- Your server exchanges that secret for a short-lived token, good for about
15 minutes, and posts with the token instead of an
Originheader. - Rotate secret issues a fresh one and shows it once. The old secret stops minting tokens immediately, but tokens already issued keep working until they expire. Clear turns server-to-server access off altogether.
The card tells you which state you are in with a Secret set or No secret pill, and the secret belongs to this one website.
Keep it server-side. Never ship the secret in front-end code or a mobile app. Only the short-lived token should leave your server.
Deleting a website
At the bottom of Advanced & danger zone is a red band: Removes the embed id, all form mappings and ingest history. Cannot be undone. Delete asks once more, with Delete this website? — This permanently removes the site, its embed id, all form mappings, and ingest history. Sites embedding this id will stop capturing. This cannot be undone.
Any page still carrying that embed id stops capturing the moment you confirm. If what you actually want is a pause, use Pause capture — it keeps everything and is one click to undo.
The domain rules that cause most 403s
The domain field checks what you type before it sends it, so these all appear under the field rather than after a failure:
| Message | What it means |
|---|---|
| Enter a domain. | The field is empty |
| Wildcards aren’t allowed — add each domain explicitly. | You used a * |
| A domain can’t contain spaces. | There is a space in it |
| That doesn’t look like a valid domain. | It could not be read as a domain at all |
| Only http:// and https:// are allowed. | Some other scheme was used |
| Domains only — drop the path (e.g. https://example.com ). | You included a path, a query or a # |
| Enter a full domain, e.g. example.com. | It is not a complete host name |
| That domain is already on the list. | It is already there |
And two limits:
- 20 domains per site. The header pill turns amber at the cap, and adding more is refused with You’ve reached the 20-domain limit for one site.
- A site must keep at least one domain. Removing the last one is refused: Keep at least one domain, or pause the site instead.
If something goes wrong
| What you see | Why | What to do |
|---|---|---|
403 on submit | The page’s address is not allow-listed, or the site is paused | Add that exact address — scheme and subdomain included — under Allowed domains, and check Capture leads from this site is on |
| The form never appears under Forms & field mapping | No data-raion-form id, or the submission carried neither an email nor a phone | Tag the form with data-raion-form, make sure it has an email or phone field, then load the page and submit once |
| No forms yet, after adding the snippet | The loader has not run on a page you have opened | Check the snippet is before </body> and keeps its defer, then reload the page. On a single-page app, call window.raion?.scan() after the route change |
| Duplicate leads | Retries are being counted separately | Send a stable externalId with each submission so retries are deduplicated |
| Leads arrive, but a field is empty | That field is Unmapped or Ignored | Open Map fields, choose the field, then Accept and Save |
| A mapping you set does not stick | Accept was pressed but Save was not | Press Save as well. A Suggested row is never stored on its own |
| Leads land under a source called Widget | The form has no lead source, so it carries the payload’s own | Pick a Lead source on the form. The amber Auto pill marks the ones that need it |
| A preset value is missing on a lead | The visitor answered that field, so their answer was kept | Nothing to fix — a submitted value always wins over a preset |
| No fields detected yet. | The form has arrived but its fields have not registered | Open the page again with the widget in place, or submit one entry |
| Failed to load fields. or Failed to load preset values. | The editor could not load | Reload the page. If it repeats, message support |
| Failed to refresh activity | The counts could not be re-read | Press Refresh again in a moment |
| A red message on the Preset values card | The backend refused that value for that field’s type | Correct the value — the message names what it objected to |
| A different site is selected than you left open | The selection is remembered in your browser, not in the address | Pick your site again from the left rail. In a private window it falls back to the first site |
| A message about your plan’s limit when adding a site | You have as many websites as your plan allows | Delete one you no longer use, or upgrade |
Next
- Capture leads from Facebook and Instagram adsConnect a Meta account, choose which Pages to bring in, map one form's fields,
- Capture leads from TikTok Lead AdsConnect TikTok, choose which advertiser accounts to bring in, map one form's
- Find the contacts you needFour controls in the toolbar decide who you are looking at: Owner (whose