Skip to main content

Save & Continue Later

Freeform includes a Save & Continue Later feature which allows your users to securely save their form progress and immediately continue or come back later to complete it.

Overview

Inside the form builder you can toggle the Save feature for the Submit buttons. It can then be configured with a special email notification as well as where the user is returned to once they click that button. These will offer you full control over instructions to the user about how to return and complete the form (including a URL with special token/key) and the amount of time they have to complete it before it expires (configurable).

All saved form progress submissions are stored in a separate encrypted database table. When a user clicks the Save button, all field validation is circumvented. Other validation such as spam protection measures still apply.

Configuration

The Save feature can be enabled or disabled for each form page by toggling the Save setting inside the Submit button, and can each have separate configuration including button label and email notification template. For example, you can optionally choose different return paths/email notification templates that could be customized based on the progress on the form (e.g. "Thanks for starting your application!", "You're almost done...", "Thanks for completing the first 3 steps...", etc).

Submit buttons are handled automatically by Freeform. They are automatically inserted at the end of your form in the form builder.

  • Button Label - defaults to Save.
  • Return URL - where the user should be returned to if they click the Save button.
    • Special token and key variables are available to include in the return path.
    • The return URL would be wherever you like, and fully customizable. This is where you'd include instructions to the user including a URL for where to return to complete the form later.
  • Target Email field (optional) - the Email field that will contain the user's email address in order to send the email notification.
    • If the user hasn't yet filled out an email address and the field is NOT required, the email notification attempt will be suppressed. If the email address field is marked as required, the form will run through regular field validation until it contains a valid value. A good way around this would be to have the first page include basic info like name and email and/or no option to save the form until the second page.
    • Email Notification Template - the email notification sent to the user if they click the Save button.
      • Choose a special Freeform email notification template.
      • The message of this email notification is completely customizable, but be sure to include instructions to the user including a URL for where to return to complete the form later.
      • The following special variables are available for this email template:
      {{ token }} - the session token
      {{ key }} - the form submission key

There are also 2 general settings specific to the Save & Continue Later feature:

  • Number of Days to Keep Saved Form Data - the number of days to store saved form progress in the database before clearing.
  • Maximum Number of Saved Forms Per Session - the maximum number of saved forms per session (per user, though it's possible a user may have multiple sessions when returning to the site over a span of several days). Default is 10, which should be a comfortable and reasonable number. Once the maximum has been reached, Freeform will begin overwriting existing older entries to create new ones.

Templating

Controlling the format for submit buttons is now done through the new buttons namespace available in the Template Overrides feature.

{{ form.render({
buttons: {
attributes: {
container: { ... },
column: { ... },
buttonWrapper: { ... },
submit: { class: "form-field-button blue" },
back: { class: "form-field-button gray" },
save: { class: "form-field-button blue" },
},
submitLabel: "Send",
backLabel: "Previous",
saveLabel: "Save",
}
}) }}

You may also override the Return URL for the Saving feature by specifying the savedFormRedirect parameter at template level:

{% set submissionToken = craft.app.request.getQueryParam('session-token') %}
{% set submissionKey = craft.app.request.getQueryParam('key') %}

{{ freeform.form("yourFormHandle").render({
savedFormRedirect: '/apply/form-save?&session-token={token}&key={key}',
savedSession: {
key: submissionKey,
token: submissionToken,
},
}) }}

If savedSession does not contain a valid key and token, the form will just render a fresh copy of the form with no saved data present and work as usual. This means that you don't necessarily need to have a unique template page to handle the continuation part.

How to Use

The general flow for making use of this feature is to have a "success" page specifically designed to educate and inform the customer about what happens next. This success page would likely have instructions as well as a link to where the form can be continued (making use of the unique submission token and key).

1

Create the 'Success' Template

Create a brand new template that contains something along the lines of this:

{% set submissionToken = craft.app.request.getQueryParam('session-token') %}
{% set submissionKey = craft.app.request.getQueryParam('key') %}

<h3>Progress Saved!</h3>
<p>
Your form progress has successfully been saved! Whenever you're ready to
complete the form, please return by visiting this URL:
</p>
<p>
<a
href="{{ siteUrl }}apply/form-save?session-token={{ submissionToken }}&key={{ submissionKey }}"
>
{{ siteUrl }}apply/form-save?session-token={{ submissionToken }}&key={{
submissionKey }}
</a>
</p>
2

Create a 'Continue' Template

It's entirely possible to resuse the existing template structure and path, but to make this as clear as possible, we'll create an extra page template to handle this. This form will contain a new parameter called saveSession to handle the Save & Continue Later feature. It'll be located at /apply/form-save and contain something like this:

{% set submissionToken = craft.app.request.getQueryParam('session-token') %}
{% set submissionKey = craft.app.request.getQueryParam('key') %}

{{ freeform.form("yourFormHandle").render({
savedSession: {
token: submissionToken,
key: submissionKey,
},
}) }}

Just like above in step 1, this example assumes that you will be passing the token and key into the URL as a query with session-token and key. This can be done in a variety of other ways if you wish.

If you wish to conditionally display an error message and/or display the form only if the session is valid, you can include a check on savedSessionLoaded, as follows:

{% set submissionToken = craft.app.request.getQueryParam('session-token') %}
{% set submissionKey = craft.app.request.getQueryParam('key') %}

{% set form = freeform.form("yourFormHandle", {
savedSession: {
key: submissionKey,
token: submissionToken,
}
}) %}

{% do form.registerContext %}
{% if form.propertyBag.get('savedSessionLoaded') %}
{{ form.render() }}
{% else %}
<div class="warning">
<h4>This session is invalid.</h4>
</div>
{% endif %}
3

Create an Email Notification template

Create a brand new email notification template so that this feature can send an email notification to the user with instructions on how to continue later. This is optional. Keeping with the examples in the steps above, be sure to match the URL structure and link to the template you just created in Step 2:

<h3>Progress Saved!</h3>
<p>
Your form progress has successfully been saved! Whenever you're ready
to complete the form, please return by visiting this URL:
</p>
<p>
<a href="{{ siteUrl }}apply/form-save?session-token={{ token }}&key={{ key }}">
{{ siteUrl }}apply/form-save?session-token={{ token }}&key={{ key }}
</a>
</p>

Just like above in step 1, this example assumes that you will be passing the token and key into the URL as a query with session-token and key. This can be done in a variety of other ways if you wish.

4

Set up the Form

  • Inside the form builder click on the Submit button field row.
  • Toggle ON the Save Button setting.
  • Edit the label as you wish, and then set the return URL to wherever you have your success/info page set up. Continuing from the steps above, let's assume the Continue page location is located at /apply/form-save and is looking for a query in the URL with session-token and key, e.g.:
    /apply/form-save?form={{ form.handle }}&session-token={token}&key={key}
  • You may include the {token} and {key} variables as well as form variables, e.g. form.handle, etc.
  • Select an Email field type in the Target Email Field dropdown setting (optional).
    • Then select the email notification template you just created in Step 3.

Repeat this for all pages you'd like to have the ability to save progress on.

5

User Flow

Let's pretend you have a 6-page form and have added the Save buttons to all of the pages.

  • The user begins filling out the 6-page form.
  • Once they make it to page 3, they decide to save the form and continue later, so they click on your Save & Continue Later button.
  • The form skips validation for that page, but saves the existing data on that page including the progress of previous pages.
  • Freeform generates a special submission entry in the database for the token that will be used. It will encrypt all data with the generated key + server secret and store it in the database.
  • It then redirects the user to the Return URL specified in the form builder (or overwritten with savedFormRedirect parameter at template level), which should include a token and key. Continuing the example, the return URL would look like /apply/form-save?&session-token=TOKEN&key=KEY, the return/success page noted in Step 1 would be presented.
  • If configured, the user will also receive an email notification with instructions and a link with the token and key to come back to finish the form later.
  • The user would need to take note of this special URL or hang on to the email notification they received.
  • For the user to resume the form, they would visit that special URL.
6

View ActivityNew in 5.9+

To see how many active saved form submissions exist for each form, navigate to the Card view in the Forms Dashboard. Any forms with submissions that have saved progress will be displayed as a statistic on the card.

Caveats

Spam Protection Behavior

The Save & Continue Later feature still respects most spam protection, but because the form is being saved instead of submitted, behavior may differ slightly.

When a user attempts to Save a form:

  • 🟢 reCAPTCHA v2 Checkbox / Invisible
    • If the check is not completed, Freeform will still allow the form to be saved.
    • The user must pass reCAPTCHA before the form can be fully submitted.
  • 🟡 Honeypot
    • If the honeypot field contains a value, Freeform will bypass saving and run normal validation.
    • If validation errors exist, they are shown to the user.
    • If there are no validation errors, the submission is treated as spam.
    • On multi-page forms, the form may simply advance to the next page.
  • 🟡 reCAPTCHA v3
    • If the score fails, saving is bypassed and normal validation runs.
    • If there are no validation errors, the submission is treated as spam.
    • If the check passes, saving works normally.
  • 🟡 Minimum Submit Time
    • If the form is saved too quickly, saving is bypassed and normal validation runs.
    • If the minimum time is later met, saving will work.
  • 🔴 Blocked Email, Keywords, or IP
    • If any block rules are triggered, saving is bypassed and the submission is treated as spam.
  • 🔴 Form Submit Expiration
    • If the maximum submit time has passed, saving is bypassed and the submission is treated as spam.

Other Considerations

Some features have limitations when using Save & Continue Later.

  • 🟢 Uploaded Files
    • Only the File Upload Drag & Drop field type fully supports saved forms.
    • Standard file inputs cannot restore previously selected files due to browser restrictions.
    • When using saved forms, uploaded files are preserved until the saved form expires based on the Number of Days to Keep Saved Form Data setting.

    Changing this setting will not retroactively affect existing uploaded files.

  • 🟡 Stripe Payments
    • If a Stripe Payment Element field is on the page:
      • Stripe may require valid payment fields before saving.
      • Payment details are not saved with the form.
      • Saving after entering payment details may still process the payment.

      Recommendation: Place payment fields on the last page and disable saving on that page.

  • 🔴 Editing Submissions
    • Saving progress is not supported when editing existing submissions.
    • Attempting this will create a duplicate submission.