A newer version of

Freeform

is available.

Try Freeform 5 now →

User Guides

Success Return URL on Forms

Freeform offers a wide variety of ways to handle the success return on forms. Check out the list below to see all available options and how to use them.

Available Options

Through the Form Builder

If you wish to offer flexibility and control to your clients for setting the Return URL, this can be set inside the form builder for each form.

INSTRUCTIONS

  1. Open up the form inside the form builder.
  2. Go to the Form Settings tab (on the right).
  3. Inside the Return URL setting, add the path you want Freeform to return the user to upon success.
    • You can also use the following (wrap with {{ and }}):
      • form.handle - handle of the form.
      • submission.token - the secure token created for the submission.
      • submission.id - the newly created unique submission ID in the URL. This (and submission.token) would allow you to use the Submissions query to display some or all of the users' submission on the success page.

EXAMPLE

Setting Return URL through form builder

IMPORTANT NOTES

  • This approach can easily be overwritten by any template parameters. As soon as the template level returnUrl parameter is specified, Freeform will ignore the value set inside the form builder.
  • This approach will not immediately work with AJAX. When AJAX is enabled, Freeform will by default stay on the same page and just show a success banner. To have Freeform perform a redirect to the return URL specified in the form builder upon successful AJAX submit, you'll need to add some JS to your page template. See example below:







 
 
 
 
 
 
 
 
 
 
 
 
 
 
 




<html>
<head>
</head>
<body>

    {{ craft.freeform.form("myFormHandle", {id: 'my-form'}).render() }}

    <script>
      // Find the form element
      const myForm = document.getElementById('my-form');
      // Do something on a successful ajax submit
      myForm.addEventListener('freeform-ajax-success', function(event) {
        // Redirect the user
        if (event.response.finished) {
          window.location.href = event.response.returnUrl;
        }
      })
      myForm.addEventListener("freeform-render-success", function (event) {
      // Stop the default success message rendering
        event.preventDefault();
      });
    </script>

</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

If you'd like something that is not specific to a single form, you can use document instead:








 
 
 
 
 
 
 
 
 
 
 
 
 




<html>
<head>
</head>
<body>

    {{ craft.freeform.form("myFormHandle", {id: 'my-form'}).render() }}

    <script>
      // Do something on a successful ajax submit
      document.addEventListener('freeform-ajax-success', function(event) {
        // Redirect the user
        if (event.response.finished) {
          window.location.href = event.response.returnUrl;
        }
      })
      document.addEventListener("freeform-render-success", function (event) {
      // Stop the default success message rendering
        event.preventDefault();
      });
    </script>

</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

At Template Level

If you wish to set the Return URL at template level, whether you're doing this to include a dynamic segment in the return URL, etc, you can do so by specifying the returnUrl parameter on the Form query or the form object.

{{ form.renderTag({returnUrl: "contact/success"}) }}
1

INSTRUCTIONS

  1. Open up your page template.
  2. Inside the Form query or the form object, add the returnUrl: "contact/success" parameter.
    • You can add most variables such as form.handle, submission.id, submission.token as well as perform conditional checks, etc:
      returnUrl: "{{ siteUrl }}freeform-demo/bootstrap/{{ form.handle }}/{% if submission %}submissions/{{ submission.id }}/{% endif %}success"
      
      1

EXAMPLE







 






<html>
<head>
</head>
<body>

    {{ craft.freeform.form("myFormHandle", {
        returnUrl: "contact/success",
        id: 'my-form'
    }).render() }}

</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12

IMPORTANT NOTES

  • This approach overrides anything set inside the form builder.
  • This approach will not immediately work with AJAX. When AJAX is enabled, Freeform will by default stay on the same page and just show a success banner. To have Freeform perform a redirect to the return URL specified in the parameter upon successful AJAX submit, you'll need to add some JS to your page template. See example below:






 



 
 
 
 
 
 
 
 
 




<html>
<head>
</head>
<body>

    {{ craft.freeform.form("myFormHandle", {
        returnUrl: "contact/success",
        id: 'my-form'
    }).render() }}

    <script>
        // Find the form element
        const myForm = document.getElementById('my-form');
        // Do something on a successful ajax submit
        myForm.addEventListener('freeform-ajax-success', function(event) {
          // Redirect the user
          window.location.href = event.response.returnUrl;
        })
    </script>

</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

Advanced Options

Returning Submit to Same Page

Aside from the obvious of using AJAX, you can achieve this by adding a query in the success URL instead of an additional segment, etc.

 
 
 


 






{% if craft.app.request.getQueryParam('success') == 1 %}
  <div class="callout success">Your message has been sent.</div>
{% endif %}

  {{ craft.freeform.form("contactForm", {
      returnUrl: "/contact?success=1",
      submitClass: "button",
    }
  ).render() }}

{% endif %}
1
2
3
4
5
6
7
8
9
10
11

Or a different option, simply redirecting to /contact?success:

{% set successParam = craft.app.request.getParam('success') %}
{% if successParam is not null %}
  <p>Success!!</p>
{% endif %}
1
2
3
4

And in case you're looking for a dynamic way of setting a return URL with combining several segments:

{% set returnUrlPath = siteUrl ~ "get-quote/" ~ craft.app.request.getSegment(2) ~ "?success=1" %}
1

Forcing a different Success URL on AJAX forms

Once using AJAX with your forms, Freeform will ignore any Return URL value you have set for the form inside the form builder as well as the returnUrl parameter. Only once you add some additional JS overrides using Freeform's Javascript handling will it begin to work that way:







 



 
 
 
 
 
 
 
 
 




<html>
<head>
</head>
<body>

    {{ craft.freeform.form("myFormHandle", {
        returnUrl: "contact/success",
        id: 'my-form'
    }).render() }}

    <script>
        // Find the form element
        const myForm = document.getElementById('my-form');
        // Do something on a successful ajax submit
        myForm.addEventListener('freeform-ajax-success', function(event) {
          // Redirect the user
          window.location.href = event.response.returnUrl;
        })
    </script>

</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

Customizing the AJAX Success Message

The built-in AJAX functionality lets you completely customize the way your forms work if you're not satisfied with anything in the provided defaults. If you only need to customize the error messages, you can do so by overriding the defaults like this:

Apply to ALL forms on the page











 
 
 
 
 
 
 
 




<html>
<head>
</head>
<body>

    {{ craft.freeform.form("myFormHandle", {
        returnUrl: "contact/success",
        id: 'my-form'
    }).render() }}

    <script>
        // Change success and error messages for all forms on this page
        document.addEventListener('freeform-ready', function(event) {
            // Customize the error and success messages
            event.options.successBannerMessage = 'My custom success message';
            event.options.errorBannerMessage = 'My custom error message';
        });
    </script>

</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

Apply to a specific form











 
 
 
 
 
 
 
 
 
 




<html>
<head>
</head>
<body>

    {{ craft.freeform.form("myFormHandle", {
        returnUrl: "contact/success",
        id: 'my-form'
    }).render() }}

    <script>
        // You can also add this only to a specific form, by listening to the
        // "freeform-ready" event on the specific form.
        const form = document.getElementById('my-form');
        form.addEventListener('freeform-ready', function (event) {
            // Customize the error and success messages
            event.options.successBannerMessage = 'My custom success message';
            event.options.errorBannerMessage = 'My custom error message';
        });
    </script>

</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

Display alternate Success markup from a Template or Existing Div after AJAX Submit

When using the Freeform built-in AJAX feature, if you wish to override the default AJAX success message and instead load alternate success markup from a template or existing div, follow the instructions below:

From Existing Div

Create a new form or edit an existing one as usual. Be sure to check off the Enable AJAX checkbox inside the form settings area in the form builder.

Add a div to hold the success contents inside your existing template that contains the form, e.g. custom-content:

<div id="custom-content">
    <h3>Thank you!</h3>
    <p>
        We have received your submission. You may now
        <a href="{{ siteUrl('path-to/file.pdf') }}">download the PDF guide</a>.
    </p>
</div>
1
2
3
4
5
6
7

Wrap your existing form render with a div to make it easier to swap out with the custom success div, e.g. form-wrapper:

<div id="form-wrapper">
    {{ craft.freeform.form('myContactForm').render }}
</div>
1
2
3

In the footer of the template that will contain the form, be sure to include something like this in the footer area:

<script src="https://code.jquery.com/jquery-3.5.1.js"></script>
<script type="text/javascript">
    document.addEventListener('freeform-render-success', function (event) {
        // Disable the default success rendering
        event.preventDefault();
        // We locate the 'form-wrapper' DIV element which contains our form
        // and we swap its contents (the whole form) with the HTML that we
        // fetch from any other element already present on the page
        $('#form-wrapper').html($('#custom-content').html());
    });
</script>
1
2
3
4
5
6
7
8
9
10
11
Finished!

From a Template

Create a new form or edit an existing one as usual. Be sure to check off the Enable AJAX checkbox inside the form settings area in the form builder.

Create a new template to hold the success contents, e.g. named ajax-success.html with content of:

<h3>Thank you!</h3>
<p>
    We have received your submission. You may now
    <a href="{{ siteUrl('path-to/file.pdf') }}">download the PDF guide</a>.
</p>
1
2
3
4
5

Wrap your existing form render with a div to make it easier to swap out with the success template, e.g. form-wrapper:

<div id="form-wrapper">
    {{ craft.freeform.form('myContactForm').render }}
</div>
1
2
3

In the footer of the template that will contain the form, be sure to include something like this in the footer area:

<script src="https://code.jquery.com/jquery-3.5.1.js"></script>
<script type="text/javascript">
    // Find the form element, can be a specific ID or just look for any forms
    var form = $('form[data-id]');
    form.on('freeform-render-success', function (event) {
        // Disable the default success rendering
        event.preventDefault();
        // We locate the 'form-wrapper' DIV element which contains our form
        // and we swap its contents (the whole form) with the HTML that we
        // fetch from the "/freeform-demo/ajax-success" template
        $('#form-wrapper').load('/freeform-demo/ajax-success');
    });
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
Finished!

User Chooses Return URL

If you wish to have the return URL based upon the user's form selection, etc, you can override the return URL manually with a hidden field or checkbox, etc named formReturnUrl, allowing for a more dynamic return URL dependent on the user's choice or action, as long as you hash the value.

Some examples of this might be:

  • Having the form return to a different page if Field X contains Y.
  • Providing a single checkbox that, when checked, returns them to a different URL.
  • Providing a series of options in a radio or select field that contain different return values.

Please keep in mind that if you're wanting to make the return path dependent on another field selection, or if you wish to know which "return option" the user chose, using the formReturnUrl field does NOT collect and store the data selection. In this case, you would be best to use a real Freeform field to collect the data, and then implement your own custom JS that calculates and/or copies another field's option values and inserts a return URL into the formReturnUrl hidden field accordingly.

If you're using an automated rendering of the form, you'll need to consider how and where to add this into the formatting template. In most cases it might be best to add a conditional and pair this with the submit button or another field.

EXAMPLES

Hidden field

<input type="hidden" name="formReturnUrl" value="{{ 'whatever/my-url'|hash }}" />
1

Checkbox field

<label for="return-checkbox">
    <input type="checkbox" name="formReturnUrl" id="return-checkbox" value="{{ 'whatever/my-url'|hash }}" />
    Some descriptive text about this checkbox
</label>
1
2
3
4

Select field

<label for="return-select">
    Please choose...
</label>
<select name="formReturnUrl" id="return-select">
    <option value="{{ 'whatever/my-url'|hash }}">Option One</option>
    <option value="{{ 'whatever/my-other-url'|hash }}">Option Two</option>
    <option value="{{ 'whatever/something-else'|hash }}">Option Three</option>
</select>
1
2
3
4
5
6
7
8