Version 5.1.0

October 4, 2026

Webhooks now refuse private, loopback and link-local addresses, on save and before each delivery, and never follow redirects. A webhook that posts to an endpoint on your own network stops delivering until you set 'allowPrivateWebhookHosts' => true in config/fjord.php.

Added

  • Funnels can be stored in project config. Settings → Where funnels are stored switches flows, steps, A/B variants and offers to project config, so they're built in development and deployed like sections; where admin changes are off, Fjord's flow and offer screens are read-only. The default is unchanged: the database, editable on the live site. Switching either way keeps every funnel; only an admin can switch, where admin changes are allowed. Purchasables travel by SKU, and sessions, analytics, grants and webhooks stay in the database.
  • A webhook's signing secret can name an environment variable ($FJORD_WEBHOOK_SECRET), so it stays out of the database.

Security

  • Webhook URLs weren't checked, so anyone who could manage webhooks could have the queue worker POST order data to the cloud metadata service or anything on the private network, with retries. Only http/https URLs without credentials that resolve to public addresses are accepted now. The connection is pinned to the checked addresses, so DNS can't be swapped in between, and redirects are never followed. A webhook saved before this release that fails the check is skipped at delivery, not retried.
  • A funnel session token was accepted from a ?fjordSession= URL, where it leaks through the Referer header and server logs. It's now read from the cookie, or from a POST body only.
  • The webhook edit screen printed the signing secret as raw HTML. It's now an escaped field.

Changed

  • Fjord's record classes describe their columns, and PHPStan and ECS run clean.

Version 5.0.0

August 19, 2026

Initial release.

  • Flows: an ordered list of steps served under one base URI, with per-site scoping and a store-checkout override.
  • Six step types — landing, opt-in, checkout, upsell, downsell and thank you — routed and guarded by a single resolver, so no caller can disagree with any other about where a visitor may go.
  • Checkout steps stock the cart with the products the funnel sells, once per session, in add, replace or leave-alone mode.
  • Order bumps: a discounted product ticked at checkout, applied by an order adjuster spliced ahead of tax and keyed off the line item rather than a ledger.
  • One-click post-purchase upsells and downsells, charged on an order linked to the original, bounded by a paid-order requirement, an offer window and a unique index that makes a double submission impossible rather than unlikely.
  • A/B split testing with a control arm, sticky assignment, and reported — never acted on — significance.
  • Condition-builder eligibility on offers and condition-builder routing on flows and steps, plus a repeat-customer rule Commerce does not have.
  • Auto-applied coupons that never overwrite a code the customer typed.
  • Per-step analytics: visitors, views, conversions, drop-off, revenue, AOV and offer take rate.
  • Outbound webhooks, queued and HMAC-signed.
  • Console commands for listing, routing, preflight checks, export/import, template installation, reporting and pruning.
  • Reference templates for every step type.
  • Lite and Pro editions; Pro configuration that survives a downgrade is ignored rather than obeyed.