For Craft Commerce 5
The checkout is one page. The sale doesn't have to be.
Commerce gives you a cart and a checkout. Fjord gives you the shape around them — a landing page, a checkout that knows what it is selling, an offer after the sale, and a thank-you page nobody can reach early. Your templates, your markup; Fjord owns the routing, the state and the money.
One line in your checkout
Fjord does not replace your checkout — it routes to it. The only change a working Commerce checkout needs is where its redirect points, because the next step is decided after the order completes, not when the form was rendered.
{# Resolved when it is followed, not when the page renders.
At render time there is no completed order, so an upsell
looks unreachable and a baked-in URL would skip it. #}
{{ redirectInput(craft.fjord.continueUrl) }}
{# The bumps for this checkout, already filtered by eligibility #}
{% for bump in craft.fjord.bumps(step, cart) %}
<h3>{{ bump.getDisplayHeadline() }}</h3>
<strong>{{ bump.getPrice()|commerceCurrency(cart.currency) }}</strong>
{% endfor %}
Features
A funnel engine and an offer engine, each with one place where decisions happen.
Six kinds of step
Landing, opt-in, checkout, upsell, downsell and thank you, served under one base URI in the order you put them in.
- A checkout step stocks the cart with what the funnel sells — once per session, so a reload never doubles it
- Add to the cart, replace it, or leave it alone
Nobody skips ahead
One resolver decides whether a visitor may see a step, so a thank-you page cannot be reached without an order and an upsell cannot be reached without a paid one. Somebody who tries is walked forward to the first step they can see.
- The offer endpoints ask the same resolver, so a hand-crafted POST cannot get past it
Order bumps that survive a recalculation
A discounted product ticked on the checkout, added as a real line item and discounted by a real order adjuster — spliced in ahead of tax, so nobody is taxed on a discount they were given.
- The line item is the truth, not a ledger entry
- Raising the quantity by hand does not extend the bump price
One click after the sale
An accepted post-purchase offer is charged on a new order linked to the original, against the card already used. A completed order is locked and already emailed — Fjord will not rewrite a document the customer has.
- Refundable on its own, and visible in Commerce's own screens
- Skipped entirely when there is nothing reusable to charge
It cannot charge twice
An offer resolves once per order, enforced by a unique database index rather than a check-then-act. A double-submitted form, a retried request and an impatient customer all collide on the index instead of taking a second payment.
- Plus a paid-order requirement, an offer window, and an eligibility check — all re-checked when the endpoint is called
Split tests that keep a control
Give a step variants with traffic weights; whatever the weights leave over goes to the step's own template. A visitor is assigned once and keeps that arm.
- Uplift and a two-proportion z-score, marked “too early” under 30 visitors an arm
- Reported, never acted on — Fjord will not quietly reweight your traffic
Where they fall out
Visitors, views, conversions and drop-off per step, plus revenue, AOV and offer take rate across the funnel — including what share of revenue came from the offers rather than the thing you set out to sell.
- A step converts when a visitor leaves it forwards, so nothing guesses at intent
- Rates are per session: a reload is not another chance to convert
Moves between environments
Flows live in the database, not project config, because they reference purchasable and entry IDs. Export and import move them — and purchasables travel by SKU, so a product never silently becomes a different product.
Questions
The things people ask before installing a funnel builder.
Lite is, and it is not a trial — flows, steps, routing, guarding, checkout steps that stock the cart, the store-checkout override, the Twig variable, per-step conversion reporting, the console commands and export/import, for as many funnels as you like. Pro is a one-off $99 with a $79/year renewal, and adds order bumps, one-click post-purchase upsells, split testing, condition-builder routing, auto-coupons, revenue reporting and webhooks.
No. Fjord routes to your templates and hands them the state; the checkout is still an ordinary Craft Commerce checkout posting to commerce/payments/pay. There is one line to change — pointing redirect at craft.fjord.continueUrl — and no page builder to learn.
It needs a gateway that supports payment sources and purchases, and a customer who chose to save their card at checkout. Stripe and most modern gateways qualify; a manual or offline gateway does not. php craft fjord/flows/check tells you whether any enabled gateway can do it — and when none can, Fjord skips every post-purchase step rather than showing an offer it cannot fulfil.
No — onto a new order linked to it. A completed Commerce order is locked, and its totals have already been emailed and invoiced; adding a line rewrites a document the customer already has. The linked order refunds on its own and shows up in Commerce's own screens. A thank-you page can list both.
An offer resolves once per order, enforced by a unique index on (orderId, offerId) rather than a check-then-act — a double-submitted form or a retried request collides on the index instead of charging again. There is also a paid-order requirement, a time window after the order, and an eligibility check, and all of them are re-checked server-side when the endpoint is called rather than trusted from the page that rendered the button.
Every offer, variant and routing rule stays in the database and stops being served. Nothing is deleted, nothing charges a customer on a licence that does not cover it, and the control panel says what it is ignoring. Renewing picks up exactly where you left off.
That is the idea, and CartFlows' model was read from its source rather than its marketing. What does not translate has been left out rather than faked: no page-builder integrations, no checkout field editor — a Commerce checkout is a template you already own, so there is no fixed form to edit — and no template importer.
Yes. A flow can be scoped to one site or served on all of them, and its routes are registered per site.
Start free, upgrade when the offers pay for it
Lite is free and gives you the whole funnel engine. Pro is $99 with a $79/year renewal, and adds the order bumps, the one-click upsells, split testing and the revenue reporting.