Skip to main content
Version: 2.0.0

Conditions & Logic Reference

Flow Manager provides two families of step types for controlling execution:

  • Conditions evaluate a test and route the flow to different outputs based on the result.
  • Logic elements control how data moves through the flow — looping, batching, delaying, splitting, and merging branches.

All condition and logic step handles, field names, and output handles used here are sourced from craft-plugin v2.2.1.


Conditions

Condition steps evaluate a test against the current flow context and route execution to one of their named output handles. Every condition routes to a false (or equivalent negative) output on any runtime error — the flow never throws from inside a condition.

If / Else

Handle: if-else

The general-purpose single-condition branch. Evaluates a context field against an expected value using one of twelve operators and routes to true or false.

Fields:

FieldTypeDescription
fieldtextDot-notation path to the context field (e.g. order.total).
operatorselectOne of equals, not_equals, greater_than, less_than, greater_or_equal, less_or_equal, contains, not_contains, is_empty, is_not_empty, starts_with, ends_with.
valuetextThe value to compare against. Twig tokens supported. Not required for is_empty / is_not_empty.

Outputs: true, false

Example: Route VIP customers (group vip) to a premium action; all others continue to the standard email.


Compare Values

Handle: compare-values

Compares two Twig-rendered values using a numeric or string operator. When both rendered values are numeric, PHP float comparison is used; otherwise string comparison applies.

Fields:

FieldTypeDescription
valueAtextFirst value. Twig tokens supported. Required.
operatorselecteq, neq, gt, gte, lt, lte
valueBtextSecond value. Twig tokens supported. Required.

Outputs: true, false

Example: Check whether {{ order.total }} is greater than a discount threshold stored in a context variable.


Filter

Handle: filter

Gate that evaluates multiple field rules with AND / OR logic. Routes to true when the ruleset passes, false otherwise. An empty rules list always passes.

Fields:

FieldTypeDescription
logicselectand (all rules must pass) or or (any rule can pass). Default: and.
rulestableEach row: field (dot-notation path), operator (equals, not_equals, greater_than, less_than, contains, is_empty, is_not_empty), value (Twig supported).

Outputs: true, false

Example: Continue only when customer.group equals vip AND order.total is greater than 100.


Switch

Handle: switch

Routes to one of four numbered case outputs, or a default, based on an exact string match against a context field. The first matching case wins.

Fields:

FieldTypeDescription
fieldtextDot-notation path to the context field (e.g. order.status).
casestableEach row: output (case_1case_4), value to match against (Twig supported).

Outputs: case_1, case_2, case_3, case_4, default

Example: Route order statuses processing, shipped, completed, cancelled to separate notification actions; anything else falls to default.


Number Range

Handle: number-range

Evaluates whether a numeric context value falls within a configured range. The value is rendered as a Twig expression (wrapped in {{ }}).

Fields:

FieldTypeDescription
valuetextContext field path or Twig expression (e.g. order.total).
minnumberLower bound.
maxnumberUpper bound.
inclusivelightswitchInclude min/max values in the range. Default: true.

Outputs: in_range, out_of_range

Example: Apply a mid-tier discount when order total is between 50 and 200.


String Contains

Handle: string-contains

Text matching with five operators. By default case-insensitive; enable case sensitivity per step.

Fields:

FieldTypeDescription
inputtextThe string to search in. Twig tokens supported.
operatorselectcontains, starts_with, ends_with, regex, equals
searchValuetextThe value to search for. Twig tokens supported.
caseSensitivelightswitchDefault: false. Has no effect on regex — include flags in the pattern.

Outputs: match, no_match

Note on regex: Supply a full PHP pattern with delimiters (e.g. /^SKU-\d+$/i). If no delimiter is detected, the value is wrapped in /…/. Twig is applied to the input before the pattern is tested.

Example: Route orders where the SKU matches /^BUNDLE-/i to a bundle-processing action.


Date Compare

Handle: date-compare

Compares two dates using before, after, same_day, or between. All date values are rendered via Twig before parsing; now is a valid literal.

Fields:

FieldTypeDescription
dateAtextFirst date. Twig tokens supported (e.g. {{ order.dateCreated }}).
operatorselectbefore, after, same_day, between
dateBtextSecond date / lower bound for between.
dateCtextUpper bound date; required only when operator is between.

Outputs: true, false

Example: Route to an expired-subscription branch when {{ subscription.expiresAt }} is before now.


List Contains

Handle: list-contains

Checks whether a rendered item value is present in a comma-separated list. Both the list and the item are Twig-rendered and trimmed before comparison (exact string match).

Fields:

FieldTypeDescription
listtextComma-separated values. Twig tokens supported.
itemtextThe value to look for. Twig tokens supported.

Outputs: found, not_found

Example: Check if {{ order.shippingCountry }} is in SK, CZ, HU, AT, PL.


Random Chance

Handle: random-chance

Routes a configurable percentage of executions to selected; the rest go to not_selected. Uses random_int(1, 100) — cryptographically random, not seedable.

Fields:

FieldTypeDescription
percentagenumber1–100. The probability (%) of routing to selected. Default: 50.

Outputs: selected, not_selected

Example: Send 20% of post-purchase customers a new email template for an A/B test.


Time Window

Handle: time-window

Checks whether the current wall-clock time falls within a configured time range and optional day-of-week schedule.

Fields:

FieldTypeDescription
startTimetextStart of window in HH:MM 24-hour format (e.g. 09:00).
endTimetextEnd of window in HH:MM 24-hour format (e.g. 17:00).
timezonetextIANA timezone (e.g. UTC, Europe/Bratislava). Default: UTC.
daysOfWeektextComma-separated day numbers: 1=Monday … 7=Sunday. Leave empty for all days. Default: 1,2,3,4,5.

Outputs: in_window, outside_window

Overnight windows: When startTime > endTime (e.g. 22:0006:00) the step correctly identifies the overnight span.

Runtime errors (invalid timezone, unparseable time) route to outside_window.

Example: Only route to the SMS action when the current time is within Mon–Fri 09:00–17:00 Europe/Bratislava.


User In Group

Handle: user-in-group

Checks whether a Craft user belongs to a specific user group by handle. The user is looked up via User::find()->id($userId).

Fields:

FieldTypeDescription
userIdtextThe Craft user ID to check. Twig tokens supported.
groupHandletextThe user group handle (e.g. editors).

Outputs: in_group, not_in_group

A missing user or empty userId / groupHandle routes to not_in_group.


Customer Order Count

Handle: customer-order-count

Compares a customer's total order count against a threshold using one of five operators. Order count is resolved via OrdersService::getOrderCountByCustomerId().

Fields:

FieldTypeDescription
customerIdtextCustomer ID. Twig tokens supported.
operatorselectgt (>), gte (>=), lt (<), lte (<=), eq (==)
thresholdnumberOrder count to compare against. Default: 1.

Outputs: meets_threshold, below_threshold

Examples:

  • Identify first-time buyers: operator eq, threshold 1.
  • VIP routing: operator gte, threshold 10.

Customer In Segment

Handle: customer-in-segment

Checks whether the customer in the flow context currently belongs to a given customer segment. Membership is resolved from live segment data, not cached — this reflects the segment's state at the moment the condition runs.

Fields:

FieldTypeDescription
segmentHandletextThe segment handle to check membership against.

Outputs: in_segment, not_in_segment

A missing customer, missing segment, or unknown segmentHandle routes to not_in_segment.


Order Status Check

Handle: order-status-check

Checks whether an order's current status matches an expected value. Resolves the order from context first (avoids a DB query when the order context object matches the ID), then falls back to OrdersService::getOrderById().

Fields:

FieldTypeDescription
orderIdtextThe order ID to check. Twig tokens supported.
expectedStatusselectnew, processing, shipped, completed, cancelled, refunded

Outputs: matches, not_matches

Example: Only send a shipping notification when order status is shipped.


Has Field Value

Handle: has-field-value

Checks whether a rendered Twig expression produces a non-empty value. The expression is rendered and trimmed; an empty string routes to empty. The literal string "0" is treated as has_value.

Fields:

FieldTypeDescription
variablePathtextA Twig expression (e.g. {{ customer.email }}).

Outputs: has_value, empty

Example: Skip the notification action when {{ order.shippingAddress }} is empty.


Entry Exists

Handle: entry-exists

Queries the Craft entries table and branches based on whether a matching entry is found. All filter values are Twig-rendered before the query is executed.

Fields:

FieldTypeDescription
sectionHandletextLimit search to a section (e.g. blog). Leave empty for all sections.
slugtextMatch by slug. Twig tokens supported.
entryIdtextMatch by ID. Twig tokens supported.
titletextMatch by title. Twig tokens supported.

At least one of slug, entryId, or title should be set to produce a useful query. All provided filters are applied together (AND).

Outputs: exists, not_found

Example: Skip content creation when an entry with the target slug already exists.


Logic Elements

Logic elements do not branch on a true/false test — they control the shape of execution: loops, delays, parallel branches, data transformation, and flow-control utilities.

For Each

Handle: for-each

Iterates over an array from the flow context. For each item, the connected item branch is executed with the current element exposed under the configured variable name. The empty output is used when the collection is absent or empty.

Fields:

FieldTypeDefaultDescription
collectionPathtextDot-notation path to a context array (e.g. order.items).
itemVariabletextcurrentItemVariable name exposed to the item branch.
maxIterationsnumber100Safety cap to prevent runaway loops.

Outputs: item (per element), empty

Context variables set: _forEachItems, _forEachItemVariable, _forEachMaxIterations

Example: Loop through order.items and send an item-level restock alert for each.


Wait / Delay

Handle: wait-delay

Pauses flow execution for a specified duration and schedules resumption via the flow runner cron job. Returns NodeResult::paused() — the runner creates a scheduled action and picks it up when the delay expires.

Fields:

FieldTypeDefaultDescription
delayAmountnumber1How long to wait.
delayUnitselecthoursminutes, hours, days, weeks

Outputs: (none — execution pauses; resumes at the next connected node)

Example: Wait 24 hours after purchase before triggering a product review request.


Split

Handle: split

Forks execution into up to four parallel branches. Each branch receives the same context snapshot and runs independently.

Outputs: branch_1, branch_2, branch_3, branch_4

Example: After an order is placed, simultaneously send a confirmation email, notify the warehouse team, and create a CP notification.


Merge

Handle: merge

Joins multiple incoming parallel branches back into a single output. Can wait for all branches or proceed on the first arrival.

Fields:

FieldTypeDescription
modeselectall — wait for all branches; first — continue on first arrival.
timeoutnumberSeconds before releasing even if not all branches have arrived (used with all mode).

Outputs: merged

Example: Recombine two Split branches before writing a summary CP notification.


A/B Test

Handle: ab-test

Routes executions into up to four variants (A/B/C/D) based on configurable weight percentages. Weight distribution is cumulative; uses random_int.

Fields:

FieldTypeDescription
variantstableEach row: variant label and integer weight. Weights are summed and used as the denominator.

Outputs: a, b, c, d

Example: Split 70% of post-purchase customers to email template A, 30% to template B.


Batch

Handle: batch

Splits a collection into smaller sub-arrays and processes each chunk sequentially via the batch output. Signals done when all chunks have been processed.

Fields:

FieldTypeDescription
collectionPathtextDot-notation path to the source array.
batchSizenumberNumber of items per chunk.

Outputs: batch (per chunk), done

Example: Process 500 newsletter subscribers in batches of 50 to stay within mail provider rate limits.


Filter Collection

Handle: filter-collection

Splits a collection into filtered (items matching a Twig condition) and rejected (items that do not match).

Fields:

FieldTypeDescription
sourceVariabletextContext variable holding the source array.
conditiontextTwig expression evaluated per item (item available as item).
filteredVariabletextContext variable name for the matching items.
rejectedVariabletextContext variable name for the non-matching items.

Outputs: filtered, rejected

Example: Split order items into in-stock and out-of-stock groups before separate notification branches.


Map

Handle: map

Transforms each element of a collection by rendering a Twig template with the item exposed as a variable. Produces a new array of transformed values.

Fields:

FieldTypeDescription
collectionPathtextDot-notation path to the source array.
itemVariabletextVariable name for the current item inside the template. Default: item.
templatetextTwig template rendered for each item.
outputVariabletextContext variable name to store the mapped array.

Outputs: mapped, empty

Example: Extract email addresses from a list of customer objects: {{ item.email }}.


Reduce

Handle: reduce

Aggregates a collection into a single value using a built-in operation or a custom Twig template.

Fields:

FieldTypeDescription
collectionPathtextDot-notation path to the source array.
operationselectsum, count, min, max, concat, custom
fieldPathtextSub-field within each item to operate on (for sum, min, max).
separatortextSeparator for concat. Default: , .
templatetextTwig accumulator template for custom (item exposed as item, accumulator as carry).
outputVariabletextContext variable name for the result.

Outputs: reduced, empty

Example: Sum all item.price values to compute a cart total.


Deduplicate

Handle: deduplicate

Uses a cache-based check to ensure a unique key is only processed once within a configurable time window. Routes to new on first occurrence and duplicate on subsequent ones.

Fields:

FieldTypeDescription
keytextTwig expression rendered to produce the deduplication key (e.g. {{ order.id }}).
ttlnumberCache TTL in seconds. Default: 3600.

Outputs: new, duplicate

Example: Prevent the same order ID from triggering a confirmation email twice within one hour.


Accumulator

Handle: accumulator

Buffers incoming executions using a cache counter until a threshold is reached, then releases. Routes to collecting while building up, and to threshold_reached when the count hits the target. The counter resets on threshold.

Fields:

FieldTypeDescription
keytextTwig expression for the accumulator key (scopes the counter).
thresholdnumberHow many executions to collect before releasing.
ttlnumberCache TTL in seconds. Counter resets if TTL expires before threshold is reached.

Outputs: collecting, threshold_reached

Example: Collect 10 abandoned cart events before sending a digest email to the operations team.


Rate Limit

Handle: rate-limit

Enforces a global execution ceiling across all invocations within a time window. Unlike Throttle (per key), Rate Limit is a shared counter for the entire step.

Fields:

FieldTypeDescription
maxExecutionsnumberMaximum allowed executions within the window.
windowSecondsnumberLength of the rolling window in seconds.

Outputs: allowed, limited

Example: Cap outbound API calls to a third-party service at 100 per hour regardless of how many orders trigger the flow.


Throttle

Handle: throttle

Per-key rate limiting. Each unique rendered key gets its own counter. Useful for per-customer or per-entity limits.

Fields:

FieldTypeDescription
keytextTwig expression rendered to produce the throttle key (e.g. {{ customer.id }}).
maxExecutionsnumberAllowed executions per window for a single key.
windowSecondsnumberRolling window in seconds.

Outputs: allowed, throttled

Example: Allow each customer to receive at most one promotional email per 24-hour window.


Priority Queue

Handle: priority-queue

Evaluates a score expression and routes to high, medium, or low output based on configurable numeric thresholds.

Fields:

FieldTypeDescription
scoreExpressiontextTwig expression rendering a numeric score.
highThresholdnumberScore >= this value → high.
mediumThresholdnumberScore >= this value (and below highThreshold) → medium. Below → low.

Outputs: high, medium, low

Example: Score orders by total value and route high-value orders to expedited fulfilment.


Audience check

  • Customer/storefront: Conditions and logic elements run server-side in the Craft queue. Customers do not interact with them directly; the results determine which emails, notifications, or CP actions they receive.
  • Admin/Craft CP: Steps are configured in Flow Manager → flow editor (yStore → Marketing → Flow Manager). Each step type is available in the step picker under "Conditions" or "Logic" categories. Runtime results are visible in Flow Health.
  • Developer/integrator: Custom conditions and logic elements can be registered by implementing ExecutableConditionInterface or ExecutableLogicInterface and extending AbstractConditionDefinition / AbstractLogicDefinition. Register via the RegisterFlowSteps event on the FlowService. Source namespace: yui\craft\flow\conditions and yui\craft\flow\logic.