Form submission redirects in Statamic

Published November 14th, 2023

I’ve been doing a heap of work across a number of projects in the area of front end forms in Statamic websites. Over the last couple of months, Forms have seen some incredible features come through, most notably the ability to use the Blueprint “sections” to help create multi-page forms with ease, and also the Spacer fieldtype to force spacing to better control form widths and layout.

But I still needed a little bit more, and have had four PRs merged in to Statamic’s core: two are minor tweaks that make working with forms and fields easier (and more efficient), but also two rather cool ones – one for runtime data at render time (there’s another blog post in me about that one, so stay tuned), and one for submission-specific form redirects – and this is the one we’ll look at today.

Out of the box, the form tag in Statamic supported the idea of redirecting on submit to another page – which is great for a simple “thank you” page, but this has two issues:

  1. If you’re using JavaScript to submit your form, there is no support for redirects, and

  2. The “thank you” page or URL is static, and has no knowledge of the submission data that was posted

In one project, I extended Statamic’s internal form workings to resolve both of these – but extending so much of Statamic’s internals isn’t really good long-term (especially with the number of private methods that needed to be verbatim copied in to the extension) – if Statamic were to change these, they could down this project.

After this project, there were two more tasks on the radar that needed redirects too, each to a different target. So I had a need for something, have the skill to extend Statamic to do this, and the knowledge that the Statamic core team are awesome at working with the community (and accepting PRs). Given the scale and number of approaches, after a quick chat with Jason to ensure these ideas still remained in Statamic’s core scope, a PR was started. It shifted its shape through the review process (with Jason’s streamlining) but has been merged, and now we can have submission-specific redirects.

To use redirects, you’ll need to be running Statamic 4.25 or later.

Register a redirect

Within one of your service providers, simply define your redirect on the Form facade: 

1use Statamic\Facades\Form;
3public function boot()
5 Form::redirect('contact', function ($submission) {
6 return ''.$submission->get('email_address');
7 });

This requires a form’s handle, and a callback that receives the Submission object. From the Submission, you have access to the submitted data, and through this, the Form itself. 

You can use the $submission->get('field_handle') to values for specific fields within your Submission - such as email_address above.

You can get the Form with $submission->form() which in turn opens up possibilities with its Blueprint too – but more on that later in the Advanced Redirects section below.

And that’s all you need to do. When a form is submitted matching the handle, in the above example, the “contact” form, the callback will be run, and will return the redirect URL. Statamic will then handle the redirect.

If you need to conditionally redirect – i.e. redirect on a specific form only sometimes, you can return:

  • a string of the redirect URL, when you need to redirect, or

  • null, when you do not want to redirect

Statamic’s FormController will behave appropriately based on the return value of your callback – null to cancel any redirect, or a URL (as a string) to perform a redirect.

Handling the redirect

Forms in Statamic can be submitted either via AJAX and JavaScript, or by a standard server-side POST request.

This new redirect feature supports both methods.

For JavaScript submissions (AJAX)

Using JavaScript to submit your form (in other words, AJAX), you need to update your JavaScript to handle the redirect yourself.

The response from Statamic now includes a redirect property in its response – and if this has a value, then Statamic has provided you with the redirect target. Use this to do the redirect in your JavaScript and you’re good to go.

For standard POST requests (non-JavaScript)

There’s nothing special you need to for your redirect to kick in: if Statamic finds a redirect for your form, the redirect will take place automatically from the server.

Advanced redirects (aka wildcard redirects)

Now this is cool, but first we need to look at the FormController source to look at the workflow when a submit request is made. Check out the source to follow along, but the basic order of our success path is:

  1. Validate the request,

  2. Dispatch the FormSubmitted event,

  3. Save the submission

  4. Call the formSuccess method, which

  5. Gets a redirect for the submission, if one exists

  6. Returns the JSON response with the redirect property (for AJAX) or handles the redirect (for server-side POST)

Now the really important bit to note here is that the FormSubmitted event is dispatched before the redirect is generated. This means that we can do something in a listener for the FormSubmitted event that can add a redirect for any Statamic form at runtime.

OK, sounds weird, why would all forms need this? Hear me out…

We’ve just created a new fieldtype (currently being reviewed before release, so stay tuned) for frontend forms that allows a Form submission to collect properties to send and redirect to Stripe.

Because this is a fieldtype that a user could add to any Statamic Form, we can’t get the user to write code in a service provider to handle the redirect. So we need some sort of wildcard. And that’s what we can do here.

For this particular use case, we only need to have a redirect if the Form’s Blueprint includes a specific fieldtype – but you could also do this based on a field handle or a field value too. In our listener, we get our Submission object that gives us all of the submitted data, as well as a reference to the Form it belongs to – all the pieces we need to hook in for a wildcard check.

For this addon, we needed to check the existence of a fieldtype, and we wrote a little helper that check’s the Submission’s Form’s Blueprint for the fieldtype to exist – and returns either true or false. When true, we can the programmatically register a redirect for that Submission’s Form.

1use Statamic\Facades\Form;
2use Statamic\Fields\Field;
3use Statamic\Forms\Submission;
5public function handle($event): void
7 // does the form contain a specific fieldtype?
8 $hasFieldtype = $event->submission->form()->blueprint()
9 ->fields()
10 ->all()
11 ->contains(fn (Field $field) => $field->type() === 'my_fieldtype_to_require');
13 // if we have the fieldtype, let's configure a redirect
14 if ($hasFieldtype) {
15 Form::redirect($event->submission->form()->handle(), function (Submission $submission) {
16 // build the redirect URL - to Stripe, to PayPal, to some other URL...
17 });
18 }

If the Statamic CP user create a new form, and uses the same fieldtype (that works with redirects), this approach means that the redirect will take place, even without having explicit code written for that specific form.

Neat, hey?

As I write this, I’ve also finished work on two more addons, one which relies on this new redirect feature. Jason’s tweaks to the redirect implementation in my original PR make this so beautiful to work with, and really opens up the scope and possibilities for how to use Statamic forms on the frontend of your website, and easily hook in to third party systems such as Stripe.

You may be interested in...