Skip to main content
Version: 2.0.0

Flow Manager — Triggers Reference

This page is the developer-level reference for Flow Manager triggers in yStore v2.2.1. For an overview of how flows work, see Flow Manager. For actions, see Flow Manager — Actions Reference.


How triggers work

Triggers are the entry points of a flow. When a trigger fires, it injects a payload of key-value pairs into the flow context. All subsequent conditions, actions, and logic nodes can read these values using Twig tokens (e.g. {{ order.total }}, {{ customer.email }}).

Most triggers support a matches() guard: fields configured on the trigger node are evaluated against the incoming event data. If the guard returns false, the flow does not start for that event.

Triggers that require a cron runner (birthday checks, cart abandonment, scheduled runs) only fire when the Craft queue processes the relevant job. The minimum polling interval is configured at yStore → Settings → Sales → Flows → Execution.

Store view scoping

Order and checkout triggers include a Store view field. Set it to a specific store code to limit the trigger to that store, or leave it at Any store (the default) to respond to all store views.

Trigger architecture

Custom triggers extend AbstractTriggerDefinition, which extends AbstractStepDefinition. The additional interface is ExecutableTriggerInterface for triggers that run on a cron schedule.

AbstractStepDefinition
└── AbstractTriggerDefinition (TYPE = 'trigger', inputHandles = [])
└── YourTrigger

Key static methods specific to triggers:

MethodDefaultDescription
requiresCron()falseReturn true for time-driven triggers (birthday, scheduled, etc.)
eventHandle()static::handle()The event handle the flow listener matches against
storeViewField()(protected)Returns a ready-made store view selector field

The matches(array $eventData, array $properties): bool instance method is called with the incoming event payload and the configured node properties. Return false to cancel the run for this event.


Order triggers

order-placed — Order Placed

Fires immediately after a successful checkout when an order is created.

FieldTypeDefaultDescription
orderStatusselectanyFilter by order status: processing, complete, or any
minimumTotalnumberOnly fire when the order total is at or above this amount
storeViewselectanyLimit to a specific store view

Payload keys: orderId, orderStatus, orderTotal, storeCode, customerId

order-status-changed — Order Status Changed

Fires when an order transitions between any two statuses.

FieldTypeDefaultDescription
fromStatustextOnly fire when leaving this status (empty = any)
toStatustextOnly fire when entering this status (empty = any)
storeViewselectanyLimit to a specific store view

Payload keys: orderId, fromStatus, toStatus, storeCode

Difference from order-status-entered

order-status-changed is useful when you need to react to a specific transition (e.g. pending → cancelled). order-status-entered matches any entry into a given status regardless of the previous state.

order-status-entered — Order Status Entered

Fires whenever an order enters a specific status, regardless of the previous status.

FieldTypeDefaultDescription
statustextOnly fire when this status handle is entered (empty = any)
storeViewselectanyLimit to a specific store view

Payload keys: orderId, toStatus, storeCode

order-shipped — Order Shipped

Fires when a full shipment is created for an order.

FieldTypeDefaultDescription
carriertextOnly fire for this carrier (case-insensitive partial match, empty = any)
storeViewselectanyLimit to a specific store view

Payload keys: orderId, carrier, trackingNumber, shippedAt, storeCode

order-partially-shipped — Order Partially Shipped

Fires when a partial shipment is created — some items shipped, some still pending.

FieldTypeDefaultDescription
carriertextOnly fire for this carrier (case-insensitive exact match, empty = any)
storeViewselectanyLimit to a specific store view

Payload keys: orderId, carrier, shippedItems, remainingItems, storeCode

order-completed — Order Completed

Fires when an order reaches the terminal completed state (all items fulfilled, payment settled).

FieldTypeDefaultDescription
minimumTotalnumber0Only fire for orders at or above this total
storeViewselectanyLimit to a specific store view

Payload keys: orderId, orderTotal, completedAt, storeCode

order-cancelled — Order Cancelled

Fires when an order is cancelled.

FieldTypeDefaultDescription
cancellationReasonselectanyFilter by reason: inventory, customer-request, payment, or any
isHighValueOnlyselectnoSet to yes to limit to orders flagged as high-value
storeViewselectanyLimit to a specific store view

Payload keys: orderId, cancellationReason, orderTotal, storeCode

order-refunded — Order Refunded

Fires when a refund is created for an order.

FieldTypeDefaultDescription
refundTypeselectanyFilter by type: full, partial, or any
storeViewselectanyLimit to a specific store view

Payload keys: orderId, refundType, refundAmount, refundId, storeCode

order-total-threshold — Order Total Threshold

Fires when an order total crosses a configured amount boundary.

FieldTypeRequiredDescription
operatorselectYesgt (>), lt (<), gte (>=), lte (<=)
amountnumberYesThreshold amount
currencytextNoCurrency code filter (empty = any)
storeViewselectNoLimit to a specific store view

Payload keys: orderId, orderTotal, currency, storeCode

high-value-order — High Value Order

Convenience trigger for orders exceeding a monetary threshold. Use order-total-threshold when you need the full operator set; this trigger always checks >=.

FieldTypeDefaultDescription
minimumTotalnumber200Fire when the order total is at or above this amount
storeViewselectanyLimit to a specific store view

Payload keys: orderId, orderTotal, storeCode

order-note-added — Order Note Added

Fires when any note (internal or customer-visible) is added to an order. No filter fields.

Payload keys: orderId, note, isCustomerVisible, addedBy

order-tag-added — Order Tag Added

Fires when a tag is attached to an order.

FieldTypeDescription
tagtextOnly fire for this specific tag (empty = any tag)

Payload keys: orderId, tag

order-address — Order Address Changed

Fires when a shipping or billing address is set or updated on an order.

FieldTypeDefaultDescription
addressTypeselectshippingshipping or billing
countryCodetextOnly fire for this country code (e.g. SK, CZ)
citytextOnly fire for this city name
postcodetextOnly fire for this postcode

Payload keys: orderId, addressType, shippingAddress, billingAddress

order-customer — Order Customer Changed

Fires when the customer on an order is assigned or reassigned.

Payload keys: orderId, customerId, previousCustomerId

order-item-added — Order Item Added

Fires when a product is added to an active order (cart).

FieldTypeDescription
storeViewselectLimit to a specific store view

Payload keys: orderId, orderItem, storeCode

order-item-removed — Order Item Removed

Fires when a product is removed from an active order (cart).

FieldTypeDescription
storeViewselectLimit to a specific store view

Payload keys: orderId, orderItem, storeCode

order-item-custom-data — Order Item Custom Data Updated

Fires when custom data is written to a specific order item.

Payload keys: orderId, orderItemId, customData

order-payment-method — Order Payment Method Changed

Fires when the payment method on an order is updated.

Payload keys: orderId, paymentMethod, previousPaymentMethod

order-shipping-method — Order Shipping Method Changed

Fires when the shipping method on an order is updated.

Payload keys: orderId, shippingMethod, previousShippingMethod


Cart triggers

cart-abandoned — Cart Abandoned

Cron-driven

This trigger requires a cron runner. It is evaluated periodically against all active carts.

FieldTypeRequiredDefaultDescription
abandonedAfterMinutesnumberYes60Minutes of inactivity before a cart is considered abandoned (minimum 15)
minimumCartTotalnumberNo0Only trigger for carts with a total above this value

Payload keys: cartId, customerId, cartTotal, cartItems, lastActivityAt

cart-total-threshold-reached — Cart Total Threshold Reached

Fires when a specific cart total key meets a minimum value.

FieldTypeDefaultDescription
totalKeytextgrand_totalCart total key to evaluate (e.g. grand_total, subtotal)
minimumTotalnumber100Only fire when the configured total is at or above this value
storeViewselectanyLimit to a specific store view

Payload keys: cartId, totals, storeCode


Checkout triggers

checkout-payment-failed — Checkout Payment Failed

Fires when a payment attempt fails at checkout before the order is placed.

Payload keys: orderId, paymentMethod, errorMessage, storeCode

discount-applied — Discount Applied

Fires when a discount (coupon or automatic rule) is applied at checkout or to a cart.

Payload keys: orderId, discountCode, discountAmount, discountType


Customer triggers

customer-registered — Customer Registered

Fires when a new customer account is created.

FieldTypeDescription
customerGrouptextOnly fire for customers assigned to this group (empty = any)

Payload keys: customerId, customerEmail, customerGroup, registeredAt

customer-logged-in — Customer Logged In

Fires when a customer authenticates.

FieldTypeDefaultDescription
requiresSuccessselectyesWhen yes, only fires for successful login attempts

Payload keys: customerId, customerEmail, loggedIn, sessionId

customer-auth-activity — Customer Auth Activity

Fires on any authentication event.

FieldTypeDefaultDescription
activityTypeselectanyFilter by type: login, signup, or any

Payload keys: customerId, activityType, timestamp

customer-birthday — Customer Birthday

Cron-driven

This trigger requires a cron runner. It is evaluated daily against customer birth dates.

FieldTypeDefaultDescription
daysBeforenumber0Fire this many days before the birthday (0 = on the birthday itself, max 30)

Payload keys: customerId, customerEmail, birthday, daysUntilBirthday

customer-first-order — Customer First Order

Fires when a customer places their very first paid order.

FieldTypeDescription
minimumTotalnumberOnly fire if the first order total meets this minimum

Payload keys: customerId, orderId, orderTotal

customer-blocked — Customer Blocked

Fires when a customer is added to the banned customers list.

Payload keys: customerId, customerEmail, reason, blockedAt

customer-segment-changed — Customer Segment Changed

Fires when a customer is added to or removed from a segment.

FieldTypeRequiredDescription
segmentHandletextYesThe segment handle that activates this flow
cooldownHoursnumberNoPrevent re-entry within this many hours (0 = no cooldown)

Payload keys: customerId, segmentHandle, action (entered/exited)

repeat-customer-order — Repeat Customer Order

Fires when a customer places an order and their total paid order count reaches a minimum.

FieldTypeDefaultDescription
minimumOrderCountnumber2Minimum total paid orders (including the current one, min 2)
storeViewselectanyLimit to a specific store view

Payload keys: customerId, orderId, customerPaidOrderCount, storeCode


Product triggers

product-created — Product Created

Fires when a new product is saved for the first time.

Payload keys: productId, productSku, productName, categoryId

product-updated — Product Updated

Fires when an existing product is saved with changes.

Payload keys: productId, productSku, changedFields

product-out-of-stock — Product Out of Stock

Fires when a product's stock quantity reaches exactly zero. No filter fields.

Payload keys: productId, productSku, stock

product-stock-low — Product Stock Low

Fires when a product's stock quantity falls to or below a threshold.

FieldTypeRequiredDefaultDescription
thresholdnumberYes5Fire when stock is at or below this quantity

Payload keys: productId, productSku, stockQty, threshold

product-price-changed — Product Price Changed

Fires when any price field on a product changes.

FieldTypeDefaultDescription
directionselectanyFilter by direction: decreased, increased, or any

Payload keys: productId, productSku, oldPrice, newPrice

product-price-dropped — Product Price Dropped

Fires specifically when a product price decreases, with optional minimum-drop filter.

FieldTypeDefaultDescription
minimumDropPercentnumber0Only fire when the price drop is at least this percentage

Payload keys: productId, productSku, oldPrice, newPrice, dropPercent

product-price-increased — Product Price Increased

Fires when a product price increases. No filter fields.

Payload keys: productId, productSku, oldPrice, newPrice

product-went-on-sale — Product Went On Sale

Fires when a special/sale price is set on a product that previously had none.

FieldTypeDefaultDescription
minimumDiscountPercentnumber0Only fire when the sale discount is at least this percentage

Payload keys: productId, productSku, newBasePrice, newSpecialPrice

product-sale-ended — Product Sale Ended

Fires when a special/sale price is removed from a product. No filter fields.

Payload keys: productId, productSku, oldSpecialPrice

inventory-level-changed — Inventory Level Changed

Fires whenever any stock quantity changes.

FieldTypeDescription
thresholdnumberOnly fire when the new stock level is at or below this value (empty = any change)

Payload keys: productId, productSku, oldLevel, newLevel


Marketing triggers

coupon-redeemed — Coupon Redeemed

Fires when a coupon code is applied at checkout.

FieldTypeDescription
couponPrefixtextOnly fire for coupon codes starting with this prefix (empty = any coupon)

Payload keys: couponCode, couponId, customerId, orderId, discountAmount

catalog-rule-matched — Catalog Rule Matched

Fires when a catalog pricing rule is applied to a product view.

Payload keys: ruleId, ruleHandle, productId, appliedDiscount

gift-card-generated — Gift Card Generated

Fires when gift card codes or vouchers are generated.

FieldTypeDefaultDescription
generationTypeselectanyFilter by type: codes, voucher, or any

Payload keys: generationType, giftCardId, codes, totalValue

review-submitted — Review Submitted

Fires when a customer submits a product review.

FieldTypeDescription
minRatingnumberOnly fire for reviews with this rating or higher (1–5, empty = any)

Payload keys: reviewId, productId, customerId, rating, comment

wishlist-updated — Wishlist Updated

Fires when a customer's wishlist changes.

FieldTypeDefaultDescription
operationselectanyFilter by operation: added, removed, shared, or any

Payload keys: wishlistId, customerId, productId, operation

newsletter-form-submitted — Newsletter Form Submitted

Fires when a form submission is recorded as a newsletter opt-in.

FieldTypeRequiredDefaultDescription
formHandletextYesOnly submissions from this form handle start the flow
requireConsentlightswitchNotrueWhen enabled, requires an explicit opt-in flag on the submission
requiredTagstextNoComma-separated tags that must all be present on the submission

Payload keys: formHandle, customerId, subscriberEmail, hasConsent, tags

newsletter-corporate-email — Newsletter Corporate Email

Fires when a corporate/B2B email newsletter subscription is recorded.

Payload keys: subscriberEmail, companyName, formHandle

subscriber-status-changed — Subscriber Status Changed

Fires when a newsletter subscriber's status changes.

FieldTypeDefaultDescription
statusselectanyFilter by new status: subscribed, unsubscribed, updated, or any

Payload keys: subscriberId, subscriberEmail, status, previousStatus

watchdog-subscribed — Watchdog Subscribed

Fires when a customer signs up for a product watchdog (price drop or back-in-stock alert).

FieldTypeDefaultDescription
watchdogTypeselectanyFilter by type: price (price drop) or stock (back in stock)

Payload keys: customerId, productId, watchdogType

shared-cart — Shared Cart

Fires when a shareable cart link is created or restored.

FieldTypeDefaultDescription
eventTypeselectanyFilter by event: created, restored, or any

Payload keys: cartId, customerId, shareToken, eventType


Subscription triggers

subscription-created — Subscription Started

Fires when a customer creates a new subscription plan. No filter fields.

Payload keys: subscriptionId, customerId, planId, startDate

subscription-cancelled — Subscription Cancelled

Fires when a subscription is cancelled or expires. No filter fields.

Payload keys: subscriptionId, customerId, planId, reason, cancelledAt


Content triggers (Craft elements)

entry-created — Entry Created

Fires when a new Craft entry is saved.

FieldTypeDescription
sectionHandletextRestrict to entries in this section (empty = any)
entryTypetextRestrict to this entry type handle (empty = any)

Payload keys: entryId, sectionHandle, entryType, title, authorId

entry-updated — Entry Updated

Fires when an existing Craft entry is resaved.

FieldTypeDescription
sectionHandletextRestrict to entries in this section (empty = any)
entryTypetextRestrict to this entry type handle (empty = any)
watchFieldstextComma-separated field handles to watch; fires only when one of these fields changed

Payload keys: entryId, sectionHandle, entryType, changedFields

entry-deleted — Entry Deleted

Fires when a Craft entry is deleted.

Payload keys: entryId, sectionHandle, title

entry-status-changed — Entry Status Changed

Fires when a Craft entry transitions between enabled/disabled states.

FieldTypeDefaultDescription
sectionHandletextRestrict to this section (empty = any)
fromStatusselectanyPrevious status: live, pending, expired, disabled, or any
toStatusselectanyNew status: live, pending, expired, disabled, or any

Payload keys: entryId, sectionHandle, fromStatus, toStatus

category-created — Category Created

Fires when a new category is saved. No filter fields.

Payload keys: categoryId, groupHandle, title

category-updated — Category Updated

Fires when a category is resaved with changes.

Payload keys: categoryId, groupHandle, changedFields

asset-uploaded — Asset Uploaded

Fires when a file is uploaded to any Craft volume. No filter fields.

Payload keys: assetId, volumeHandle, filename, mimeType, size

asset-deleted — Asset Deleted

Fires when an asset is deleted from a Craft volume. No filter fields.

Payload keys: assetId, volumeHandle, filename

tag-created — Tag Created

Fires when a new Craft tag is created. No filter fields.

Payload keys: tagId, tagTitle, groupHandle

global-set-updated — Global Set Updated

Fires when a Craft global set is saved.

Payload keys: globalSetHandle, changedFields

user-created — Craft User Created

Fires when a new Craft user account is created (covers all users, not just yStore customers).

Payload keys: userId, email, username

user-updated — Craft User Updated

Fires when a Craft user record is saved with changes.

Payload keys: userId, email, changedFields

user-activated — Craft User Activated

Fires when a Craft user account is activated (email verified or admin-activated).

Payload keys: userId, email

user-suspended — Craft User Suspended

Fires when a Craft user account is suspended.

Payload keys: userId, email, suspendedBy

form-submitted — Form Submitted

Fires when a Craft form plugin records a submission.

FieldTypeDescription
formHandletextOnly fire for submissions from this form handle (empty = any form)

Payload keys: formHandle, submissionId, fields (all submitted field values)

notification-created — Notification Created

Fires when an internal system notification is created.

Payload keys: notificationId, type, recipientId, message


Scheduled / system triggers

scheduled — Scheduled

Cron-driven

This trigger is evaluated by the cron runner. Configure the schedule and timezone in the node.

FieldTypeRequiredDefaultDescription
scheduleselectYesdailyPreset: every_5_minutes, every_15_minutes, every_30_minutes, hourly, daily, weekly, monthly, or custom
cronExpressiontextNoCustom 5-field cron expression (only used when schedule = custom)
timezonetextNoUTCIANA timezone for schedule evaluation

Payload keys: scheduledAt, schedule, timezone

recurring-schedule — Recurring Schedule

Cron-driven

More flexible than scheduled — always accepts a raw cron expression.

FieldTypeRequiredDefaultDescription
cronExpressiontextYes0 9 * * 1Standard 5-field cron expression (e.g. 0 9 * * 1 for every Monday at 9:00)
timezonetextNoUTCIANA timezone for schedule evaluation

Payload keys: scheduledAt, cronExpression, timezone

date-field-approaching — Date Field Approaching

Cron-driven

Runs daily against all entries in the configured section to detect upcoming dates.

FieldTypeRequiredDescription
sectionHandletextYesSection containing entries with the date field
dateFieldHandletextYesHandle of the date/datetime field to watch
daysBeforenumberYesFire this many days before the field value (min 1)

Payload keys: entryId, sectionHandle, dateFieldHandle, daysRemaining, targetDate

webhook-received — Webhook Received

Fires when an HTTP request arrives at the yStore webhook endpoint.

The endpoint URL is: /yui/flow/webhook/{secret} where {secret} matches the secret field.

FieldTypeDefaultDescription
secrettextToken embedded in the endpoint URL for routing to this trigger
methodselectPOSTHTTP method to accept: POST, GET, or any

Payload keys: httpMethod, headers, body, queryParams

manual — Manual Trigger

Runs the flow on demand from the Craft CP. Use this for ad hoc flows or as a sub-flow entry point.

FieldTypeDescription
inputFieldstableDefine custom input fields (key, label, default value) shown in the run dialog

Payload keys: whatever inputFields defines, plus the standard context (operatorId, runAt)


Shopware-specific triggers

These triggers apply only to stores using the Shopware integration.

shopware-customer-registered — Shopware Customer Registered

Fires when a customer registers through a connected Shopware storefront.

Payload keys: shopwareCustomerId, email, shopwareGroupId

shopware-order-shipped — Shopware Order Shipped

Fires when a Shopware order shipment is recorded.

Payload keys: shopwareOrderId, carrier, trackingNumber


Payload variable reference

All payload keys become flow context variables accessible in Twig: {{ order.total }}, {{ customer.email }}, {{ product.sku }}, etc.

The exact variable path depends on how the flow runner maps the payload. Use the Variable Picker ({} button) in any action field to browse available variables for the current flow's trigger.


Custom triggers

Registering a custom trigger

use yui\craft\events\RegisterFlowDefinitionsEvent;
use yui\craft\services\marketing\FlowService;
use ycraft\craft\Event;

Event::on(
FlowService::class,
FlowService::EVENT_REGISTER_TRIGGER_DEFINITIONS,
function (RegisterFlowDefinitionsEvent $event): void {
$event->classList[] = MyCustomTrigger::class;
}
);

Implementing a custom trigger

<?php

namespace my\plugin\flow\triggers;

use yui\craft\flow\steps\AbstractTriggerDefinition;

class LoyaltyPointsMilestoneTrigger extends AbstractTriggerDefinition
{
public static function handle(): string
{
return 'loyalty-points-milestone';
}

public static function name(): string
{
return 'Loyalty Points Milestone';
}

public static function description(): string
{
return 'Fires when a customer reaches a loyalty points threshold.';
}

public static function category(): string
{
return 'customers';
}

public static function fields(): array
{
return [
[
'handle' => 'milestone',
'label' => 'Points milestone',
'type' => 'number',
'required' => true,
'default' => 1000,
'instructions' => 'Fire when the customer\'s point balance reaches or exceeds this value.',
],
];
}

/**
* Called by the flow event listener to decide whether to start the flow.
*/
public function matches(array $eventData, array $properties): bool
{
$milestone = (int)($properties['milestone'] ?? 1000);
$currentPoints = (int)($eventData['currentPoints'] ?? 0);
return $currentPoints >= $milestone;
}
}

To fire the trigger from your plugin code, dispatch a flow event through the FlowRunnerService:

use yui\craft\Plugin;

Plugin::getInstance()->getFlowRunner()->dispatchEvent(
'loyalty-points-milestone',
[
'customerId' => $customer->id,
'currentPoints' => $newBalance,
'milestone' => $milestone,
]
);

Cron-driven custom trigger

If your trigger requires periodic evaluation (like birthday or cart abandonment), implement ExecutableTriggerInterface and return true from requiresCron():

use yui\craft\flow\executors\ExecutableTriggerInterface;
use yui\craft\flow\FlowContext;
use yui\craft\flow\NodeResult;

class MyScheduledTrigger extends AbstractTriggerDefinition implements ExecutableTriggerInterface
{
public static function requiresCron(): bool
{
return true;
}

public function executeScheduled(array $properties): array
{
// Return an array of payload arrays, one per flow run to start
// Each element becomes one flow execution
return [
['customerId' => 1, 'triggeredAt' => date('c')],
['customerId' => 2, 'triggeredAt' => date('c')],
];
}
}

Audience check

PerspectiveAssessment
Customer / storefrontTriggers are invisible to customers. They fire server-side in response to store events
Admin / Craft CPTriggers are configured in the flow editor at yStore → Marketing → Flows. Trigger nodes appear as the first node in a flow; their fields are rendered in the node panel. Run history is visible at yStore → Logs → Automation
Developer / integratorCustom triggers extend AbstractTriggerDefinition and implement matches(). Register via EVENT_REGISTER_TRIGGER_DEFINITIONS on FlowService. Cron-driven triggers additionally implement ExecutableTriggerInterface and return true from requiresCron(). Dispatch events with FlowRunnerService::dispatchEvent()