Fjord for Craft CMS

Reporting

The funnel

Fjord → Reports shows one row per step, in step order, so the table reads as the funnel:

ColumnIs
Visitorsdistinct sessions that saw the step
Viewspage views, reloads included
Moved onsessions that went forward from it
Drop-offthe share that did not
Orders, RevenuePro
Take rateaccepted 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.