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:
| Method | Default | Description |
|---|---|---|
requiresCron() | false | Return 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.
| Field | Type | Default | Description |
|---|---|---|---|
orderStatus | select | any | Filter by order status: processing, complete, or any |
minimumTotal | number | — | Only fire when the order total is at or above this amount |
storeView | select | any | Limit 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.
| Field | Type | Default | Description |
|---|---|---|---|
fromStatus | text | — | Only fire when leaving this status (empty = any) |
toStatus | text | — | Only fire when entering this status (empty = any) |
storeView | select | any | Limit to a specific store view |
Payload keys: orderId, fromStatus, toStatus, storeCode
order-status-enteredorder-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.
| Field | Type | Default | Description |
|---|---|---|---|
status | text | — | Only fire when this status handle is entered (empty = any) |
storeView | select | any | Limit to a specific store view |
Payload keys: orderId, toStatus, storeCode
order-shipped — Order Shipped
Fires when a full shipment is created for an order.
| Field | Type | Default | Description |
|---|---|---|---|
carrier | text | — | Only fire for this carrier (case-insensitive partial match, empty = any) |
storeView | select | any | Limit 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.
| Field | Type | Default | Description |
|---|---|---|---|
carrier | text | — | Only fire for this carrier (case-insensitive exact match, empty = any) |
storeView | select | any | Limit 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).
| Field | Type | Default | Description |
|---|---|---|---|
minimumTotal | number | 0 | Only fire for orders at or above this total |
storeView | select | any | Limit to a specific store view |
Payload keys: orderId, orderTotal, completedAt, storeCode
order-cancelled — Order Cancelled
Fires when an order is cancelled.
| Field | Type | Default | Description |
|---|---|---|---|
cancellationReason | select | any | Filter by reason: inventory, customer-request, payment, or any |
isHighValueOnly | select | no | Set to yes to limit to orders flagged as high-value |
storeView | select | any | Limit to a specific store view |
Payload keys: orderId, cancellationReason, orderTotal, storeCode
order-refunded — Order Refunded
Fires when a refund is created for an order.
| Field | Type | Default | Description |
|---|---|---|---|
refundType | select | any | Filter by type: full, partial, or any |
storeView | select | any | Limit 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.
| Field | Type | Required | Description |
|---|---|---|---|
operator | select | Yes | gt (>), lt (<), gte (>=), lte (<=) |
amount | number | Yes | Threshold amount |
currency | text | No | Currency code filter (empty = any) |
storeView | select | No | Limit 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 >=.
| Field | Type | Default | Description |
|---|---|---|---|
minimumTotal | number | 200 | Fire when the order total is at or above this amount |
storeView | select | any | Limit 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.
| Field | Type | Description |
|---|---|---|
tag | text | Only 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.
| Field | Type | Default | Description |
|---|---|---|---|
addressType | select | shipping | shipping or billing |
countryCode | text | — | Only fire for this country code (e.g. SK, CZ) |
city | text | — | Only fire for this city name |
postcode | text | — | Only 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).
| Field | Type | Description |
|---|---|---|
storeView | select | Limit 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).
| Field | Type | Description |
|---|---|---|
storeView | select | Limit 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
This trigger requires a cron runner. It is evaluated periodically against all active carts.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
abandonedAfterMinutes | number | Yes | 60 | Minutes of inactivity before a cart is considered abandoned (minimum 15) |
minimumCartTotal | number | No | 0 | Only 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.
| Field | Type | Default | Description |
|---|---|---|---|
totalKey | text | grand_total | Cart total key to evaluate (e.g. grand_total, subtotal) |
minimumTotal | number | 100 | Only fire when the configured total is at or above this value |
storeView | select | any | Limit 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.
| Field | Type | Description |
|---|---|---|
customerGroup | text | Only 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.
| Field | Type | Default | Description |
|---|---|---|---|
requiresSuccess | select | yes | When yes, only fires for successful login attempts |
Payload keys: customerId, customerEmail, loggedIn, sessionId
customer-auth-activity — Customer Auth Activity
Fires on any authentication event.
| Field | Type | Default | Description |
|---|---|---|---|
activityType | select | any | Filter by type: login, signup, or any |
Payload keys: customerId, activityType, timestamp
customer-birthday — Customer Birthday
This trigger requires a cron runner. It is evaluated daily against customer birth dates.
| Field | Type | Default | Description |
|---|---|---|---|
daysBefore | number | 0 | Fire 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.
| Field | Type | Description |
|---|---|---|
minimumTotal | number | Only 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.
| Field | Type | Required | Description |
|---|---|---|---|
segmentHandle | text | Yes | The segment handle that activates this flow |
cooldownHours | number | No | Prevent 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.
| Field | Type | Default | Description |
|---|---|---|---|
minimumOrderCount | number | 2 | Minimum total paid orders (including the current one, min 2) |
storeView | select | any | Limit 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.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
threshold | number | Yes | 5 | Fire 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.
| Field | Type | Default | Description |
|---|---|---|---|
direction | select | any | Filter 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.
| Field | Type | Default | Description |
|---|---|---|---|
minimumDropPercent | number | 0 | Only 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.
| Field | Type | Default | Description |
|---|---|---|---|
minimumDiscountPercent | number | 0 | Only 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.
| Field | Type | Description |
|---|---|---|
threshold | number | Only 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.
| Field | Type | Description |
|---|---|---|
couponPrefix | text | Only 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.
| Field | Type | Default | Description |
|---|---|---|---|
generationType | select | any | Filter by type: codes, voucher, or any |
Payload keys: generationType, giftCardId, codes, totalValue
review-submitted — Review Submitted
Fires when a customer submits a product review.
| Field | Type | Description |
|---|---|---|
minRating | number | Only 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.
| Field | Type | Default | Description |
|---|---|---|---|
operation | select | any | Filter 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.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
formHandle | text | Yes | — | Only submissions from this form handle start the flow |
requireConsent | lightswitch | No | true | When enabled, requires an explicit opt-in flag on the submission |
requiredTags | text | No | — | Comma-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.
| Field | Type | Default | Description |
|---|---|---|---|
status | select | any | Filter 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).
| Field | Type | Default | Description |
|---|---|---|---|
watchdogType | select | any | Filter 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.
| Field | Type | Default | Description |
|---|---|---|---|
eventType | select | any | Filter 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.
| Field | Type | Description |
|---|---|---|
sectionHandle | text | Restrict to entries in this section (empty = any) |
entryType | text | Restrict 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.
| Field | Type | Description |
|---|---|---|
sectionHandle | text | Restrict to entries in this section (empty = any) |
entryType | text | Restrict to this entry type handle (empty = any) |
watchFields | text | Comma-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.
| Field | Type | Default | Description |
|---|---|---|---|
sectionHandle | text | — | Restrict to this section (empty = any) |
fromStatus | select | any | Previous status: live, pending, expired, disabled, or any |
toStatus | select | any | New 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.
| Field | Type | Description |
|---|---|---|
formHandle | text | Only 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
This trigger is evaluated by the cron runner. Configure the schedule and timezone in the node.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
schedule | select | Yes | daily | Preset: every_5_minutes, every_15_minutes, every_30_minutes, hourly, daily, weekly, monthly, or custom |
cronExpression | text | No | — | Custom 5-field cron expression (only used when schedule = custom) |
timezone | text | No | UTC | IANA timezone for schedule evaluation |
Payload keys: scheduledAt, schedule, timezone
recurring-schedule — Recurring Schedule
More flexible than scheduled — always accepts a raw cron expression.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
cronExpression | text | Yes | 0 9 * * 1 | Standard 5-field cron expression (e.g. 0 9 * * 1 for every Monday at 9:00) |
timezone | text | No | UTC | IANA timezone for schedule evaluation |
Payload keys: scheduledAt, cronExpression, timezone
date-field-approaching — Date Field Approaching
Runs daily against all entries in the configured section to detect upcoming dates.
| Field | Type | Required | Description |
|---|---|---|---|
sectionHandle | text | Yes | Section containing entries with the date field |
dateFieldHandle | text | Yes | Handle of the date/datetime field to watch |
daysBefore | number | Yes | Fire 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.
| Field | Type | Default | Description |
|---|---|---|---|
secret | text | — | Token embedded in the endpoint URL for routing to this trigger |
method | select | POST | HTTP 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.
| Field | Type | Description |
|---|---|---|
inputFields | table | Define 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
| Perspective | Assessment |
|---|---|
| Customer / storefront | Triggers are invisible to customers. They fire server-side in response to store events |
| Admin / Craft CP | Triggers 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 / integrator | Custom 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() |