Reporting
The funnel
Fjord → Reports shows one row per step, in step order, so the table reads as the funnel:
| Column | Is |
|---|---|
| Visitors | distinct sessions that saw the step |
| Views | page views, reloads included |
| Moved on | sessions that went forward from it |
| Drop-off | the share that did not |
| Orders, Revenue | Pro |
| Take rate | accepted offers over offers seen, on an upsell step |
Every rate is per session, not per view. A reload is not another chance to convert.
What "converted" means
A step converts when a visitor leaves it forwards — recorded at the moment the next step is seen. That is the only definition that does not require guessing at intent, and it is why the last step in a funnel always shows a 0% conversion rate: there is nothing after it to leave towards.
A conversion is recorded once per session per step, so navigating back and forward again does not count twice.
Across the flow
Sessions, orders, end-to-end conversion (orders over the sessions that entered at all), average order value, and — on Pro — what share of revenue came from bumps and post-purchase offers rather than from the thing the funnel set out to sell. That last figure is the one that says whether the offer engine is earning its keep.
The biggest drop-off is highlighted. A step nobody has seen yet is not eligible for it: an unseen step has no drop-off, only a missing denominator.
On the command line
php craft fjord/stats/report # every flow
php craft fjord/stats/report springLaunch # one
php craft fjord/stats/report --days=90
Recent offers
The report lists the last 25 offer outcomes across the store — accepted, declined or failed, with the amount, the order, and the gateway's message on a failure. It is the fastest way to see that a gateway has started refusing stored cards.
Webhooks
Pro. Subscribe an endpoint to any of:
step.view · step.convert · order.complete · offer.accepted · offer.declined ·
offer.failed
Deliveries are queued, never inline — an upsell must not get slower, or fail, because a marketing endpoint is down. A webhook can be scoped to one flow.
Every delivery carries X-Fjord-Signature: an HMAC-SHA256 of the exact body sent, keyed with the
webhook's secret. Verify against the raw body, not a re-serialised copy of it:
hash_equals(
$_SERVER['HTTP_X_FJORD_SIGNATURE'],
hash_hmac('sha256', file_get_contents('php://input'), $secret)
);
The body is {"event": "…", "timestamp": …, "data": {…}}.
Retention
Events are kept for Event Retention days (365 by default; 0 keeps them forever) and pruned by garbage collection, along with expired sessions. Run it now with:
php craft fjord/stats/prune
Turning Track Events off leaves every funnel working and the reports empty. Recording never throws: a funnel that stopped working because its analytics did would be a worse bug than a missing number.