Skip to content

Feedback forms · 3 fields

NPS survey template

The standard Net Promoter Score question on a 0 to 10 scale, followed by one open question about the reason. Two answers are enough; every extra question lowers the response rate.

Get the code

NPS survey

Live demo: try the fields. Submitting sends nothing.

Why these fields

  • Email

    email · optional

    Optional. Leave it empty for anonymous answers, or prefill it as a hidden field from your email link if you plan to follow up with detractors.

  • How likely are you to recommend us? (0-10)

    number · required

    Required, and the only number you need. The generated markup is a plain number input, so add min="0" max="10" to it; the browser then rejects anything outside the scale.

  • What is the main reason for your score?

    textarea · optional

    Optional, but this is where the useful part lives. A single open question gets more honest answers than a list of checkboxes.

When to use it

Send it a few weeks after onboarding or after a support case is closed, by email link or on a thank-you page. Asking the same customer too often wears the score down.

If you want to know what to fix rather than how loyal people are, a customer satisfaction or feature feedback survey asks more directly.

Privacy and GDPR

  • Say whether answers are anonymous, and mean it. If the survey collects email, you can link a score to a person.
  • Free text can contain anything, including personal details about staff. Keep the retention short and review answers before sharing them widely.

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="email">Email</label>
  <input type="email" name="email" id="email" />
  <label for="score">How likely are you to recommend us? (0-10)</label>
  <input type="number" name="score" id="score" required />
  <label for="reason">What is the main reason for your score?</label>
  <textarea name="reason" id="reason"></textarea>
  <input type="text" name="_gotcha" tabindex="-1" autocomplete="off" style="position:absolute;left:-9999px" aria-hidden="true" />
  <button type="submit">Send</button>
</form>

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.

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 NpsSurveyForm() {
  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="email">Email</label>
      <input type="email" name="email" id="email" />
      <label htmlFor="score">How likely are you to recommend us? (0-10)</label>
      <input type="number" name="score" id="score" required />
      <label htmlFor="reason">What is the main reason for your score?</label>
      <textarea name="reason" id="reason" />
      <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

  • Every answer is stored in the EU and emailed to you on every plan. To compute NPS, export the responses as CSV (from Personal) and subtract the share of 0 to 6 scores from the share of 9 and 10 scores.
  • Webhooks from Professional can push each score to a dashboard or a spreadsheet as it arrives.

Questions

How do I calculate NPS from the responses?
Count scores of 9 and 10 as promoters and 0 to 6 as detractors. NPS is the percentage of promoters minus the percentage of detractors, a number between minus 100 and 100.
Why does the hosted NPS template use a 1 to 5 scale?
Hosted forms render ratings on a 1 to 5 scale. If you need a true 0 to 10 NPS, use this code template on your own site, where the score is a number field.

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.

Use this template →

No website? Use a hosted form

  • NPS survey hosted template Hosted page with a loyalty rating and a reason. It uses the 1 to 5 rating scale of hosted forms, so it is not a standard 0 to 10 NPS.