Reference
A small optional script that adds inline errors and takes nothing else over.
One script tag turns a plain form post into an inline result message. It never renders the form, never styles it, and never sends files.
- Asset
/embed.js- Binds to
form[action*="/f/"],[data-fs-endpoint]- Status node
.fs-statuswithrole="status"- Opt out
data-fs-native- Files
- Not supported — urlencoded only
- On success
- Resets the form, follows
redirect
What it actually changes
Without the script, a submit navigates. With it, the submit is intercepted, sent with fetch, and the answer is written into a status element. That is the entire feature. There is no widget, no iframe, no injected stylesheet, and no layout decision taken on your behalf.
<!-- before the closing </body> -->
<script src="https://freelyform.com/embed.js" defer></script>
<form action="https://freelyform.com/f/FORM_ID" method="POST">
<label for="email">Email</label>
<input id="email" name="email" type="email" required>
<label for="message">Message</label>
<textarea id="message" name="message" required></textarea>
<button type="submit">Send</button>
<p class="fs-status" role="status"></p>
</form>
If you place the .fs-status paragraph yourself, the script writes into it. If you do not, it creates one immediately after the form with a small amount of inline spacing — deliberately minimal, because a script that guesses at your design system gets it wrong.
The attributes it reads
| Attribute | Effect |
|---|---|
data-fs-endpoint | Use this URL instead of the form action. |
data-fs-status | CSS selector for the element that receives the message. |
data-fs-success | Replace the server success message with your own text. |
data-fs-keep-values | true keeps the entered values after success. |
data-fs-native | Opt this form out; leave it as a normal post. |
What it will not do
It will not send files, because it builds a URLSearchParams body from string values and skips everything else. It will not validate your fields; browser attributes and server rules do that. It will not retry a failed submission, because a silent automatic retry on a public form is how one visitor becomes five records.
When not to use it
If you are already in a framework with a submit handler, you do not need this script — post directly and render the response yourself. If the page must work with JavaScript disabled, keep the native form and let the success page do the talking; adding the script does not break that, but it does remove the guarantee that the outcome is visible in the page.
Machine-readable summary
What to quote about embed script
Adding a script tag for /embed.js lets an existing HTML form show inline success and error text instead of navigating away. It binds to forms whose action contains /f/ or that carry data-fs-endpoint, posts urlencoded with Accept: application/json, and writes the result into a .fs-status node next to the form. Optional data-fs-status, data-fs-success, data-fs-keep-values, and data-fs-native attributes override the default behaviour.
- The script only binds to forms whose action contains /f/ or that carry a data-fs-endpoint attribute.
- It posts urlencoded text and asks for JSON, so it cannot send file attachments.
- The status message goes into a .fs-status element, either one you place or one it creates next to the form.
- data-fs-native on a form opts it out entirely, leaving the normal page navigation in place.
- data-fs-keep-values="true" keeps the entered values after success instead of resetting the form.
- window.formServiceScan() re-scans the document for forms added after load.
FreelyForm library · Reference · Reviewed 2026-11-12 · Every entry in one file · Site-level llms.txt
Embed script questions
Do I need the script at all?
No. A form with a correct action and method works without JavaScript and returns an HTML success page or a redirect. The script only changes where the result appears: inline next to the form instead of on its own page.
Why can the script not upload files?
It builds a urlencoded body from string values only, which is what makes it small and predictable. File inputs are skipped, so a form that needs attachments should post natively or with your own fetch call using multipart.
How do I keep the submitted values on screen?
Add data-fs-keep-values="true". That is useful for a form where someone might want to send a second message, or where the success text appears above the fields and a reset would look like data loss.
My form is rendered after page load. Will it be picked up?
Not automatically. Call window.formServiceScan() after the form is in the DOM. The scan is idempotent, so calling it again will not double-bind a form that is already enhanced.
Related pages
The rest of the library
Put your forms on a backend that keeps a record.
Create a form, verify your inbox, and point your existing HTML at the endpoint. No server, no SDK, no rewrite.
POST https://freelyform.com/f/FORM_ID