Purchase funnel
Purchase Funnel counts tracked checkout sessions at visits, order clicks and purchase completion. It does not confirm money received.
Payment Successful comes from a browser purchase-completion event; reconcile payments against payment records, not this count.
Events and session attribution#
The writer reads Signal's /analytics/checkout-funnel/raw endpoint and groups events by sessionId. Events without a session ID are skipped. Within each fetched day, it keeps:
| Step | Event retained | Package and payment attribution |
|---|---|---|
| Visits | First pageview containing /checkout/. | Package from that URL; payment method from the retained order click. |
| Order Clicked | Latest checkout_order_clicked event. | package_slug and payment_method from that click. |
| Payment Successful | First convert event named purchase. | Package and method from the retained order click, or empty values without one. |
An order click without a pageview creates an inferred visit with the click's package, date and hour. A purchase alone does not create that missing visit.
For example, a session visits package A, then orders package B. The visit stays under A while the click and purchase appear under B. Payment comparisons instead assign the click's method back to the visit. Event selection and attribution.
TrackPurchase fires on the payment-completion component when checkout response data is available. The report does not query settled transactions. Purchase tracking.
Aggregation and freshness#
A first run processes the previous 24 completed hours. Later runs continue after the checkpoint through the preceding hour.
The writer fetches whole calendar days grouped in Europe/Oslo, correlates sessions, then keeps only the target hours. Session deduplication is limited to that day; the same person or session can contribute across days. Requests are paged at 1,000 events, with a 100-page cap.
If page 100 still has pagination.hasMore: true, unread events remain. The function neither throws nor logs a cap warning; it aggregates the fetched events.
The caller can save incomplete counts and advance the checkpoint. Check that final page's pagination metadata when investigating missing events after a large processing run. Pagination limit, save and checkpoint.
Stored summaries group by tenant, package, payment method, step, hour and date. Upserts replace counts only for matching keys. Later clicks can change attribution after an earlier hour was processed; those earlier keys are not automatically removed. This is a source-based consistency concern requiring a controlled test. Hour processing, upsert and retrieval.
Event hours use UTC, while event dates use server-local formatting. Verify deployed timezone behavior when investigating midnight or cross-day differences.
Formulas and displayed bars#
Let V be Visits, O be Order Clicked and P be Payment Successful for one funnel.
| Figure | Calculation |
|---|---|
| Step percentage | Step count ÷ V × 100, rounded to one decimal. |
| Conversion Rate | P ÷ V × 100, rounded to one decimal. |
| Change in percentage points | Current rounded conversion rate minus previous rounded conversion rate, rounded to one decimal. |
| Loss after a preceding step | Preceding count minus current count; percentage uses the preceding count. |
A zero denominator produces zero percent. Each compared funnel uses its own V; comparison percentages are not shares of the combined audience. Formulas.
The visible drop-off below Order Clicked is (V − O) ÷ V, although its position suggests the next transition. The UI omits the final click-to-purchase loss and displays only positive drops.
With visits present, bar widths are clamped between 2% and 100%. Printed counts and percentages can therefore show differences hidden by bar widths. Rendering.
Date windows and comparisons#
Summary queries use inclusive dataDate bounds. Selected Last 7 days and Last 30 days presets include today plus 7 or 30 preceding dates.
The previous-window calculation uses milliseconds: duration = to − from, previousTo = from − 1 ms, previousFrom = previousTo − duration. These timestamp bounds query a DATE column. Their calendar coverage needs testing, particularly for Today, where the selected endpoints are equal.
An initial request without dates also retains the current time, while selected presets send date-only values. Compare actual API parameters before treating two displayed periods as identical. Both explicit endpoints must be ordered and no more than 365 days apart. Window calculation, date validation.
Single view accepts a package and payment-method filter. Package comparison ignores the payment filter; payment comparison ignores the package filter. Comparisons accept up to 3 selections, and an empty selection falls back to the aggregate funnel. Quick Comparison repeats the same returned counts and rates.
The option lists use all stored package/method values, regardless of the chosen dates. No payment selected maps to an empty method, not a failed-payment status. Comparison queries, available options.
Diagnostic checks#
| Symptom | Check and interpretation |
|---|---|
| Purchase or click count exceeds visits for one package | Trace first URL, latest click and purchase in the same day/session. Package switching can split the counts. |
| Funnel differs from payment reports | Reconcile purchase events with order/payment records. Missing browser tracking or completion-page data can separate the measures. |
| Payment comparison has fewer visits than expected | Check the method assigned from the latest click and empty-method group, not only visit URLs. |
| Historical counts change unexpectedly | Compare source sessions, processed hours and stored attribution keys. Test whether later events changed an earlier session's attribution. |
| Period comparison looks wrong | Inspect current and previous query bounds; verify their DATE-column coverage before calculating a business trend. |
Verification limits#
Source checked at 6cd1850 on 28 September 2026; UI labels inherit the 27 September walkthrough. No checkout, payment, event-reconciliation or ordinary-role test was run. Date boundaries, incremental attribution and pagination-limit behavior have not been tested at runtime. The page checks Analytics access; its API requires READ for DASHBOARD.
For controls and interpretation, see Purchase funnel in Administrators.