Form Auto Saver + Reminder

Automatically saves front-end forms before they are submitted. This ensures users cannot lose their entered form data, whether they forget to submit the form, their browser freezes, they take a break from the form, or even if they switch devices.

This module will also send 1-2 reminder emails to the user, reminding them of their pending form submission and providing them with a unique URL where they can finish it. This module is provided both in ProDevTools (to use with your own forms) and with FormBuilder (to use with FormBuilder forms).

About Form Auto Saver

What’s Included

  1. The FormAutoSaver main module.

  2. The ProcessFormAutoSaver module which enables you to view forms that are in progress from within the ProcessWire admin (Setup > Forms in progress). This module also lets you send reminders manually, edit form data, or delete existing forms in progress.

  3. The FormBuilderProcessorAutoSaver module, which provides a turn-key action for using FormAutoSaver in FormBuilder forms.

  4. An email-reminder.php template file that includes instructions on how to create your own (optional) custom email reminder files. You can choose to use the same reminder for all forms, or use a different one per-form.

Requirements

  • ProcessWire 3.0.184 or newer.
  • An existing front-end form or a FormBuilder form using FormBuilder v50+.
  • jQuery is required by this module, but it will automatically insert it if not already present.
  • ProcessWire must be allowed to send email (if using email reminders).
  • If using with FormBuilder, it must be used with embed method C (the most common one).

You can use FormAutoSaver with FormBuilder or with your own front-end forms. Usage instructions for both options is described below.

Installation

  1. Copy all the files for this module into /site/modules/FormAutoSaver/.
  2. In your admin, click Modules > Refresh.
  3. Click “Install” for the FormAutoSaver module.
  4. Configure the module settings or make note of them to return to later.
  5. If using FormBuilder, also install the included FormBuilderProcessorAutoSaver module.

Note: installation will create a new menu item in your admin: Setup > Forms in progress.

Supported input types

FormAutoSaver currently remembers values for all HTML native input types except for: input[type=hidden] and input[type=file]. For input types that are primarily JS driven, support may depend on several factors. Please contact us (post in the FormBuilder or ProDevTools support board) if you have trouble getting it to work with one input type or another, as it may be possible to support with minor adjustments.

Using with Form Builder

To use with FormBuilder, you must use embed method C with a non-paginated form. (Paginated forms already have their own auto-save capabilities).

Step 1: Install the FormBuilderProcessorAutoSaver module

To use with FormBuilder, after you have installed the FormAutoSaver module, you'll want to install the FormBuilderProcessorAutoSaver module that is included here. This module serves as the connection between FormBuilder and FormAutoSaver.

Step 2: Enable the PageAutoSave action

Edit any FormBuilder form and click on the “Actions” tab. Check the box for “Form Auto Saver + Reminder for FormBuilder”. This will reveal a fieldset having the same title below. Save your form and then return to this fieldset for additional configuration settings.

Select the form field that contains the email address, as well as the form field that start trigger the auto-saving to start. Save.

On your form’s “settings” tab, ensure that you do NOT have the checkbox checked for: "Remember entered form field values on every change?" – this particular feature will complete with and interfere with FormAutoSaver, so it should be disabled when using FormAutoSaver.

Step 3: Test, customize further and finish

Now test your form on the front-end of your site (not in the preview window). Ensure that everything is working as you expect.

  • See the section further in this document on how to customize the reminder emails that get sent.
  • See the section further in this document on maintenance and CRON jobs.
  • See the FormAutoSaver module settings in your admin (Modules > FormAutoSaver) to configure how long saved form data should be remembered, when reminder emails should be sent, and more.

Using with your own front-end forms

Before using FormAutoSaver you should already have a functioning form. For example, let’s say that we have this form in HTML:

<form id='my_form_id' method='post' action='./'>
  <p><label>First name: <input type='text' name='first_name' /></label></p>
  <p><label>Last name: <input type='text' name='last_name' /></label</p>
  <p><label>Email: <input type='email' name='email' /></label></p>
  <p><label>Comments: <textarea name='comments'></textarea></label></p>
  …and so on…
  <input type='submit' name='submit' />
</form>

The following steps will describe how you can use FormAutoSaver with the form above.

Step 1: Initialization

Before rendering or processing your existing form, get the FormAutoSaver module (code example below) and provide it with the following:

  • The id attribute of your <form>
  • What field name contains the email address.
  • Optionally what field name should trigger auto-saving to start.
  • A short description of the form, i.e “Contact form”.
  • The URL where the form can be accessed.

Here's what that might look like:

// get FormAutoSaver
$fas = $modules->get('FormAutoSaver');

// set what is the id attribute of the form (required)
$fas->setFormId('my_form_id');

// let it know what field name contains the email address
$fas->setEmailFieldName('email');

// start saving after this field is populated
$fas->setStartFieldName('last_name');

// tell it what the name of this form is
$fas->setDescription('Contact form');

// tell it the URL where this form is located
$fas->setUrl($page->url);

Step 2: Render or process your form

Typically before you render a form, you have some code that checks if it has been submitted. If the form has been submitted, you process it. If the form has not been submitted (or was submitted with errors) then you render it.

How the form is processed and validated is up to you, FormAutoSaver just needs to know whether you are starting or finishing a form. When starting a form, you output the content returned by $fas->start() before the form markup. When the form has been submitted, you should call $fas->finish(). For example:

if("form is submitted and valid") {
  $fas->finish();
} else {
  echo $fas->start();
}

The start() method return the necessary Javascript to connect your form with FormAutoSaver, so its return value should be output above your form markup. The finish() method clears the auto-saved form data from the database, so that the user does not get more reminder emails about it.

You should replace the "form is submitted and valid" text with whatever conditions you use to determine the form is submitted and that all required fields are present, valid, etc.

Recap: Here's the entire example discussed above but all together, and expanded a bit:

// get FormAutoSaver and tell it what to do
$fas = $modules->get('FormAutoSaver');
$fas->setFormId('my_form_id');
$fas->setEmailFieldName('email');
$fas->setStartFieldName('last_name');
$fas->setDescription('Contact form');
$fas->setUrl($page->url);

if("form is submitted and valid") {
  // save your form submission or email it, etc.
  // then call the finish() method
  $fas->finish();
  // redirect to a thanks page (or output thanks msg)
  $session->location('/url/to/thanks/page/');
}

// output FormAutoSaver JS
echo $fas->start();

// output form
echo "
  <form id='my_form_id' method='post' action='./'>
    <p><label>First name: <input type='text' name='first_name' /></label></p>
    <p><label>Last name: <input type='text' name='last_name' /></label</p>
    <p><label>Email: <input type='email' name='email' /></label></p>
    <p><label>Comments: <textarea name='comments'></textarea></label></p>
    …and so on…
    <input type='submit' name='submit' />
  </form>
";

Step 3: Test, customize further and finish

Now test your form on the front-end of your site. Ensure that everything is working as you expect.

  • See the section further in this document on how to customize the reminder emails that get sent.
  • See the section further in this document on maintenance and CRON jobs.
  • See the FormAutoSaver module settings in your admin (Modules > FormAutoSaver) to configure how long saved form data should be remembered, when reminder emails should be sent, and more.

Customizing the reminder emails

Step 1: Copy the default email template to your own file

You can customize the default reminder email, or you can create custom reminder emails for each of your forms. To do this, you must copy the default reminder email php file out of the module’s files and into a FormAutoSaver directory in your site’s templates directory:

  • Copy the file: /site/modules/FormAutoSaver/email-reminder.php
  • To new file: /site/templates/FormAutoSaver/email-reminder.php

If you want to create a custom reminder email for a specific form, then append the form id to it like this:

  • /site/templates/FormAutoSaver/email-reminder-my_form_id.php

Note that “my_form_id” is the “id” attribute of the form, and there is no requirement that it use underscores, hyphens or lowercase. The only requirement is that it matches the “id” attribute of the form, which is also what you provided to the $fas->setFormId(…) call in the earlier examples. So if your form “id” attribute is “contact-form” then you would copy to this file:

  • /site/templates/FormAutoSaver/email-reminder-contact-form.php

If using FormBuilder: Please note that the form “id” will be “FormBuilder_form-name”, so if your FormBuilder form is named “contact” then the file will be:

  • /site/templates/FormAutoSaver/email-reminder-FormBuilder_contact.php

Step 2: Edit and customize your email template file

Whatever file you copied to, you should now open the file and edit it in your favorite text/code editor. The file contains instructions within it for modifying the email subject, from name, from email, and email body, but we'll repeat some of them here.

This file receives several variables, which are outlined below:

  • $values (array): Associative array of values from the form (entity encoded).
  • $row (array): Database row for this raw form entry (NOT entity encoded).
  • $url (string): URL to access and continue this form entry (entity encoded).
  • $httpHost (string): Current HTTP host (entity encoded).
  • $description (string): Current form description (entity encoded).
  • $reminderNum (int): 1 if first reminder, 2 if second, or 0 if sent from admin.

Below is a very simple example of a custom email reminder template file. In this case it is only using the $url variable. Note how the email subject, from email and from name are defined as data attributes in the <html> element.

<!DOCTYPE html>
<html
  data-subject="Finish your form"
  data-from="noreply@your-domain.com"
  data-from-name="Your Company">
<head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
  <title>Email reminder</title>
</head>
<body>
  <h2>Your form has not yet been submitted</h2>
  <p>If you would like finish your form please click the link below:</p>
  <p><a href="<?php echo $url; ?>">Continue</a></p>
</body>
</html>

Note: the text-only version of the email is automatically generated from the HTML version.

Please see the default email-reminder.php file for a more complete example and additional instructions. This also includes information on how to develop the reminder email for multiple-languages.

Maintenance and CRON jobs

In order to send reminder emails, the FormAutoSaver must run at regular intervals in order to complete this maintenance task. By default it will perform this maintenance when working with other live form submissions. This requires that your auto-saved forms are regularly viewed by users on your site. If your forms are rarely used or if you'd prefer a more consistent maintenance pattern, you can run FormAutoSaver maintenance from a CRON job.

To run maintenance from a CRON job, first you'll want to disable the automatic maintenance by editing the module settings in your admin (Modules > FormAutoSaver) and setting the “Run maintenance automatically?” setting to “No”.

Next, you'll want to run the FormAutoSaver maintenance() method at regular intervals (we recommend every 5 minutes). There are many ways you can do this, but in our example below, we'll use the standard and reliable unix crontab method:

Step 1: Create a script to run from CRON

Create a php script that you will execute from a CRON job. In the example below, we've created a shell script /usr/local/bin/form_auto_saver

#!/usr/bin/php
<?php namespace ProcessWire;

require('/path/to/pw/index.php'); // path to PW’s index.php file

$config->httpHost = 'www.domain.com'; // update to your site hostname
$config->https = true; // set https to true if your site uses HTTPS

if($modules->isInstalled('FormAutoSaver')) {
  $modules->get('FormAutoSaver')->maintenance();
}

Why manually set the two $config properties in the example above? Because from a shell script the hostname and scheme won't be known or applicable, so we set them manually to ensure the correct URL and scheme are used in any reminder emails that get sent.

Step 2: Make the script executable

chmod +x /usr/local/bin/form_auto_saver

Step 3: Add the script to your crontab

crontab -e

While editing crontab, add a line like the following to make it run every 5 minutes:

*/5 * * * * /usr/local/bin/form_auto_saver

Save and you are done. Test to double check that your reminder emails are working at the interval you configured.

Viewing forms in progress

You can view forms in progress using the ProcessFormAutoSaver module, which can be accessed in your admin from: Setup > Auto Saved Forms.

What information is shown

For each form in progress, you'll see the following:

  • auto-save ID number
  • a description of what form it is for
  • the email address of the person working on the form
  • when the form was started
  • when the form was last updated
  • when the last reminder email was sent

Actions you can perform

You can click on the "description" to view the live form submission in progress (in a modal window). Avoid making changes to the user's form, as your changes will also be auto-saved.

If using FormBuilder, avoid viewing a form in progress that the user might have open in their browser, as this can interfere with the CSRF/session tracking.

Each form in progress (aka "entry") has a checkbox which can be used to delete an entry or manually send a reminder to the user. You'll see buttons for "Delete checked" and "Remind checked" which correspond to these checkboxes.

Twitter updates

  • Introduction to an invoice application profile being built in ProcessWire: More
    30 September 2022
  • Stumbling upon a really nice ProcessWire-powered website, plus core updates including API improvements for ProcessWire forms— More
    9 September 2022
  • Useful new dot-and-bracket syntax options added for page.get() method— More
    2 September 2022

Latest news

  • ProcessWire Weekly #438
    In the 348th issue of ProcessWire Weekly we're going to cover the latest weekly update from Ryan, take a closer look at a couple of new third party modules, and more. Read on!
    Weekly.pw / 1 October 2022
  • Multi-language field translation export/import
    In this post we cover the details of a new module that enables export and import capabilities for multi-language fields in ProcessWire.
    Blog / 5 August 2022
  • Subscribe to weekly ProcessWire news

I just love the easy and intuitive ProcessWire API. ProcessWire rocks!” —Jens Martsch, Web developer