Funnel
Interactive conversion funnel for Jupyter notebooks.
A path is counted at step N if it contains that step's event after
already passing through all previous steps. Supports diff mode to
compare two segments side by side. steps is also editable from the
widget's sidebar without re-running the cell.
How it works
A funnel keeps only the events you name and asks of each path: did it reach these, in this order? Everything in between is ignored — which is what makes a funnel easy to agree on with stakeholders, and unable to tell you why the drop happened.
Two conventions worth being explicit about, because funnels in different tools count differently:
- Order matters, gaps do not. A path counts at step N only if it already passed every earlier step, in sequence. Other events may happen in between, any number of times.
- Paths are counted once. The numbers are unique paths, not event occurrences — buying twice does not count twice.
The result carries two conversion rates per step, and mixing them up is the most common misreading:
| Field | Denominator | Reads as |
|---|---|---|
conversion_rate | all paths in the eventstream | "share of everyone who got this far" |
step_conversion_rate | the previous step | "share of those who got here from the step before" |
Note the denominator of conversion_rate: all paths, including those that
never entered the funnel at all. If most of your eventstream never touches the
funnel, filter first (filter_paths) so
the rate answers the question you meant.
When the funnel stops being enough
The moment you want to know why users dropped between two levels, put the discarded detail back on a narrower question:
# what actually happens between two levels
stream.truncate_paths(start_event="add_to_cart", end_event="purchase").transition_graph()
# turn "how far did this path get" into a segment, then compare the groups
labelled = stream.add_segment("funnel", funnel_events=["add_to_cart", "shipping_details", "purchase"])
labelled.step_matrix(diff=("funnel", "shipping_details", "purchase"))
See Path Analysis for how a funnel compares with the step and transition representations of the same paths.
Usage
stream.funnel(steps=["catalog", "add_to_cart", "purchase"])
stream.funnel(steps=["add_to_cart", "purchase"], diff=("user_lifecycle", "loyal", "new"))
Examples
Basic
stream.funnel(
steps=["catalog", "product_view", "add_to_cart", "purchase"],
)
Diff mode
stream.funnel(
steps=["catalog", "product_view", "add_to_cart", "purchase"],
diff=["platform", "mobile", "desktop"]
)
Parameters
Data
Data parameters change the computed result. They are exactly the arguments of
the widget's headless twin stream.funnel_data() — see
headless mode below.
| Parameter | Type | Description |
|---|---|---|
steps | list of str, optional | Ordered event names defining the funnel steps. |
diff | tuple or list, optional | Draws a comparative chart for a pair of segments; see Diff mode. (segment_col, value1, value2) or (path_ids1, path_ids2); value2 may be <REST>. |
path_col | str, optional | Path ID column override; defaults to schema.path_col. |
Display
Display parameters only affect how the widget is rendered.
| Parameter | Type | Description |
|---|---|---|
height | int, default 420 | Widget height in pixels. |
sidebar_open | bool, default True | Whether the sidebar starts open. |
state_file | str, optional | JSON file the widget state is bound to; see Saving widget state. |
Headless mode
stream.funnel_data()
Compute funnel conversion metrics and return a dict (headless).