Guide

Forms

Receive contact forms on a static site: copy-paste HTML, email notifications, a spam filter, an inbox with CSV export, and a JavaScript option.

On this page

Your site is made of static files, so a contact form on it has nowhere to send its answers. Zeloxa gives every form an address to send to. Visitors fill in the form as usual, and each message lands in your project's Forms tab and, if you like, in your email. Spam is filtered out for you.

It works with any site: plain HTML, a site builder export, or a framework. There is no code to run on a server.

Add a contact form

  1. Open your project in Hosting and choose the Forms tab.
  2. Choose Create your first form (or New form).
  3. Give it a Form name you will recognise, such as Contact form.
  4. Under Email new submissions to, tick the people in your organization who should get each message (up to 5; you are ticked already). Untick everyone to only collect messages in the dashboard.
  5. Choose Create form.

What you'll see: the form's Add to your site page, with its address, a ready-made contact form to copy, and a test command.

  1. Copy the HTML with the Copy button and paste it into the page where the form should appear (for example contact.html).
  2. Deploy your site as usual, open the page, and send yourself a test message.

What you'll see: a "Thank you!" page with a Back to site button. The message appears under Submissions, and in your email if you added an address.

The ready-made form

This is the form the dashboard gives you, with your own form's address in place of f_XXXXXXXXXXXXXXXX:

<form action="https://zeloxalabs.com/api/forms/f_XXXXXXXXXXXXXXXX" method="POST">
  <label>Name <input type="text" name="name" required></label>
  <label>Email <input type="email" name="email" required></label>
  <label>Message <textarea name="message" rows="5" required></textarea></label>
  <input type="text" name="_gotcha" style="display:none" tabindex="-1" autocomplete="off">
  <button type="submit">Send</button>
</form>

Change it to suit your site:

  • Add or remove fields. Every field with a name is saved, in the order it appears in the form. Checkboxes and multiple choices that share a name are saved together, separated by commas.
  • Style it with your own CSS. Only the action and method matter.
  • Already have a form? Keep it, and set its action to your form's address and its method to POST.
  • Keep the hidden _gotcha field. It is the spam trap: people never see it, bots fill it in (see Spam protection).
  • Name the email field email. Notification emails then reply straight to the person who wrote.

File uploads are not supported: file fields are ignored, and a very large upload is refused. Ask visitors for a link instead (for example to a shared folder).

Send it with JavaScript

To keep visitors on the page and show a message instead of a thank-you page, send the form with fetch. The Add to your site page has a complete, copyable example; the important part is:

const response = await fetch("https://zeloxalabs.com/api/forms/f_XXXXXXXXXXXXXXXX", {
  method: "POST",
  headers: { Accept: "application/json" },
  body: new FormData(form),
});
const result = await response.json();

You can also send JSON, for example from a framework:

await fetch("https://zeloxalabs.com/api/forms/f_XXXXXXXXXXXXXXXX", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ name: "Ada", email: "ada@example.com", message: "Hello" }),
});

What you'll see: status 200 and { "ok": true, "message": "Thanks! Your submission was received." }. When something is wrong, the status explains it and the body says why, for example { "ok": false, "error": { "code": "RATE_LIMITED", "message": "…" } }.

Browsers only let a page read the answer when the page is on your own site: your project's address, its preview addresses and its connected custom domains, over HTTPS. A page anywhere else can still send the form, but cannot read the reply.

Statuserror.codeWhat it means
400EMPTY_SUBMISSIONEvery field was empty.
400INVALID_BODYThe JSON or form data could not be read.
400CHALLENGE_FAILEDThe anti-spam check is on and was not completed.
403FORM_UNAVAILABLEThe form is turned off, or the account is suspended.
404NOT_FOUNDNo form has this address (it may have been deleted).
413TOO_MANY_FIELDSMore than 50 fields.
413FIELD_TOO_LARGEOne field is longer than 10 KB.
413PAYLOAD_TOO_LARGEThe whole submission is larger than 64 KB, or a file was attached.
415UNSUPPORTED_CONTENT_TYPEThe body was not form data or JSON.
429RATE_LIMITEDSent too often. Wait for the time in the Retry-After header.
429MONTHLY_LIMITThe project received its monthly maximum of submissions.

A normal browser form post gets the same answers as a simple page instead of JSON, with a Back to site button when the form was on your site.

Thank-you page

After sending, visitors see a plain "Thank you!" page with a Back to site button. It shows no name or logo, so it suits any site.

To use a page of your own instead, open the form's Settings and fill in Thank-you page:

  • a path on your site, such as /thanks or /thanks.html (the visitor stays on the domain they were on), or
  • a full address on one of your project's own domains, such as https://www.yourbusiness.com/thanks.

Addresses on other websites are refused, so the form cannot be used to send visitors somewhere unexpected. If you later remove the domain the page is on, visitors get the plain thank-you page instead.

Email notifications

Each new message (not spam) is emailed to the people ticked under Email new submissions to. The email lists every field, links to the message in your dashboard, and replies go to the visitor when the form has a valid email field.

Notifications only go to members of your organization: the list shows your team, and the person who creates a form is ticked by default. To email someone else, invite them to the organization first. Recipients are checked again for every message, so someone who leaves the organization stops receiving its submissions straight away, even before the form is edited.

An email that cannot be delivered never loses the message: it is always saved in the inbox first. Each message shows whether its email went out (Emailed) or not, and why.

Spam protection

Every form is protected in four ways, with nothing for you to set up:

  • The spam trap. The hidden _gotcha field is invisible to people, but bots fill in every field they find. Anything that fills it in is accepted quietly (so the bot does not retry) and filed under Spam. If your form already uses a field called _gotcha, choose another name under Spam protection in the form's settings and use that name in your HTML.
  • Link filter. A message that is little more than links, or has more than five, is filed under Spam.
  • Rate limits. One visitor can send a form 10 times a minute, and one form accepts 500 submissions a day. From the 21st message in a day, everything one visitor sends to a form is accepted as usual but filed under Spam: it is never emailed and does not count towards the monthly limit, so one sender cannot fill your inbox or use up your month.
  • Size limits. See Limits.

Spam is kept for you to check, in the Spam folder, and is never emailed. If something real ends up there, open it and choose Not spam.

For forms that attract a lot of spam, turn on Require an anti-spam check under Spam protection, when your account offers it. Visitors then pass a quick check, usually invisible, before the form sends. The Add to your site page shows the two extra lines to add to your page; without them, submissions are refused.

Your inbox

The Submissions tab of a form lists messages newest first, 25 per page.

  • Open a message to read every field. Opening it marks it as read; choose Mark as unread to flag it again. Unread only shows what you have not read yet.
  • Mark as spam moves a message to the Spam folder; Not spam moves it back.
  • Delete removes a message for good, after you confirm.
  • Export downloads a CSV file that opens in Excel, Numbers or Google Sheets: the folder you are looking at, or Export all. Values that a spreadsheet would treat as a formula (starting with =, +, - or @) are saved with a leading apostrophe, so opening an export can never run something a visitor typed.

To stop a form from accepting messages without deleting anything, choose Turn off. Visitors who send it then see that it is not accepting submissions. Turn on reverses it.

Deleting a form (under Settings) deletes all of its messages too, and its address stops working at once.

Limits

LimitValue
Forms per project20
Notification addresses per form5
Fields per submission50
Size of one field10 KB
Size of one submission64 KB
Submissions per visitor10 per minute, per form
Inbox messages per visitor20 per day, per form (the rest go to Spam)
Submissions per form500 per day
Submissions per project1,000 per month
How long submissions are kept12 months

The monthly limit counts inbox messages across all of a project's forms, from the 1st of each month (UTC). Spam does not count towards it. The Forms tab shows how much of it is used. Once it is reached, new messages are refused until the next month, and visitors are asked to get in touch another way.

Privacy

  • Messages are stored for 12 months, then deleted automatically. Export them to keep a copy for longer.
  • Visitors' IP addresses are never stored. Only a one-way code made from the address is kept, so repeated sending can be limited without knowing who sent it.
  • The browser name and the page the form was sent from are saved with each message, to help you spot spam.
  • Only members of your organization can see a project's messages.

Troubleshooting

"This form does not exist." The address in your form's action is wrong or the form was deleted. Copy the address again from the form's Add to your site page.

"This form is not accepting submissions right now." The form is turned off. Open it and choose Turn on.

Messages arrive in Spam. Check the hidden field: it must stay empty and hidden (style="display:none"). A form builder that fills in every field, or a password manager, can trigger the trap; rename the field in Spam protection if needed.

No email arrives. Check who is ticked under Email new submissions to (only members of your organization can be emailed) and your spam folder. The message itself is always in the dashboard, with its email status.

My JavaScript cannot read the reply. The page must be on your project's own domain over HTTPS. Test from your live site rather than from a file on your computer.

I get "Please wait a moment". The same browser sent the form more than 10 times in a minute. Wait a minute and try again.

For developers: the dashboard API

The Forms tab uses these routes. They take the dashboard session only (not API tokens) and live under /api/host/sites/{siteId}:

MethodPathDoes
GET/formsLists forms with this month's counts and the project's usage.
POST/formsCreates a form: name, notifyEmails (members' addresses only; defaults to yours), redirectUrl, honeypotField, requireChallenge, enabled.
GET/forms/{formId}One form.
PATCH/forms/{formId}Changes any of the fields above.
DELETE/forms/{formId}Deletes the form and its submissions.
GET/forms/{formId}/submissions?folder=inbox&unread=1&page=1One page of submissions, newest first.
PATCH/forms/{formId}/submissions/{submissionId}{ "read": true } or { "spam": false }.
DELETE/forms/{formId}/submissions/{submissionId}Deletes one submission.
GET/forms/{formId}/export?folder=inboxCSV of inbox, spam or all (10,000 newest at most).

Creating, changing and deleting forms, and deleting submissions, are recorded in Activity.

Ready when you are

Everything in this guide is under Hosting in your dashboard.

Open Hosting

Something unclear or missing? Tell us.