Skip to content

Implement basics of funnel exploration logic along with UI prototype#6242

Merged
zoldar merged 21 commits intomasterfrom
funnel-exploration-query-implementations
Apr 13, 2026
Merged

Implement basics of funnel exploration logic along with UI prototype#6242
zoldar merged 21 commits intomasterfrom
funnel-exploration-query-implementations

Conversation

@zoldar
Copy link
Copy Markdown
Contributor

@zoldar zoldar commented Apr 9, 2026

Changes

This PR introduces first iteration of user journey exploration. It implements forward-only exploration, largely in line with what the earlier PoC (#6163) did. The difference is that the querying logic is completely dedicated to exploration and is based on recent research we did with plain SQL prototypes.

One important addition is the ability to filter the next step, so exploration is not entirely dependent on only 10 most popular paths.

The UI is adapted from the earlier prototype. While the API provides ability to query for a full funnel with dropoff and dropoff percentage calculations, for the time being, the UI is only showing visitors, still sticking to incremental querying.

The exploration feature is entirely hidden from everyone but superadmins. For superadmins though, it's available for every site.

The main purpose of this PR is to get an early version out for experimentation against a larger number of various real-world cases - to verify he range of possible journeys across very different datasets as well as the performance.

Tests

  • Automated tests have been added
  • This PR does not require tests

@zoldar zoldar added the preview label Apr 12, 2026
@github-actions
Copy link
Copy Markdown

Preview environment👷🏼‍♀️🏗️
PR-6242

@zoldar zoldar force-pushed the funnel-exploration-query-implementations branch from d5091fd to 756eb0b Compare April 13, 2026 08:55
@zoldar zoldar changed the title [PoC] Implement basics of funnel exploration logic Implement basics of funnel exploration logic along with UI prototype Apr 13, 2026
@zoldar zoldar requested a review from a team April 13, 2026 09:49
@zoldar zoldar marked this pull request as ready for review April 13, 2026 09:49
Copy link
Copy Markdown
Member

@aerosol aerosol left a comment

Choose a reason for hiding this comment

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

Great work ✨

UI shortcomings are obvious so I won't comment on that and let @sanne-san iterate.

term when byte_size(term) > 2 ->
from(s in query,
where:
ilike(selected_as(:next_name), ^"%#{term}%") or
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Pretty cool that you can search for non-pageviews thanks to that

@zoldar zoldar force-pushed the funnel-exploration-query-implementations branch from 3523b59 to 9ad25b0 Compare April 13, 2026 11:05
@zoldar zoldar added this pull request to the merge queue Apr 13, 2026
Merged via the queue into master with commit d298071 Apr 13, 2026
22 checks passed
@zoldar zoldar deleted the funnel-exploration-query-implementations branch April 13, 2026 12:29
Copy link
Copy Markdown
Contributor

@ukutaht ukutaht left a comment

Choose a reason for hiding this comment

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

Looks good overall 👍

input
|> Jason.decode!()
|> Enum.map(&parse_journey_step/1)
|> Enum.reject(&is_nil/1)
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.

This Enum.reject seems to be a no-op currently. parse_journey_step will always return a non-nil value or raise if pattern match fails.

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.

Sorry, my bad. Initially I've made it permissive, silently removing invalid steps and later on I've decided it better crash loudly (an explicit error state can be added later on, if necessary, however, for internal API purposes at least, the input should be expected to be well-formed).

I'll clean that up in one of the follow-ups.


q_next =
from(s in subquery(q_steps),
# avoid cycling back to the beginning of the exploration
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.

Why prevent cycling to the first step but allow cycling to step 2, step 3, etc?

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.

At first I thought that'd follow the logic of windowFunnel with allow_reentry=false, which is the default. However, taking a closer look at it's definition, it seems to apply to a more specific case which doesn't even occur when building funnel using the current method.

Other than this, it "felt" wrong 😅 But other than that, I have no rational reason to no allow that. If somebody wants to explore cycles, no point in preventing that. I'll drop that condition in a follow-up.

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