Version 5.3.14

May 1, 2026

No database schema changes; schemaVersion remains 5.3.0.

Changed

  • Setup UX refresh: modernized onboarding visuals for Project, Integrations, Craft Commerce setup, and Review steps with improved spacing, status chips/cards, richer guidance, and plugin icon usage.
  • Project step selection UX: clicking anywhere on a project row now selects its radio option, and the current project (or first row) is auto-selected by default.
  • Dashboard snapshot refresh flow: Refresh Snapshot now supports returnTo=dashboard so dashboard refresh no longer redirects users to Setup Review.

Fixed

  • Freeform realtime submissions: forms events now include required routing metadata (organizationId, clientId) in buildFormsSubmissionEvent(), fixing Burrow API rejections like Missing required field: organizationId.
  • Dispatch auth fallback: dispatch clients now correctly fall back to the account API key when ingestion key is empty, avoiding empty-auth 401s on backfill/dispatch paths.
  • Outbox source filtering: element index source criteria and query status handling now treat Outbox statuses (pending, retrying, failed, sent) as first-class; All no longer collapses to only enabled/sent rows.
  • Outbox default ordering: Outbox element query now defaults to newest-first (outboxCreatedAt DESC) for consistent recency ordering.
  • Outbox implicit sort override: when Craft applies an implicit default id ASC sort, the query now overrides it to newest-first (outboxCreatedAt DESC, elements.id DESC) so default list order is never oldest-first.
  • Outbox sort guard: fixed a type-casting crash when Craft supplies OrderByPlaceholderExpression values in orderBy; default-sort detection now ignores non-scalar direction values safely.

Version 5.3.13

April 1, 2026

No database schema changes; schemaVersion remains 5.3.0.

Added

  • DeliverOutboxRowJob queues delayed republish of a single outbox row for automatic retries and manual retry.
  • Outbox slide-out (element editor): “Delivery” section explains the retry cap and adds Retry now when Burrow is dispatchable, plus optional return to the same editor after POST.

Changed

  • Outbox delivery now uses up to six attempts by default (aligned with the WordPress plugin). Failed realtime sends move to retrying, schedule backoff jobs, and markSent no longer inflates the attempt counter on success.
  • retryNow() resets attempts, clears the last error, and pushes the delivery job so retries actually run (previously only flipped status to pending).
  • Backfill batch failures call markFailed with no automatic outbox retry queue, avoiding a storm of per-event jobs.
  • SettingsController::actionRetryOutbox accepts return = burrow/outbox/{id} for redirects from the slide-out.
  • BurrowApiService::createClient accepts optional runtime scope overlay so SDK client state matches DB runtime (projectId, ingestion key, forms source id). This keeps realtime /api/v1/events routing consistent with backfill when persisted SDK state lags.
  • publishEvents surfaces the last exception message when all publishes fail instead of a generic message only.

Version 5.3.12

April 1, 2026

No database schema changes; schemaVersion remains 5.3.0.

Fixed

  • Freeform realtime dispatch no longer gates on Form::isValid(). Freeform can leave the internal $valid flag false after a successful DB save, which caused the handler to return before publishing to Burrow.

Changed

  • Diagnostics: when a forms submission envelope cannot be built (missing project or forms source id), the plugin now logs a warning with context flags so misconfiguration is easier to spot.

Version 5.3.11

April 1, 2026

No database schema changes; schemaVersion remains 5.3.0.

Fixed

  • Freeform front-end submissions were only observed when SubmissionsService::EVENT_AFTER_SUBMIT ran (after a stored DB save). Forms with “Store submissions” disabled never triggered that path. The listener now uses Solspace\Freeform\Form\Form::EVENT_AFTER_SUBMIT, which runs after every successful handleSubmission() completion. Invalid, error, and spam-marked forms are skipped before dispatch.
  • Freeform form config lookup now falls back to externalFormId when resolving the numeric form id, so tracked forms still match if saved settings lose associative keys.

Version 5.3.10

March 27, 2026

No database schema changes; schemaVersion remains 5.3.0.

Fixed

  • Commerce order status lifecycle handler was registered on OrderStatuses::EVENT_ORDER_STATUS_CHANGE, which Craft Commerce does not define. Status changes are dispatched from OrderHistories::EVENT_ORDER_STATUS_CHANGE; the listener is now attached there so ecommerce.order.fulfilled, refunded, and cancelled fire when CP status changes.

Changed

  • Lifecycle event timestamps use the order element’s dateUpdated (Craft’s persisted save time), normalized through the existing dateValue() helper for ISO-8601 transport, instead of gmdate('c') at handler runtime.

Version 5.3.9

March 27, 2026

No database schema changes; schemaVersion remains 5.3.0.

Fixed

  • Commerce backfill: exclude incomplete carts. The backfill query now requires isCompleted(true) in addition to isPaid(), filtering out carts that had a payment recorded but were never submitted through checkout. These incomplete carts had no Commerce order status and were inflating order counts (~41 extra orders in YTD testing).

Added

  • Order lifecycle events. The plugin now emits ecommerce.order.fulfilled, ecommerce.order.refunded, and ecommerce.order.cancelled events when an order's status changes in Craft Commerce. This enables time-to-ship metrics and accurate net-revenue reporting in Burrow.
  • Order status mapping in onboarding. The Commerce setup step now shows all of the store's order statuses and lets you map each one to a lifecycle state (Fulfilled / Shipped, Refunded, Cancelled). Statuses not mapped are treated as active placed orders. Custom Commerce statuses are fully supported.
  • Lifecycle events in backfill. Ecommerce backfill now emits the appropriate lifecycle event alongside order.placed when an order's current status maps to fulfilled, refunded, or cancelled.
  • Backfill probe: status breakdown. The diagnostics probe now shows a per-status order count and revenue table, plus a Year to date window preset.
  • Canonical shippingTotal property. ecommerce.order.placed events now include properties.shippingTotal (numeric) as the canonical shipping amount, set natively via the SDK builder. The legacy properties.shipping field and properties.shippingMethod duplication have been removed; shippingMethod remains in tags only.
  • Replay-safe externalEventId. All order lifecycle events (placed, fulfilled, refunded, cancelled) now carry a stable externalEventId (e.g. craft_order_123_placed) so Burrow can deduplicate on replay. externalEntityId (craft_order_123) continues to link events for the same order entity.

Version 5.3.8

March 27, 2026

No database schema changes; schemaVersion remains 5.3.0.

Fixed

  • Freeform custom_fields: Stopped merging the full Freeform submission toArray() payload into Burrow properties. Events now include only the minimal envelope (formId, submissionId, submittedAt, isBackfill) plus field-contract mappings (tags/properties). provider and formName remain in tags only, not duplicated in properties.

Added

  • Formie parity with Freeform: Per-form Off / Count-only / Custom fields in onboarding, getFormieFields() for the mapping table, contract sync with real custom_fields / fieldMappings, live submission events, and historical backfill all follow the same rules as Freeform (minimal envelope, mapped fields only).

Version 5.3.7

March 26, 2026

No database schema changes; schemaVersion remains 5.3.0.

Fixed

  • Commerce ecommerce backfill now limits imported orders to those Craft Commerce considers paid (OrderQuery::isPaid()), so unpaid carts and abandoned checkouts are no longer sent as order backfill events. The paid-only filter is shared with the commerce probe used for discovery counts.

Version 5.3.6

March 26, 2026

No database schema changes; schemaVersion remains 5.3.0.

Added

  • CleanupOutboxRetentionJob: Saving outbox retention (including force purge with 0 days) now queues cleanup on Craft’s queue (15-minute TTR) instead of running large deletes during the CP request, avoiding PHP/web timeouts.
  • Reset stuck backfill: When backfill status is Queued or Running but no queue job is actually processing (worker stopped, timeout, deploy), the dashboard offers Reset stuck backfill to mark the run failed and allow a new start.

Version 5.3.5

March 26, 2026

No database schema changes; schemaVersion remains 5.3.0.

Added

  • Outbox retention 0 (force purge): Saving operations settings with 0 days removes all sent and failed outbox rows immediately, truncates burrow_outbox_sent (send dedupe index), and leaves pending / retrying untouched. The stored retention window is not saved as 0; the previous schedule (or default 30 days) remains.

Version 5.3.4

March 26, 2026

No database schema changes; schemaVersion remains 5.3.0.

Fixed

  • ecommerce.order.placed events now include shippingTotal and shippingMethod on properties (Burrow activity UIs that surface properties were missing them; the PHP SDK only emits tax/subtotal there by default). Commerce payloads already carried shipping in tags / internal fields but they were not merged into properties.
  • Commerce shipping amount is read from totalShippingCost only (removed adjustmentSubtotal fallback, which was not shipping-specific and could misreport totals). Applies to live order tracking and historical backfill.

Version 5.3.3

March 26, 2026

No database schema changes; schemaVersion remains 5.3.0.

Changed

  • During BackfillChunkJob, outbox mirror elements are saved with Craft search indexing deferred; at the end of each job run, accumulated outbox elements are indexed once via Search::indexElementAttributes(), reducing search-index churn on large backfills.

Added

  • .gitignore entries for .DS_Store.

Version 5.3.2

March 26, 2026

No database schema changes; schemaVersion remains 5.3.0.

Added

  • BackfillChunkJob — historical backfill runs through Craft’s queue in bounded chunks (configurable query pages per job) so long windows and all-time runs no longer rely on a single Control Panel HTTP request and are far less likely to hit timeouts.

Changed

  • Dashboard backfill action queues the first chunk job, shows Queued / Running status, blocks overlapping starts, and reminds operators to keep a queue worker running.
  • forms.submission.received events (live and backfill): tags emphasize the form title (formName); properties.formId is the numeric Craft form id instead of a provider prefix (FF / FRM), for clearer context in Burrow.

Version 5.3.1

March 26, 2026

No database schema changes; schemaVersion remains 5.3.0.

Fixed

  • SDK-built ecommerce envelopes (cart abandonment, cart/checkout funnel, order placed, line items, etc.) now set source to craft-plugin after canonical builders run, so payloads and Burrow UI no longer incorrectly show wordpress-plugin for Craft Commerce.

Changed

  • Historical backfill loads submissions and orders in fixed batches, streams events to the API in submit chunks, and avoids building a single giant in-memory event list (reduces PHP memory exhaustion on large datasets).
  • Backfill probe uses lightweight DB counts for form submission totals instead of materializing full event lists; ecommerce event counts still follow the same eligibility rules as backfill.

Version 5.3.0

March 25, 2026

Added

  • Runtime state columns connectionBaseUrl and connectionApiKey (migration) so Control Panel connection can be saved when allowAdminChanges is false.
  • Plugin::getBurrowBaseUrl(), getBurrowApiKey(), getConnectionSettingsForDisplay(), canDispatchToBurrow(), runtimeStateHasIngestionKey(), and clearAccountApiKeyFromProjectConfigIfAllowed() for consistent credential resolution across CP, queue jobs, and the snapshot API.
  • helpers/CredentialCrypto — encrypts ingestionKey.key and connectionApiKey at rest via Craft::$app->getSecurity()->encryptByKey() / decryptByKey() with distinct HKDF info strings; legacy plaintext values are read until the next save re-seals them.

Changed

  • Connection step persists credentials to the database first; project-config plugin settings are updated only when admin changes are permitted.
  • After a successful project link, the account-level API key is cleared from runtime state (short-lived bootstrap); project ingestion key remains for ongoing API use. When allowAdminChanges is true, the plugin apiKey setting is also cleared after link.
  • getBurrowApiKey() no longer falls back to project-config apiKey when an ingestion key exists, so stale YAML cannot override project-scoped auth.
  • Forms contract submission uses ingestion-first SDK client auth (same pattern as event dispatch).
  • Snapshot, heartbeat, abandoned-cart jobs, and the stack-snapshot API gate on canDispatchToBurrow() so ingestion-only installs work without a stored account key.

Fixed

  • Control Panel connection save no longer hard-depends on allowAdminChanges; production environments with project config frozen can complete onboarding using DB-backed credentials.

Version 5.2.0

March 19, 2026

Added

  • Ecommerce funnel event: ecommerce.cart.abandoned — queue job scans for idle Commerce carts past a configurable threshold (default 120 min), emitted as a lifecycle event with deduplication on externalEntityId.
  • Ecommerce funnel event: ecommerce.payment.failed — hooks Commerce EVENT_AFTER_PROCESS_PAYMENT for unsuccessful transactions with gateway-provided failure reasons.
  • Ecommerce funnel event: ecommerce.checkout.started — detects checkout initiation when an email is first populated on an incomplete order with line items, deduped per cart.
  • Ecommerce funnel event: ecommerce.cart.recovered — emitted at order completion when a prior cart or checkout abandonment signal exists for the customer.
  • Four new envelope builders in BurrowApiService with SDK canonical builder pass-through and manual fallback.
  • DetectAbandonedCartsJob scheduled alongside existing system jobs (30-minute cadence), gated by ecommerce_funnel capability.

Version 5.1.0

March 19, 2026

Added

  • Realtime event tracking for Freeform and Formie form submissions.
  • Realtime commerce hooks for completed orders and cart removal events.
  • Durable Outbox pipeline — all realtime events now route through the Outbox for delivery guarantees.
  • Native Craft Element Index UI for the Outbox page with condition rules, channel/event name query filters, and status badges.
  • Outbox slideout detail view with configurable provider prefix for form IDs.
  • Public API endpoint for remote snapshot refresh.
  • CP breadcrumbs across all control panel pages.

Changed

  • Aligned backfill and event assembly around SDK boundaries.
  • Tightened forms backfill filtering and normalized Formie mode handling.
  • Hardened Freeform realtime submission matching and field mapping.
  • Populated full commerce order tags to match SDK and WordPress parity.
  • Cleaned up dashboard layout and persisted project name from SDK link result.
  • Refined onboarding defaults and plugin branding.
  • Simplified CP page titles to avoid redundant plugin name prefix.

Fixed

  • Ecommerce order envelope parity with SDK contracts.
  • Outbox element index virtual attribute errors.
  • Outbox slideout click handling and detail view polish.

Version 5.0.0

March 18, 2026

Added

  • Initial Craft CMS 5 release of the Burrow bridge plugin.
  • 5-step Control Panel onboarding flow for connection, project linking, integration setup, review, and finish.
  • Burrow SDK-based discovery and link workflow for connecting a Craft site to a Burrow project.
  • Integration support for Freeform, Formie, and Craft Commerce.
  • Forms contract generation and contract sync to Burrow.
  • System snapshot collection and publish flow for Craft and installed plugin version visibility.
  • Dashboard view for linked project status, integrations, sync state, snapshot health, logs, and backfill actions.
  • Outbox management screen with queue statistics plus retry and delete actions.
  • Manual historical backfill workflow for form submissions and ecommerce orders/items.
  • Plugin database tables for runtime state, outbox records, sent-event dedupe tracking, and operational event logs.