Complaint form template

    What happened, when, the reference to look it up, and what would put it right.

    Reviewed by Ritu Fadadu · Last reviewed

    Preview and code

    Preview

    How should we contact you? (optional)

    Code — replace YOUR_ENDPOINT_ID with your form's ID

    <style>
      .fb-form { display: grid; gap: 1rem; max-width: 36rem; }
      .fb-field { display: flex; flex-direction: column; gap: 0.375rem; }
      .fb-fieldset { margin: 0; padding: 0; border: 0; min-width: 0; }
      .fb-label { font-weight: 600; }
      .fb-optional { font-weight: 400; color: #6b7280; }
      .fb-help { margin: 0; font-size: 0.875rem; color: #6b7280; }
      .fb-input { box-sizing: border-box; width: 100%; padding: 0.625rem 0.75rem; border: 1px solid #d1d5db; border-radius: 0.5rem; background: #fff; color: #111827; font: inherit; }
      .fb-input:focus { border-color: #2563eb; outline: 2px solid #2563eb; outline-offset: 1px; }
      .fb-options { display: flex; flex-direction: column; gap: 0.5rem; }
      .fb-option { display: flex; align-items: center; gap: 0.5rem; }
      .fb-check { width: 1.125rem; height: 1.125rem; margin: 0; accent-color: #2563eb; }
      .fb-button { justify-self: start; min-height: 44px; padding: 0.625rem 1.25rem; border: 0; border-radius: 0.5rem; background: #2563eb; color: #fff; font: inherit; font-weight: 600; cursor: pointer; }
      .fb-button:hover { background: #1d4ed8; }
      .fb-button:focus-visible { outline: 2px solid #2563eb; outline-offset: 2px; }
      .fb-button:disabled { opacity: 0.6; cursor: wait; }
      .fb-status { margin: 0; min-height: 1.5em; }
      @media (min-width: 640px) {
        .fb-form { grid-template-columns: 1fr 1fr; }
        .fb-field, .fb-button, .fb-status { grid-column: 1 / -1; }
        .fb-field--half { grid-column: auto; }
      }
    </style>
    
    <form id="fb-form" class="fb-form" action="https://formboost.app/f/YOUR_ENDPOINT_ID" method="POST">
      <div class="fb-field fb-field--half">
        <label for="fb-name" class="fb-label">Name</label>
        <input type="text" id="fb-name" name="name" class="fb-input" required autocomplete="name">
      </div>
      <div class="fb-field fb-field--half">
        <label for="fb-email" class="fb-label">Email</label>
        <input type="email" id="fb-email" name="email" class="fb-input" required autocomplete="email">
      </div>
      <div class="fb-field fb-field--half">
        <label for="fb-category" class="fb-label">What is it about?</label>
        <select id="fb-category" name="category" class="fb-input" required>
          <option value="">Choose…</option>
          <option value="a-product">A product</option>
          <option value="a-service">A service</option>
          <option value="billing">Billing</option>
          <option value="a-member-of-staff">A member of staff</option>
          <option value="something-else">Something else</option>
        </select>
      </div>
      <div class="fb-field fb-field--half">
        <label for="fb-reference" class="fb-label">
          Order or reference number
          <span class="fb-optional">(optional)</span>
        </label>
        <input type="text" id="fb-reference" name="reference" class="fb-input">
      </div>
      <div class="fb-field fb-field--half">
        <label for="fb-incident_date" class="fb-label">
          When did it happen?
          <span class="fb-optional">(optional)</span>
        </label>
        <input type="date" id="fb-incident_date" name="incident_date" class="fb-input">
      </div>
      <div class="fb-field">
        <label for="fb-details" class="fb-label">Tell us what happened</label>
        <textarea id="fb-details" name="details" class="fb-input" required rows="6"></textarea>
      </div>
      <div class="fb-field">
        <label for="fb-resolution" class="fb-label">
          What would put this right?
          <span class="fb-optional">(optional)</span>
        </label>
        <textarea id="fb-resolution" name="resolution" class="fb-input" rows="3"></textarea>
      </div>
      <fieldset class="fb-field fb-fieldset">
        <legend class="fb-label">
          How should we contact you?
          <span class="fb-optional">(optional)</span>
        </legend>
        <div class="fb-options">
          <label class="fb-option">
            <input type="radio" name="contact_method" value="email" class="fb-check">
            <span>Email</span>
          </label>
          <label class="fb-option">
            <input type="radio" name="contact_method" value="phone" class="fb-check">
            <span>Phone</span>
          </label>
        </div>
      </fieldset>
      <!-- Honeypot: keep it hidden. People never see it; bots fill it in and get flagged as spam. -->
      <div
        aria-hidden="true"
        style="position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden"
      >
        <label for="fb-honey">Leave this field empty</label>
        <input type="text" id="fb-honey" name="_honey" tabindex="-1" autocomplete="off">
      </div>
      <input type="hidden" name="_subject" value="New complaint">
      <button type="submit" class="fb-button">Send complaint</button>
    </form>
    

    About this template

    A good complaint form makes a complaint easier to resolve, not easier to dismiss. This template asks for the facts you need to investigate — a category, an order or reference number, the date — and then the question most forms skip: what would put this right? Knowing the outcome someone wants is half the resolution.

    The tone of the labels matters here. “Tell us what happened” reads better than “Describe the issue”, and none of the fields asks the customer to justify themselves. The reference number is optional, because not every complaint has one and a required field the customer cannot fill in turns a complaint into two.

    Say on the page how soon you respond and who will. Complaints are the submissions where a fast acknowledgement matters most — on Starter and above, Auto Reply sends one the moment the form is submitted.

    Fields in this template

    FieldNameTypeRequiredWhy it is there
    NamenameShort textYesRequired.
    EmailemailEmailYesRequired, so you can respond and Auto Reply can acknowledge.
    What is it about?categoryDropdownYesRequired dropdown, for routing to the right person.
    Order or reference numberreferenceShort textNoOptional — not every complaint has one.
    When did it happen?incident_dateDateNoOptional date picker.
    Tell us what happeneddetailsLong textYesRequired. The account of what happened.
    What would put this right?resolutionLong textNoOptional, and the most useful answer on the form.
    How should we contact you?contact_methodSingle choiceNoOptional preference.

    Each name becomes a column in your dashboard and a row in the notification email. The hidden _honey field is the honeypot; _subject sets the email's subject line. Both are reserved fields and never appear in the field table.

    Make it yours

    • Add a phone field if you prefer to resolve complaints by call — make it optional.
    • Rename the categories to your own departments so each complaint reaches its owner.
    • Keep the success message human; it is the first response the customer reads.
    • If complaints also arrive by phone or in person, add a hidden channel field and enter those into the same form, so every complaint is counted in one export.

    Where the submissions go

    • Complaints are stored and emailed to you; export them to CSV on every plan to spot recurring causes.
    • Post each complaint to a private Slack or Discord channel so it is never missed.
    • On Starter and above, open a case in your helpdesk with a webhook or Zapier.

    Feedback Forms: plans, destinations and a worked setup →

    Before you publish it

    1. Create a form in the Formboost dashboard and replace YOUR_ENDPOINT_ID with its ID.
    2. Pick one variant: HTML posts and reloads, HTML + JS and React send JSON with fetch() and stay on the page.
    3. For the plain HTML version, add a hidden _redirect with an https:// thank-you page on the same site as the form — anything else falls back to Formboost's page.
    4. Submit it once from the live page and check the submission in your dashboard. Every request is acknowledged, so the dashboard is the real test. Troubleshooting covers the rest.

    More form templates

    Put the complaint form live

    Free forever: 500 submissions a month across 10 forms, no card.