> For the complete documentation index, see [llms.txt](https://kb.craftformswp.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://kb.craftformswp.com/documentation/form-building/flows.md).

# Flows

A flow is a set of steps that run one after another, with branches. Where a form's Submit Actions always run the same list from top to bottom, a flow can make decisions: "if the visitor chose *Weddings*, add them to Mailchimp and email the events team, otherwise just email the salon". You build it on a canvas, step by step, and then point one or more forms at it.

Flows can also start from a **WooCommerce order** instead of a form, for example "when an order is completed, send our own branded email with the order's items and attach an invoice PDF", and can switch off the WooCommerce email they replace so customers don't get two.

<figure><img src="https://97821998-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FM2yV1foUgoGHBC66VBDw%2Fuploads%2FyjGqpZvFtQB7j7QuuIuT%2FSCR-20261002-pmhs.png?alt=media&amp;token=cff3b7a3-3c3a-4b24-8138-60e091ff28e0" alt=""><figcaption><p>A CraftForms flow with a condition and two branches on the canvas</p></figcaption></figure>

### What you need <a href="#what-you-need" id="what-you-need"></a>

* **CraftForms PRO.** Flows are a PRO feature. In the free version there is no **Flows** page and no Flow picker in the form editor.
* **WooCommerce** only if you want flows that start from WooCommerce orders. Form flows work without it.
* An administrator or shop manager account (see [Who can use Flow](#who-can-use-flows)).

Forms that don't use a flow keep working exactly as before. A flow is always optional.

### How a flow is built <a href="#how-a-flow-is-built" id="how-a-flow-is-built"></a>

Every flow has:

* **One trigger**, the step at the top that decides when the flow starts. It's added for you when you create the flow and can't be deleted, only changed. There are two:
  * **Form submitted**: runs when a form that uses this flow is submitted.
  * **WooCommerce order**: runs for WooCommerce orders, when one is placed or changes status. It doesn't depend on any form.
* **Steps** below the trigger, of two kinds:
  * **Action**: does something: sends an email, generates a PDF, sends a webhook, adds a contact to Mailchimp, and so on. These are the same actions you know from a form's Submit Actions, with the same settings.
  * **Condition**: checks something and splits the flow into **Yes** and **No**.
* **Connections** between the steps. Each action has two exits: **Next** (it worked) and **If it fails**. Each condition has **Yes** and **No**.

Two branches can lead into the same step. That step still runs only once, the first time the flow reaches it. A step can't loop back to an earlier step.

### Create a flow <a href="#create-a-flow" id="create-a-flow"></a>

1. Go to **CraftForms → Flows** and click **New flow**.
2. Give it a **Name**, for example "Wedding enquiry routing".
3. Under **Starts when**, choose **Form submitted** or **WooCommerce order**.
4. For a form flow, you can pick a **Reference form (optional)**. It only fills the field pickers while you build, so you can choose "Which service?" from a list instead of typing field names. Any form can use the flow later, whichever form you pick here.
5. Click **Create & open**. The editor opens with the trigger already on the canvas.

<figure><img src="https://97821998-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FM2yV1foUgoGHBC66VBDw%2Fuploads%2FVmTv94I1znoEq9dKi3vi%2FSCR-20261002-pmwc.png?alt=media&amp;token=1e676910-5649-420e-8c9a-66f96daa50a6" alt=""><figcaption><p>Creating a new flow in CraftForms</p></figcaption></figure>

**Tip:** You can set or change the reference form later. Double-click the trigger (or select it and click **Trigger settings**). While no reference form is set, the left panel reminds you: *"Tip: pick a reference form on the trigger so field pickers list its fields."*

### Add steps <a href="#add-steps" id="add-steps"></a>

The left panel, **Add a step**, has two items: **Action** (*Email, Mailchimp, webhook…*) and **Condition** (*Split into Yes / No*). There are two ways to add them:

* **Click** an item. The new step goes below the step you have selected and is connected to its first free exit. On a condition, the first new step goes on **Yes** and the next one on **No**. On an action, the first goes on **Next** and the next one on **If it fails**.
* **Drag** an item onto the canvas to drop it exactly where you want. A dropped step isn't connected yet: drag from a step's dot to the new step to connect it.

Clicking **Action** opens the actions library, where you pick the action and then fill in its settings, just like in a form's Submit Actions panel. Clicking **Condition** opens the condition editor straight away.

Working on the canvas:

| To…                         | Do this                                                                   |
| --------------------------- | ------------------------------------------------------------------------- |
| Connect two steps           | Drag from a dot at the bottom of a step to the step that should run next. |
| Change a step's settings    | Double-click it, or select it and click **Edit step** on the right.       |
| Rename a step on the canvas | Select it and type in **Label on the canvas** on the right.               |
| Remove a step               | Select it and press Delete (or click **Delete** on the right).            |

<figure><img src="https://97821998-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FM2yV1foUgoGHBC66VBDw%2Fuploads%2FyL5FXIhpUyLTtfFNbW9w%2FSCR-20261002-pnjv.png?alt=media&amp;token=91bc2870-6566-478a-996b-2f9375a92a9e" alt=""><figcaption><p>Adding and configuring steps in the CraftForms flow editor</p></figcaption></figure>

#### Condition steps <a href="#condition-steps" id="condition-steps"></a>

A condition uses the same rule editor as conditional logic in your forms. You choose a field, an operator such as *is*, *is not*, *is one of* or *is empty*, and a value, and you can combine several rules with *and* / *or*. Click **Save condition**. The flow carries on through **Yes** when the condition matches and through **No** otherwise.

Besides the form's fields (from the reference form), a **Form submitted** flow can check:

* **User is logged in (1/0)**, **User role**, **User ID**, **User email**: the person who submitted the form. This is worked out by WordPress on the server, so a visitor can't fake it by adding a "role" field to the form.
* **Submission ID (after Save Submission)**.

A **WooCommerce order** flow can check **Order status**, **Order total**, **Number of items**, **Has CraftForms-configured items (1/0)**, **Payment method**, **Billing country (code)**, **Shipping country (code)**, **Customer role (empty for guests)**, **Coupon codes (comma-separated)** and **Created via (checkout, admin…)**.

#### Action steps <a href="#action-steps" id="action-steps"></a>

Which actions you can add depends on the trigger:

* **Form submitted** flows can use the actions from a form's Submit Actions library, plus **Generate PDF**.
* **WooCommerce order** flows can use **Send Email (Plain Text)**, **Send Email (Template)**, **Generate PDF**, **Send Webhook**, the email-marketing integrations (Mailchimp, Brevo, FluentCRM, MailPoet), and **Send WooCommerce email**. Actions that need a form, such as Save Submission, aren't offered there.

Actions in a flow also have the **Run only if** setting (except Send WooCommerce email). See [Run only if: conditional submit actions](/documentation/form-building/create-form/form-settings-post-context/submit-actions/run-only-if-conditional-actions.md).

#### When a step fails <a href="#when-a-step-fails" id="when-a-step-fails"></a>

By default a failed action doesn't stop the flow:

* If you connected something to its **If it fails** exit, the flow goes that way. Use this for a backup, for example "if the Mailchimp step fails, email the office".
* If nothing is connected there, that branch simply ends. Other branches carry on.

To stop the whole flow when a step fails, select the step and tick **Stop the flow if this step fails**. The step then shows a *stop on fail* badge. An action whose own **Required (abort on failure)** setting is on also stops the flow when it fails.

### Save, publish and switch off <a href="#save-publish-and-switch-off" id="save-publish-and-switch-off"></a>

A new flow is a **draft**. Drafts never run.

* **Save draft** keeps your changes without turning the flow on.
* **Publish** turns it on: *"Published — forms using this flow run it now."* The flow shows as **Active** in the list.
* Once a flow is active, the buttons are **Save** (keep it running with your changes) and **Switch off** (back to draft).

CraftForms checks the flow when you publish. If something is wrong, you'll see *"Fix the highlighted steps before publishing."* and the problem steps are marked on the canvas, for example:

* *Set up this condition.*
* *Not connected — this step would never run.*
* *Steps can't loop back to an earlier step.*
* *“Save Submission” can't run from this trigger.*
* a required action setting that's still empty.

You can always save a draft, even with problems.

### Use a flow in a form <a href="#use-a-flow-in-a-form" id="use-a-flow-in-a-form"></a>

1. Open the form in the editor (**CraftForms → Forms → Edit**).
2. In the right-hand sidebar, open the **Submit Actions** panel.
3. At the top, choose your flow under **Flow**. The list shows flows with the **Form submitted** trigger. Drafts are marked *(draft — won't run)*.
4. Choose how it works with the form's own actions:
   * **Run after the actions below** (default): the form's actions run as usual, then the flow. The flow can use what those actions produced, for example the submission number after **Save Submission**.
   * **Replace the actions below**: the flow is the whole job. The form's actions are kept, but greyed out, and don't run. Switch back to bring them back.
5. Save the form.

**Open in Flows ↗** under the picker opens the flow in a new tab.

<figure><img src="https://97821998-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FM2yV1foUgoGHBC66VBDw%2Fuploads%2F45SWFVJuvEeYS5Tb7xJo%2FSCR-20261002-pnwq.png?alt=media&amp;token=9afc8195-d140-440d-b973-bf40f062e546" alt=""><figcaption><p>Linking a flow to a form in the CraftForms form editor</p></figcaption></figure>

Good to know:

* **Automatic steps always run.** For a form connected to a catalog item, the order is still created; for a form on a WooCommerce product, the item is still added to the cart. These run first, even in **Replace** mode.
* **A draft or deleted flow is skipped, safely.** The form's own actions still run, even in Replace mode, and the form editor warns you: *"This flow is a draft, so it's skipped — the actions below still run. Publish it in Flows."*
* **If one of the form's actions stops the submission** (for example a required action failed or the payment was declined), the flow doesn't run.
* **One flow per form.** Several forms can share the same flow. Conditions and field mappings refer to fields by name, so the forms should use the same field names.
* **Forms on WooCommerce products** submit when the customer adds the item to the cart. A Form submitted flow on such a form runs at that moment, before any order exists. For order emails and documents, use a WooCommerce order flow instead.

#### When a form flow runs <a href="#when-a-form-flow-runs" id="when-a-form-flow-runs"></a>

By default the flow runs **after the visitor's response is sent**: the visitor sees the confirmation straight away and doesn't wait for emails, PDFs or third-party services. The trigger on the canvas reads *After the response*.

If a step marked **Stop the flow if this step fails** must be able to reject the submission and show the visitor an error, open the trigger settings and untick **Run after the visitor's response is sent (recommended)**. The trigger then reads *During the submission*, and the visitor waits until the flow has finished.

### WooCommerce order flows <a href="#woocommerce-order-flows" id="woocommerce-order-flows"></a>

Choose **WooCommerce order** under **Starts when** in the New flow dialog. Double-click the trigger to set it up:

| Setting                      | What it does                                                                                                                                                                                                                                              |
| ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **When**                     | **An order changes status** (default) or **An order is placed (checkout)**.                                                                                                                                                                               |
| **From** / **To**            | For status changes: the status the order moves into (**To**, e.g. Completed), and optionally the status it comes from (**From**, default **Any status**).                                                                                                 |
| **Orders**                   | **All orders**, **Only orders with CraftForms-configured items**, or **Only orders without them**. This is decided per order, because a cart can mix configured and plain products. For finer targeting (category, total, country), add a Condition step. |
| **WooCommerce's own emails** | **Switch off the ones this flow replaces** (recommended, the default for new order flows), **Choose which to switch off**, or **Keep sending all of them**. See below.                                                                                    |
| **Only once per order**      | For status changes. When off, the flow runs every time the order enters this status, like WooCommerce's own emails.                                                                                                                                       |

Order flows run in the background (through WooCommerce's scheduled actions), so changing an order's status in wp-admin or receiving a payment never waits for emails or PDFs.

#### Which WooCommerce emails a flow switches off <a href="#which-woocommerce-emails-a-flow-switches-off" id="which-woocommerce-emails-a-flow-switches-off"></a>

With **Switch off the ones this flow replaces**, CraftForms works the list out from the flow's own email steps, so you don't have to keep two settings in sync:

* A step that emails the **customer** (its recipient is `{{order.customer_email}}` or `{{order.billing_email}}`) replaces WooCommerce's customer email for the flow's status, e.g. **Completed order** for a flow that runs when an order changes to Completed.
* A step that emails **the shop** (any other recipient, e.g. `{{site.admin_email}}` or a fixed address) replaces WooCommerce's admin email for that moment, e.g. **New order**.
* Add or remove an email step and the list changes with it. The trigger dialog and the trigger step on the canvas show what is switched off right now.

| Flow runs when…                      | Customer email step replaces    | Shop email step replaces                                     |
| ------------------------------------ | ------------------------------- | ------------------------------------------------------------ |
| An order is placed                   | Processing order, Order on-hold | New order                                                    |
| Status changes to Processing         | Processing order                | New order                                                    |
| Status changes to On hold            | Order on-hold                   | New order                                                    |
| Status changes to Completed          | Completed order                 | New order, only for orders that arrive straight as Completed |
| Status changes to Cancelled / Failed | Cancelled / Failed order        | Cancelled / Failed order                                     |
| Status changes to Refunded           | Refunded order                  | —                                                            |

An automatic replacement only applies at the flow's own moment. A Completed flow never switches off the New order email an order gets when it first comes in as Processing.

Use **Choose which to switch off** for emails WooCommerce sends on request (Customer invoice, Customer note) or emails added by other plugins. Those are switched off whenever WooCommerce would send them, for the orders the flow covers.

The emails are switched off for every order the flow covers, even an order a Condition step sends down a path without an email step. Give each path its own email step, or add a **Send WooCommerce email** step on the path that has none.

#### Replace a WooCommerce email (without risk) <a href="#replace-a-woocommerce-email-without-risk" id="replace-a-woocommerce-email-without-risk"></a>

1. Create a WooCommerce order flow: **When** = An order changes status, **To** = Completed. Leave **WooCommerce's own emails** on **Switch off the ones this flow replaces**.
2. Add a **Send Email (Template)** step with your own design. Add an **Order Items** block to the template to list what was ordered (see [Order Items block](/documentation/email-templates/create-email-template/email-template-blocks/order-items.md)).
3. As a safety net, click the email step, then add the action **Send WooCommerce email** and choose **Completed order**. Because the email step's **Next** exit is already used, the new step lands on its **If it fails** exit. If your email can't be sent, the customer still gets WooCommerce's standard email.
4. Publish.

While the flow is active, WooCommerce's "Completed order" email is off for the orders the flow covers. With **Orders** set to "Only orders with CraftForms-configured items", other orders keep WooCommerce's email. Switch the flow off, or delete it, and WooCommerce's email comes back straight away. Nothing is changed in WooCommerce's own email settings.

When you use **Resend order emails** on the WooCommerce order screen for an email that a flow replaces, the flow runs again for that order.

#### Order details in emails and PDFs <a href="#order-details-in-emails-and-pdfs" id="order-details-in-emails-and-pdfs"></a>

Email and PDF steps in an order flow can use the order's dynamic tags (`{{order.*}}`): customer, billing and shipping details, shipping and payment method, the customer's note, every amount (subtotal, discount, shipping, fees, tax, total), and links to view, pay for or edit the order. That covers everything WooCommerce shows in its own order emails. For the full list, see [Dynamic Tags and Variables](/documentation/form-building/create-form/dynamic-tags-and-variables.md).

For the list of items, add the **Order Items** block to your email or PDF template, or use the ready-made `{{order.items_table}}` or `{{order.items_list}}` tags. `{{order.totals_table}}` adds WooCommerce's totals rows. A **Generate PDF** step in an order flow attaches the document to the WooCommerce order. For a sequential invoice number, set the step's **Document role** to Invoice and use `{{pdf.invoice_number}}` in the template.

To start quickly, create your templates from the WooCommerce starters:

* **Email templates:** **WC: Order Confirmation** (to the customer) and **WC: New Order (admin)** (to the shop).
* **PDF templates:** **WC: Invoice** and **WC: Packing Slip**.

A flow that sends a PDF made by an earlier step attaches that same document; it doesn't create a second copy.

### Runs: what happened <a href="#runs-what-happened" id="runs-what-happened"></a>

Open a flow and click the **Runs** tab (next to **Steps**). Each row is one time the flow ran:

* **When**, and **From**: the form, and the submission number if there is one.
* **Result**: **Succeeded**, **Some steps failed**, **Failed** or **Skipped**, with the reason. For example *"Skipped: the flow is not published."* or *"Stopped: a step marked “stop the flow if this fails” failed."*
* **Path**: the steps it went through, in order, with *done*, *failed*, *yes* or *no*, and the error message for any step that failed. Click **Show all … steps** for long flows.

Runs are kept for 30 days. The **Flows** list also shows each flow's **Last run**, and **Used by** lists the forms that point to it.

<figure><img src="https://97821998-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FM2yV1foUgoGHBC66VBDw%2Fuploads%2FFkXHiSdzWzbem7uGio62%2FSCR-20261002-praa.png?alt=media&amp;token=86d8a5fc-499a-4774-b269-6663726c21b0" alt=""><figcaption><p>Flow run log in CraftForms</p></figcaption></figure>

Integration steps (Mailchimp, Brevo…) also write their own entries in **CraftForms → Settings → Integrations → Activity**.

### Export and import <a href="#export-and-import" id="export-and-import"></a>

To copy a flow to another site, or keep a backup:

* **Export:** click the download icon next to a flow in the list, or **Export flow** in the editor. You get a `<flow-name>.craftflow.json` file. The export contains the last *saved* version, so save first.
* **Import:** on the Flows page, click **Import** and choose the file.

What happens on import:

* **The imported flow is always a draft.** Nothing starts running, replacing a form's actions or switching off a WooCommerce email until you've reviewed it and clicked **Publish**.
* **Email templates, PDF templates, SMTP servers, attached files and integration connections are matched by name** on the new site. If one isn't found, you get a warning, and you pick the right one in that step.
* The reference form is matched too. If it isn't found, nothing breaks; the field pickers are just empty until you choose one.
* A step that doesn't exist on the new site (for example an integration whose plugin isn't installed) is reported: *"The step “…” is not available on this site — remove it or the flow can't be published."*

**Forms bring their flow along.** When you export a form that uses a flow, the flow travels inside the form's export file. On import, CraftForms links the form to a flow with the same name if the site already has one. Otherwise it recreates the flow as a draft and tells you: *"Flow “…” was imported as a draft. Review it under CraftForms → Flows and publish it to use it."* Until you publish it, the form's own actions run.

### Who can use Flows <a href="#who-can-use-flows" id="who-can-use-flows"></a>

The **Flows** page is for users who can manage CraftForms settings: by default **administrators** and **shop managers**. Editors can still choose a flow in a form's Submit Actions panel, but they can't open or change flows.

### Good examples <a href="#good-examples" id="good-examples"></a>

* **Route enquiries by service.** A Condition on "Which service?" sends wedding enquiries to Mailchimp and the events team, and everything else to the general inbox.
* **Members vs guests.** A Condition on **User is logged in (1/0)** sends members a different confirmation from guests.
* **A safe Mailchimp sign-up.** Mailchimp step → **If it fails** → Send Email to the office with the contact's details, so no lead is lost when Mailchimp is down.
* **Branded order emails.** A WooCommerce order flow replaces "Completed order" with your own template and Order Items table, with "Send WooCommerce email" as the fallback.
* **Invoice on completion.** WooCommerce order → status Completed → **Generate PDF** (attached to the order) → Send Email (Template) with the PDF attached.
* **Big orders.** WooCommerce order → placed → Condition **Order total** ≥ 500 → Send Webhook to your CRM.

### Tips & troubleshooting <a href="#tips--troubleshooting" id="tips--troubleshooting"></a>

* **The flow didn't run.** Check that it's **Active** (published) and that the form's **Flow** picker points to it. Then open the **Runs** tab: a skipped run says why.
* **The form's actions ran and the flow didn't.** If the picker shows *(draft — won't run)*, publish the flow. If an earlier action stopped the submission, the flow doesn't run.
* **I can't publish.** Look for the steps marked with a warning on the canvas. Every step must be connected to the trigger through some path, and every condition must be set up.
* **My field isn't in the condition's field list.** Set a **Reference form** on the trigger that contains that field.
* **The field pickers list fields, but my other form uses different names.** Conditions and mappings use field names. Give the field the same name in every form that shares the flow.
* **Customers get two emails.** Check **WooCommerce's own emails** in the order flow's trigger settings and make sure the flow is published. The trigger step on the canvas shows **Switches off:** with the emails it replaces.
* **I want order emails for a product configurator.** Use a WooCommerce order flow (order placed or status changed), not the product form's own flow. The form flow runs at add-to-cart, before the order exists.

### FAQ <a href="#faq" id="faq"></a>

**Is Flows a free feature?** No, it's part of CraftForms PRO.

**Do I have to use flows?** No. A form's Submit Actions work exactly as before. Flows are for when you need branches or WooCommerce order automation.

**Can one form use two flows?** No, one flow per form. One flow can be shared by many forms.

**What's the difference between a flow and "Run only if"?** **Run only if** skips a single action based on one choice field, right in the form's Submit Actions. A flow can branch on several conditions, on who submitted, or on order details, and can react when a step fails.

**Does replacing the actions also stop order creation or add-to-cart?** No. Those automatic steps always run first.

**What happens if I delete a flow that forms use?** Those forms skip the flow and run their own actions. The form editor shows *"The selected flow no longer exists; it's skipped."*
