Skip to content

Implement open funnel with first and last steps required - #6665

Open
zoldar wants to merge 15 commits into
masterfrom
open-funnel-with-first-and-last
Open

zoldar wants to merge 15 commits into
masterfrom
open-funnel-with-first-and-last

Conversation

@zoldar

@zoldar zoldar commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Changes

This PR implements support for a flexible funnel, where only first and last step are mandatory, while the rest is optional. It's a special, simplified case of an open funnel.

On the implementation side, another shrunk version of the queried funnel is computed - only with 2 steps - the first and last one. The metrics computed for the last step of the short funnel replace the metrics of the last step in the original funnel. And that's basically it.

The UI for configuring funnels is revised as well - now instead of a strict funnel toggle, a user can switch the funnel to work in one of three modes by setting its type:

  • sequential (strict_order: false, first_and_last: false)
  • flexible - the new mode (strict_order: false, first_and_last: true)
  • strict (strict_order: true, first_and_last: false)

The current implementation treats funnel_type as a computed field, abstracting the existing strict_order and the new first_an_last flags. While flags could be replaced with a single enum field, I'm not sure if that's the way to go, yet. Funnel may undergo more changes some time soon and might require further revisions of how we store the configuration.

The only visible change on the dashboard is mostly around the sequential/flexible/strict funnel indication copy shown in place of former strict funnel label.

Luckily, our public API did not expose "strict_order" as an option in funnel creation yet, so there's no problem of dealing with a potential breaking change - yet.

The migration will be extracted and released first once this PR gets approved.

image image

Tests

  • Automated tests have been added

Dark mode

  • The UI has been tested both in dark and light mode

@zoldar zoldar added the preview label Sep 9, 2026
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Preview environment👷🏼‍♀️🏗️
PR-6665

@zoldar
zoldar force-pushed the open-funnel-with-first-and-last branch 6 times, most recently from 25c2cdd to c603c59 Compare September 14, 2026 12:55
@zoldar
zoldar requested a review from a team September 14, 2026 15:27
@zoldar
zoldar marked this pull request as ready for review September 14, 2026 15:27
<div class="flex items-center justify-between gap-4 mt-2">
<.input
type="radio"
class="block h-5 w-5 dark:bg-gray-700 border-gray-300 text-indigo-600 focus:ring-indigo-600"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue, blocking: This class doesn't take effect, can put h-15 here and nothing happens, it is overridden. Same issue for all instances of .input type="radio" component in this file.

Comment thread extra/lib/plausible/stats/funnel.ex Outdated
Comment thread extra/lib/plausible/stats/funnel.ex Outdated
|> Enum.with_index(1)
|> Enum.map(fn {step, idx} -> %{step | step_order: idx} end)

%{funnel | funnel_type: :sequential, steps: steps}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue, non-blocking: This temporary funnel has contradictory values: it's first_and_last?: true, funnel_type: :sequential.

It seems the virtual field :funnel_type field creates a whole class of these integrity problems. There's a few others spots where they lurk in wait.

Can we migrate to a single persisted :funnel_type field for this feature, then migrate out to separate columns again if it indeed turns out we need something else?

  • migration: create funnel_type column
  • deploy code change: when persisting funnels, set funnel_type based on strict_order
  • migration: backfill funnel_type based on strict_order
  • deploy code change: this PR, rewires everything to purely funnel_type and implements the new feature
  • migration: drop strict_order column

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With a fresh eye, yeah, I agree, it's best to switch to the new field completely. However, with the abstracting layer already in place, it can be done simpler:

  • add funnel_type in addition to existing strict_order and newly added first_and_last
  • turn funnel_type into a non-virtual schema field; now everything should work normally when deployed in the current state with 3b76140 and 0c30a5c applied
  • backfill funnel_type (data script TBD)
  • modify Funnel.changeset and Funnels.base_get_query to populate and read funnel_type directly instead of using flag fields
  • remove first_and_last and strict_order

@zoldar
zoldar force-pushed the open-funnel-with-first-and-last branch from 38ee85d to cbc733f Compare September 21, 2026 07:58
@zoldar
zoldar force-pushed the open-funnel-with-first-and-last branch from 0c30a5c to 5b023fd Compare September 21, 2026 08:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants