Registration forms · 5 fields
Event registration form template
Registers one attendee with a ticket type and leaves room for dietary needs. Short enough for a meetup or a workshop, and easy to extend for a conference.
Event registration
Live demo: try the fields. Submitting sends nothing.
02 / Field guide
Why these fields
Full name
text · requiredRequired for the attendee list and name badges.
Email
email · requiredRequired. It is where the confirmation and any change of venue or time go.
Phone
tel · optionalOptional. Collect it only if you will call or text on the day, and say so in the help text.
Ticket type
select · optionalKeeps ticket counts exact. Rename the options to the tiers you actually sell, and remove the field if there is only one.
Dietary requirements
text · optionalOptional. Dietary and accessibility details can reveal health or religious information, so ask only what the caterer or venue needs and delete it after the event.
When to use it
Use it for free or invoiced events where the form is a registration, not a payment. If people pay at sign-up, take the payment in a payment provider and keep this form for the details you need on the day.
For a group registration with a head count, an accessibility question and a consent checkbox, start from the hosted event registration template instead. It runs on its own page, so you need no website at all.
Privacy and GDPR
- Keep event updates and marketing apart. A registration lets you send information about this event; a newsletter needs its own unticked checkbox.
- Dietary and accessibility notes are sensitive. The hosted template asks for a required consent before storing them, which is a good pattern to copy.
- Set the form's retention to a short period after the event, for example 30 days, so the attendee list does not linger.
03 / Make it yours
Choose your stack. Copy your form.
Replace the example endpoint with your Formward endpoint, then adapt the fields to your needs.
<form action="https://forms.formward.eu/f/your-form-id" method="POST">
<label for="name">Full name</label>
<input type="text" name="name" id="name" required />
<label for="email">Email</label>
<input type="email" name="email" id="email" required />
<label for="phone">Phone</label>
<input type="tel" name="phone" id="phone" />
<label for="ticket">Ticket type</label>
<select name="ticket" id="ticket">
<option value="General">General</option>
<option value="VIP">VIP</option>
<option value="Student">Student</option>
</select>
<label for="dietary">Dietary requirements</label>
<input type="text" name="dietary" id="dietary" />
<input type="text" name="_gotcha" tabindex="-1" autocomplete="off" style="position:absolute;left:-9999px" aria-hidden="true" />
<button type="submit">Send</button>
</form>Accessibility
Accessible by default, and how to keep it that way
- Every field in the code has a visible label tied to it with for and id, so screen readers announce what to enter and a click on the label focuses the field.
- Required fields carry the required attribute, so the browser explains a missing answer before anything is sent. Say “required” in words as well; an asterisk or a colour alone is easy to miss.
- The spam trap field (_gotcha) is hidden from screen readers with aria-hidden and skipped by the Tab key, so people never meet it.
- In the JavaScript versions, show the confirmation or error in an element with role="status" so the result is announced, and keep the entered answers when sending fails.
Changed the fields? Paste your version into the HTML form tester to see exactly what it sends, or run it through the GDPR form checker.
04 / Implementation
How the code talks to Formward
Each form you create gets its own endpoint in the form https://forms.formward.eu/f/your-form-id. The HTML version posts to it directly and the browser is redirected to a thank-you page, so it works without JavaScript.
The Next.js version below sends the same fields with fetch and an Accept: application/json header. Formward then answers with { ok: true, id }, or an error body with 402 when the plan limit is reached and 429 when the rate limit kicks in. See responses and status codes.
Next.js client component
"use client";
import { useState } from "react";
export function EventRegistrationForm() {
const [sent, setSent] = useState(false);
async function onSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
const form = e.currentTarget;
const res = await fetch("https://forms.formward.eu/f/your-form-id", {
method: "POST",
headers: { Accept: "application/json" },
body: new FormData(form),
});
if (res.ok) {
setSent(true);
form.reset();
}
}
if (sent) return <p>Thanks! Your message has been sent.</p>;
return (
<form onSubmit={onSubmit}>
<label htmlFor="name">Full name</label>
<input type="text" name="name" id="name" required />
<label htmlFor="email">Email</label>
<input type="email" name="email" id="email" required />
<label htmlFor="phone">Phone</label>
<input type="tel" name="phone" id="phone" />
<label htmlFor="ticket">Ticket type</label>
<select name="ticket" id="ticket">
<option value="General">General</option>
<option value="VIP">VIP</option>
<option value="Student">Student</option>
</select>
<label htmlFor="dietary">Dietary requirements</label>
<input type="text" name="dietary" id="dietary" />
<input
type="text"
name="_gotcha"
tabIndex={-1}
autoComplete="off"
style={{ position: "absolute", left: "-9999px" }}
aria-hidden="true"
/>
<button type="submit">Send</button>
</form>
);
}
Spam protection
- The generated code already includes the hidden _gotcha honeypot. Leave it in: a bot that fills it gets a normal success response, the submission is filed as spam and no email is sent.
- Every form has a per-IP rate limit, and you can restrict it to your own domains with the allowed-origins list in the form settings.
- Cloudflare Turnstile is optional and works on every plan, including Free. Turn it on in the form settings, add the widget to your markup and Formward checks the token server-side.
- The form settings can also reject disposable email addresses, which is worth turning on when a fake address would waste your time.
What happens after submit
- Each registration is emailed to you and stored in the EU on every plan. Export the attendee list as CSV from Personal up.
- A confirmation email to the attendee uses the autoresponder, available from Professional. Webhooks to a ticketing tool or a spreadsheet start at Professional.
Questions
- Can I cap the number of registrations?
- Yes. The form's response settings take a submission limit and a closing date. Once either is reached, Formward stops accepting registrations and shows your closed message instead.
- Should dietary requirements be required?
- No. Most attendees have none, and a required field pushes people to type None or something invented. Keep it optional and only ask what the caterer needs.
Related
- Registration templates
Course, webinar, contest and warranty registration.
- Online forms without a website
Publish the registration on its own page.
- Form data retention
Delete attendee data when the event is over.
- React forms
Post the form from a component without a backend route.
Customize before publishing
- Remove fields you do not need and mark only essential answers as required.
- Replace placeholder wording with terms your audience already understands.
- Add your privacy notice, retention details and expected response time.
- Test keyboard focus, validation errors and the confirmation state on mobile.
Use this template
Create a free account and the form is set up from this template. Copy your endpoint and replace https://forms.formward.eu/f/your-form-id in the code above.
No website? Use a hosted form
- Event registration hosted template Hosted page with ticket type, group size, optional dietary and accessibility notes and a consent checkbox.
- RSVP hosted template Yes, no or maybe with a guest count, for private events.