How many people made it from the first step to the last, and where the rest stopped.
Nothing else on Hex does this. Plausible Community Edition withholds funnels as a paid feature, so in Elixir today the only way to answer this question is to ship your data to PostHog.
Pixelex.Query.Funnel.run("shop", range, [
"px.pageview", "view_doctor", "book_click", "booking_completed"
])
%{
steps: [
%{name: "px.pageview", count: 4182, rate: 1.0, step_rate: 1.0, dropped: 3011},
%{name: "view_doctor", count: 1171, rate: 0.28, step_rate: 0.28, dropped: 894},
%{name: "book_click", count: 277, rate: 0.066, step_rate: 0.237, dropped: 129},
%{name: "booking_completed", count: 148, rate: 0.035, step_rate: 0.534, dropped: 0}
],
conversion_rate: 0.035,
subject: :visitor
}rate is against the first step; step_rate is against the step before —
the second is what tells you which step is broken.
Order is enforced, not assumed
Each step is built from the one before it in its own CTE, so step 3 only
counts events that happened at or after that subject's step 2. The
shortcut most implementations take —
min(occurred_at) FILTER (WHERE name = step_n) in a single pass — silently
drops anyone who did step 3 before step 2 and again after it, and silently
counts nobody whose steps interleave. This costs one CTE per step and is
correct.
Which subject: :visitor or :user
visitor_id is a hash under a salt that rotates every UTC day, so a funnel
keyed on it cannot span midnight. That is right for a checkout and wrong
for an onboarding funnel measured over a week.
run(site, range, steps, subject: :user)keys on user_id instead, which only exists after Pixelex.identify/3. Pick
:visitor for a single-visit funnel and :user for anything longer, and be
aware that :user counts only signed-in people.
Conversion window
run(site, range, steps, within: {2, "hours"})bounds how long a subject has to get from one step to the next. Without it, a visitor who bounced in March and converted in May counts as one funnel.
Summary
Functions
Run an ordered funnel.
Types
Functions
@spec run(String.t(), Pixelex.Query.Range.t(), [String.t()], keyword()) :: map()
Run an ordered funnel.
Options
:subject—:visitor(default) or:user:within—{amount, unit}, e.g.{30, "minutes"}. Units areminutes,hoursordays.