Skip to content

Commit f428d38

Browse files
authored
Serve exploration config to the front-end (#6352)
* Serve exploration config to the front-end * Move exploration config to site context * !fixup * !fixup * Remove unnecessary effect dependencies * camelCase context vars * Enforce dataset keys, since we provide fallbacks already * Format
1 parent e2abdb8 commit f428d38

6 files changed

Lines changed: 55 additions & 13 deletions

File tree

assets/js/dashboard/extra/exploration.js

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@ import { ChevronUpDownIcon, ChevronRightIcon } from '@heroicons/react/20/solid'
2222
import { FlagIcon, MagnifyingGlassIcon } from '@heroicons/react/24/outline'
2323
import { popover } from '../components/popover'
2424

25-
const JOURNEY_END_EVENT = '__journey_end__'
26-
2725
const DIRECTION = { FORWARD: 'forward', BACKWARD: 'backward' }
2826

2927
const DIRECTION_OPTIONS = [
@@ -33,7 +31,6 @@ const DIRECTION_OPTIONS = [
3331

3432
const PAGE_FILTER_KEYS = ['page', 'entry_page', 'exit_page']
3533

36-
const MAX_JOURNEY_STEPS = 20
3734
const MAX_VISIBLE_CANDIDATES = 10
3835
const MIN_GRID_COLUMNS = 3
3936
const PRELOAD_MAX_STEPS = 2
@@ -105,12 +102,12 @@ function stepsToJourneyParam(steps) {
105102
)
106103
}
107104

108-
function maybeEmptyResults(results, activeFilter) {
105+
function maybeEmptyResults(results, activeFilter, journeyEndEvent) {
109106
if (
110107
results.length === 0 ||
111108
(!activeFilter &&
112109
results.length === 1 &&
113-
results[0].step.name === JOURNEY_END_EVENT)
110+
results[0].step.name === journeyEndEvent)
114111
) {
115112
return []
116113
} else {
@@ -370,9 +367,10 @@ function CandidateCard({
370367
colIndex,
371368
onSelect
372369
}) {
373-
const isJourneyEnd = step.name === JOURNEY_END_EVENT
370+
const { explorationJourneyEndEvent: journeyEndEvent } = useSiteContext()
371+
const isJourneyEnd = step.name === journeyEndEvent
374372
const isCustomEvent =
375-
step.name !== 'pageview' && step.name !== JOURNEY_END_EVENT
373+
step.name !== 'pageview' && step.name !== journeyEndEvent
376374
const isGoal = step.is_goal
377375

378376
const visitorsToShow =
@@ -528,6 +526,7 @@ function ColumnEmptyState({
528526
}
529527

530528
function MaxDepthColumn({ colIndex, header }) {
529+
const { explorationMaxJourneySteps: maxJourneySteps } = useSiteContext()
531530
return (
532531
<div
533532
data-exploration-column={colIndex}
@@ -541,7 +540,7 @@ function MaxDepthColumn({ colIndex, header }) {
541540
<div className="h-92 flex items-center justify-center max-w-2/3 mx-auto text-center text-sm text-pretty text-gray-400 dark:text-gray-500">
542541
<span className="flex flex-col items-center gap-2">
543542
<FlagIcon className="size-4.5" />
544-
{`You've reached the maximum journey depth of ${MAX_JOURNEY_STEPS} steps.`}
543+
{`You've reached the maximum journey depth of ${maxJourneySteps} steps.`}
545544
</span>
546545
</div>
547546
</div>
@@ -679,6 +678,10 @@ function provisionalEntry(step, columnIndex, sourceResults, existingFunnel) {
679678
// useExplorationData manages all async data fetching, cancellation, and
680679
// journey state.
681680
function useExplorationData(site, dashboardState, inViewport) {
681+
const {
682+
explorationMaxJourneySteps: maxJourneySteps,
683+
explorationJourneyEndEvent: journeyEndEvent
684+
} = useSiteContext()
682685
const [state, setState] = useState(EMPTY_JOURNEY_STATE)
683686
const [activeLoading, setActiveLoading] = useState(false)
684687
const [retryCount, setRetryCount] = useState(0)
@@ -797,7 +800,7 @@ function useExplorationData(site, dashboardState, inViewport) {
797800
const steps = state.steps
798801
const activeFilter = state.activeFilter
799802

800-
if (steps.length >= MAX_JOURNEY_STEPS) {
803+
if (steps.length >= maxJourneySteps) {
801804
setActiveLoading(false)
802805
return
803806
}
@@ -854,7 +857,8 @@ function useExplorationData(site, dashboardState, inViewport) {
854857
...prev,
855858
activeResults: maybeEmptyResults(
856859
r?.next ?? [],
857-
prev.activeFilter
860+
prev.activeFilter,
861+
journeyEndEvent
858862
),
859863
rateLimited: false
860864
}))
@@ -902,7 +906,8 @@ function useExplorationData(site, dashboardState, inViewport) {
902906
...prev,
903907
activeResults: maybeEmptyResults(
904908
r?.next ?? [],
905-
prev.activeFilter
909+
prev.activeFilter,
910+
journeyEndEvent
906911
),
907912
rateLimited: false
908913
}))
@@ -956,7 +961,8 @@ function useExplorationData(site, dashboardState, inViewport) {
956961
...prev,
957962
activeResults: maybeEmptyResults(
958963
response?.next ?? [],
959-
prev.activeFilter
964+
prev.activeFilter,
965+
journeyEndEvent
960966
),
961967
rateLimited: false
962968
}
@@ -1091,6 +1097,7 @@ export function FunnelExploration() {
10911097
const site = useSiteContext()
10921098
const { dashboardState } = useDashboardStateContext()
10931099
const [inViewport, setInViewport] = useState(false)
1100+
const maxJourneySteps = site.explorationMaxJourneySteps
10941101

10951102
const {
10961103
state,
@@ -1220,7 +1227,7 @@ export function FunnelExploration() {
12201227
: `${parseFloat(funnel[i].conversion_rate).toFixed(1)}%`
12211228
: null
12221229

1223-
if (isActive && steps.length >= MAX_JOURNEY_STEPS) {
1230+
if (isActive && steps.length >= maxJourneySteps) {
12241231
return (
12251232
<MaxDepthColumn
12261233
key={i}

assets/js/dashboard/site-context.test.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ describe('parseSiteFromDataset', () => {
1616
data-props-opted-out="false"
1717
data-funnels-available="true"
1818
data-exploration-available="false"
19+
data-exploration-journey-end-event="__journey_end__"
20+
data-exploration-max-journey-steps="20"
1921
data-site-segments-available="true"
2022
data-props-available="true"
2123
data-revenue-goals='[{"currency":"USD","display_name":"Purchase"}]'
@@ -45,6 +47,8 @@ describe('parseSiteFromDataset', () => {
4547
funnelsAvailable: true,
4648
propsAvailable: true,
4749
explorationAvailable: false,
50+
explorationJourneyEndEvent: '__journey_end__',
51+
explorationMaxJourneySteps: 20,
4852
siteSegmentsAvailable: true,
4953
revenueGoals: [{ currency: 'USD', display_name: 'Purchase' }],
5054
funnels: [{ id: 1, name: 'From homepage to login', steps_count: 3 }],

assets/js/dashboard/site-context.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ export function parseSiteFromDataset(dataset: DOMStringMap): PlausibleSite {
99
funnelsAvailable: dataset.funnelsAvailable === 'true',
1010
propsAvailable: dataset.propsAvailable === 'true',
1111
explorationAvailable: dataset.explorationAvailable === 'true',
12+
explorationJourneyEndEvent: dataset.explorationJourneyEndEvent!,
13+
explorationMaxJourneySteps: parseInt(
14+
dataset.explorationMaxJourneySteps!,
15+
10
16+
),
1217
siteSegmentsAvailable: dataset.siteSegmentsAvailable === 'true',
1318
conversionsOptedOut: dataset.conversionsOptedOut === 'true',
1419
funnelsOptedOut: dataset.funnelsOptedOut === 'true',
@@ -37,6 +42,8 @@ export const siteContextDefaultValue = {
3742
hasProps: false,
3843
funnelsAvailable: false,
3944
explorationAvailable: false,
45+
explorationJourneyEndEvent: '',
46+
explorationMaxJourneySteps: 0,
4047
propsAvailable: false,
4148
siteSegmentsAvailable: false,
4249
conversionsOptedOut: false,

assets/test-utils/app-context-providers.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ export const DEFAULT_SITE: PlausibleSite = {
3232
hasProps: false,
3333
funnelsAvailable: false,
3434
explorationAvailable: false,
35+
explorationJourneyEndEvent: '',
36+
explorationMaxJourneySteps: 0,
3537
propsAvailable: false,
3638
siteSegmentsAvailable: false,
3739
conversionsOptedOut: false,

lib/plausible_web/controllers/stats_controller.ex

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,14 @@ defmodule PlausibleWeb.StatsController do
6262
exploration_available? =
6363
on_ee(do: Plausible.Auth.is_super_admin?(current_user), else: false)
6464

65+
{exploration_journey_end_event, exploration_max_journey_steps} =
66+
on_ee(
67+
do:
68+
{Plausible.Stats.Exploration.Journey.Step.journey_end_event(),
69+
Plausible.Stats.Exploration.max_steps()},
70+
else: {"", 0}
71+
)
72+
6573
consolidated_view_available? =
6674
on_ee(do: Plausible.ConsolidatedView.ok_to_display?(site.team), else: false)
6775

@@ -101,6 +109,8 @@ defmodule PlausibleWeb.StatsController do
101109
consolidated_view?: consolidated_view?,
102110
consolidated_view_available?: consolidated_view_available?,
103111
exploration_available?: exploration_available?,
112+
exploration_journey_end_event: exploration_journey_end_event,
113+
exploration_max_journey_steps: exploration_max_journey_steps,
104114
team_identifier: team_identifier,
105115
limited_to_segment_id: nil
106116
)
@@ -475,6 +485,14 @@ defmodule PlausibleWeb.StatsController do
475485
exploration_available? =
476486
on_ee(do: Plausible.Auth.is_super_admin?(current_user), else: false)
477487

488+
{exploration_journey_end_event, exploration_max_journey_steps} =
489+
on_ee(
490+
do:
491+
{Plausible.Stats.Exploration.Journey.Step.journey_end_event(),
492+
Plausible.Stats.Exploration.max_steps()},
493+
else: {"", 0}
494+
)
495+
478496
limited_to_segment_id =
479497
if Plausible.Site.SharedLink.limited_to_segment?(shared_link) do
480498
shared_link.segment.id
@@ -525,6 +543,8 @@ defmodule PlausibleWeb.StatsController do
525543
consolidated_view?: false,
526544
consolidated_view_available?: false,
527545
exploration_available?: exploration_available?,
546+
exploration_journey_end_event: exploration_journey_end_event,
547+
exploration_max_journey_steps: exploration_max_journey_steps,
528548
team_identifier: team_identifier,
529549
limited_to_segment_id: limited_to_segment_id
530550
)

lib/plausible_web/templates/stats/stats.html.heex

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@
4848
data-is-consolidated-view={Jason.encode!(@consolidated_view?)}
4949
data-consolidated-view-available={Jason.encode!(@consolidated_view_available?)}
5050
data-exploration-available={Jason.encode!(@exploration_available?)}
51+
data-exploration-journey-end-event={@exploration_journey_end_event}
52+
data-exploration-max-journey-steps={@exploration_max_journey_steps}
5153
data-team-identifier={@team_identifier}
5254
data-limited-to-segment-id={Jason.encode!(@limited_to_segment_id)}
5355
>

0 commit comments

Comments
 (0)