Skip to main content

Workflows

Introduction​

A workflow is something that happens after a submission: an email, a webhook call, or a push to a mailing list or CRM. Each form has its own workflows, on its Workflows tab, and each runs only when its conditions hold.

Creating a workflow​

Choose Add Workflow on the form's Workflows tab. A workflow has:

Setting
NameFor you. Shown in the log.
EnabledA switched-off workflow does not run.
EventSubmission Created, Submission Updated (an edit from the control panel, or a visitor editing through submission_handle=), Submission Created or Updated, Submission Status Changed (see below), Draft Saved (a visitor saved the form to finish later) or Draft Reminder (a saved draft has waited the form's reminder days) or Submission Action (someone ran one of the form's submission actions). See Save and resume.
ActionSend an email, Call a webhook or Send to a connection.
ConditionsOptional. The workflow runs only when they hold for the submitted answers, using the same condition builder as fields.

Workflows receive every answer, including real file ids for uploads, even when the form does not store submissions or their data. A form with storage turned off is a workflows only form.

When a status changes​

Submission Status Changed runs when someone moves a submission to another status on its control panel page, or a submission action moves it. Use it to tell the person who submitted that their application was approved, or to push an accepted lead to a CRM.

Pick which move with conditions: Status is the status it has now, and Previous status is the one it had. "Status is Approved" runs on any move to Approved; add "Previous status is Pending" to run only from Pending.

The same save also runs Submission Updated workflows, first. Submission Created or Updated workflows run once for that save, not twice. The Run workflows switch on the submission's page silences both.

Send an email​

Setting
RecipientsAny number of rows, each delivered as To, Cc or Bcc: a typed address, a member, every member of a role, or a form field.
From name, From email, Reply-to, SubjectA blank From uses the site's webmaster name and address, and a blank Subject uses the form's name. The subject, the From name and Reply-to can include answers with {field:HANDLE}, so replying to a notification can go straight to the person who submitted: set Reply-to to {field:email}. Only valid addresses are kept (up to five), and Reply-to is left off when none is. The From email is always a fixed address, because mail sent "from" a visitor's address is usually rejected as spoofed.
MessageOne of the email theme's messages, such as Submission, which lists every answer, or text written on the workflow.
Use the email layoutWrap the message in the email theme's _layout.
Attach uploaded filesAttach the files uploaded with the submission.
AttachmentsFiles from ExpressionEngine's file manager to attach to every email this workflow sends, such as a brochure.

A form field recipient only sends to an address the field can safely resolve to. Otherwise anyone who submits the form could make your site email any address. The field must be one of:

  • an option field whose choices come from Recipients, where each choice has addresses that never reach the page;
  • an option field whose choices are Members;
  • a field with Allow as Workflow Recipient turned on, such as a "send me a copy" email field. Turn that on only where you mean it.

See Email notifications for a worked example.

Call a webhook​

Posts the submission as JSON to a URL.

Setting
URLWhere to post.
SecretOptional. When set, each request carries an X-Formidable-Signature header: the HMAC-SHA256 of the request body, keyed with the secret.
What to sendAny of: the form (id, handle, name), the submission (id, status, member id, date), the answers, and the member who submitted. The event name is always sent.
Member detailsWhich member fields to include, when the member is sent: username, screen name, email address, primary role, join date, and custom member fields.
Leave out of the answersAnswers not to send, such as anything sensitive the receiving service does not need.

To check a signature, compute the HMAC of the raw request body with your secret and compare it with the header in constant time:

webhook-receiver.php
<?php
$body = file_get_contents('php://input');
$expected = hash_hmac('sha256', $body, getenv('FORMIDABLE_WEBHOOK_SECRET'));
$given = $_SERVER['HTTP_X_FORMIDABLE_SIGNATURE'] ?? '';

if (! hash_equals($expected, $given)) {
http_response_code(401);
exit;
}

$payload = json_decode($body, true);
// $payload['event'] is always present; the rest depends on "What to send".

Send to a connection​

Pushes the submission to a third-party service through a saved connection: a mailing list or a CRM.

Setting
ConnectionWhich saved connection to use.
TargetThe list, audience or object at the provider, where the provider needs one.
MappingWhich form field fills which of the provider's fields.

Map form fields to email, name, first_name, last_name, phone and company, and each provider translates them into its own field names, so one mapping works with any provider. Any other key is sent as that provider's own custom field, named exactly as the provider knows it.

Reading the results​

Every run is recorded, with what it sent and what came back. A form's Workflows tab switches between three views:

  • Simple: a table of the form's workflows, each with when it runs, what it does and to whom, whether it has conditions, how its last run went, and whether it's on. Click a name to edit it.
  • Detailed: each workflow written out in words, conditions and all.
  • Recent runs: the latest runs, filterable by result, with a link to the full log. The tab shows a red dot when a workflow's most recent run failed.

To run workflows in the background with retries, add a queue. Both are covered in The workflow log and queue.

Workflows › Simple · Screenshot: ExpressionEngine 7.5.26, demo data

For developers​

Formidable calls hooks at each step: formidable_workflow_should_run to veto a workflow, formidable_workflow_email, formidable_webhook_payload and formidable_connection_payload to change what's sent, and formidable_workflow_complete after each run.