HTML form submission

HTML form submission6 min read

Redirect to a thank-you page after form submit

Send visitors to your own thank-you page after a form posts: the 303 redirect, the _redirect field, which domains are allowed and what refresh does.

Preet SutharFounder, Ikiform

A form can't redirect itself; the server that receives the post answers 303 See Other with a Location header, and the browser loads that page. With Ikiform, set Redirect after submit in the form's settings, or add a hidden _redirect input with an https: URL on one of the form's Allowed domains. With neither, visitors land on Ikiform's hosted thank-you page.

The example is a demo request form whose thank-you page is really a next step: it asks the visitor to pick a time. That makes the redirect target matter more than usual, and it raises the question this page is mostly about: who is allowed to decide where a form sends people.

What's different here

HTML has no attribute for "go here after submit". The action is where the data goes, and the page after that is whatever the server answers. So the redirect is always the receiving server's decision. When that server is Ikiform, there are exactly two ways to influence it, and they don't carry the same trust.

ItemRedirect after submit setting_redirect hidden input
Who sets itMembers of your workspace, in the dashboardAnyone who can edit the page's HTML, or the visitor's browser
Allowed targetsAny http: or https: URLhttps: only, on an allowed domain or a subdomain of one
ScopeOne target for the whole formOne per page, so per language or per campaign
When both are setWinsIgnored

The strict rules on _redirect exist because its value arrives with the post. Without them, anyone could put your form's URL in a link that posts and then bounces visitors to a phishing page, which is what an open redirect is.

How Ikiform picks where to send the browser after a successful post1. Redirect after submit is set2. _redirect passes the rules3. neithersuccessful postdashboard settingany http: or https: URL303 to itsuccessful post_redirect or _nexthttps:, allowed domain,no port303 to itsuccessful posthosted thank-you/f/<formId>/thanks303 to itlinks back to your pageHow Ikiform picks where to send the browser after a successful post1. Redirect after submit is set2. _redirect passes the rules3. neithersuccessful postdashboard settingany http: or https: URL303 to itsuccessful post_redirect or _nexthttps:, allowed domain, no port303 to itsuccessful posthosted thank-you/f/<formId>/thanks303 to itlinks back to your page
  1. If the form has a Redirect after submit URL in its settings, Ikiform answers with a 303 to it and looks no further.
  2. Otherwise, if the post has a _redirect field, or _next, that is an https URL on an allowed domain with no port or credentials, Ikiform redirects there.
  3. Otherwise Ikiform redirects to its hosted thank-you page, which links back to your page when the post came from an https page on an allowed domain.
The first match wins. A _redirect that fails the rules falls through silently; it is never an error.

The form

demo.html
<form action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="post">
  <label for="email">Work email</label>
  <input id="email" name="email" type="email" autocomplete="email" required />

  <label for="company">Company</label>
  <input id="company" name="company" autocomplete="organization" required />

  <label for="team_size">Team size</label>
  <select id="team_size" name="team_size">
    <option value="1-10">1 to 10</option>
    <option value="11-50">11 to 50</option>
    <option value="51+">51 or more</option>
  </select>

  <input type="hidden" name="_redirect" value="https://example.com/demo/next-step" />
  <input name="_gotcha" type="text" tabindex="-1" autocomplete="off" hidden />
  <button>Request a demo</button>
</form>

Add example.com under the form's Allowed domains and this posts, gets a 303 and lands on /demo/next-step. The thank-you page is ordinary HTML on your site:

demo/next-step.html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="robots" content="noindex" />
    <title>Thanks, pick a time</title>
  </head>
  <body>
    <h1>Thanks. One more step.</h1>
    <p>Pick a time for your demo. You'll get a calendar invite right away.</p>
    <p><a href="https://cal.example.com/acme/demo">Choose a time</a></p>
  </body>
</html>
  • noindex keeps it out of search results. Nobody should land there from Google, and a thank-you page in your analytics as an entrance is a sign something links to it.
  • Refresh is safe. Because Ikiform answered with 303, the browser loaded this page with GET, and reloading it sends nothing again.
  • If you count conversions on this page, count once per session. A refresh or a bookmark reloads it, and Ikiform's dashboard is the real count.

Redirecting to another site

Suppose you want to skip your own page and send people straight to a booking tool on another domain, such as cal.example.com or a scheduling service's domain. With _redirect, that domain would have to be in Allowed domains, and that list has a second job: it decides which sites may post to the form. Adding a scheduling service's domain means pages on that domain could post to your form too.

Use Redirect after submit in the form's settings instead. It accepts any URL, because only your workspace can set it, and it leaves Allowed domains listing only your own sites.

Ikiform redirects to the URL exactly as given. It doesn't append the submission id or any field values, so a booking page can't be prefilled from the redirect. Ask for the email again there, or link to the booking page from your own thank-you page.

Different pages for different forms

The dashboard setting is one URL per form. When one form appears on several pages that need different thank-you pages, leave the setting empty and give each page its own _redirect. A German page sends visitors to the German thank-you page:

de/demo.html
<input type="hidden" name="_redirect" value="https://example.com/de/demo/danke" />

Adding a value to the redirect

Query strings on _redirect are kept, so you can pass what the visitor chose to the thank-you page. Set the value in a submit listener, which runs after the browser's validation and before the form is encoded:

demo.js
const form = document.querySelector("form");
const redirect = form.elements.namedItem("_redirect");

form.addEventListener("submit", () => {
  const size = form.elements.namedItem("team_size").value;
  const next = new URL("https://example.com/demo/next-step");
  next.searchParams.set("size", size);
  redirect.value = next.href;
});

The visitor arrives at /demo/next-step?size=11-50, and the page can show the right booking link for that team size. Keep it to non-personal values: query strings end up in browser history, server logs and analytics.

Redirecting after a fetch submit

A fetch call gets JSON, not a redirect, so Ikiform's redirect rules don't apply. Navigate yourself when the answer is ok:

Redirect from a script
const response = await fetch(form.action, {
  method: "POST",
  headers: { Accept: "application/json" },
  body: new FormData(form),
});
const result = await response.json();
if (result.ok) location.assign("/demo/next-step");

Use location.assign rather than location.replace if the back button should return to the form. The no-reload guide has the full handler with errors and loading state.

Check it works

  1. Under the form's Allowed domains, add your site's domain, plus localhost while you develop. Leave it empty to accept posts from anywhere.
  2. Submit the form from your live page. The address bar shows your thank-you page, and the Network panel shows the post answered with 303.
  3. Press refresh on the thank-you page. The browser doesn't ask to resubmit, and the dashboard still shows one submission.
  4. Change _redirect to an address on a domain that isn't allowed and submit. You land on Ikiform's hosted thank-you page instead, with no error.
  5. Open Submissions in the dashboard. The new submission is there with every field you sent.

Gotchas

ProblemCause and fix
_redirect is ignored even though the domain is allowedRedirect after submit is set in the form's settings, and it always wins. Clear it to use per-page redirects
Works in production, not on localhost_redirect must be https: with no port, so http://localhost:3000/thanks never passes. Test on a preview deploy, or accept the hosted page locally
The hosted thank-you page has no link back to your siteIt links back only when the post came from an https: page on one of the form's allowed domains. Add the domain, or redirect to your own page
The browser lands on Ikiform's thank-you page instead of yours_redirect is ignored unless its domain is in Allowed domains and it is an https: URL. Add the domain, or set Redirect after submit in the form's settings instead.
The thank-you page shows in search resultsAdd <meta name="robots" content="noindex"> to it, and don't link to it from your navigation

The exact rules, with examples of URLs that pass and fail, are in HTML forms. The overview explains why the answer is a 303 and not a 302 or 200.

Questions

Stuck on a step, or want a guide for your situation? Email hello@ikiform.com.