From 9bd7618874768b4610f26a2a771a4ae285f59c50 Mon Sep 17 00:00:00 2001 From: Ben White Date: Fri, 26 Apr 2024 13:26:01 +0200 Subject: [PATCH] feat: Improve Heatmaps UI and notices (#21887) --- .../src/toolbar/stats/HeatmapToolbarMenu.tsx | 244 +++++++++++++----- 1 file changed, 179 insertions(+), 65 deletions(-) diff --git a/frontend/src/toolbar/stats/HeatmapToolbarMenu.tsx b/frontend/src/toolbar/stats/HeatmapToolbarMenu.tsx index 273796a853a9e..f5c9a5ce8ac17 100644 --- a/frontend/src/toolbar/stats/HeatmapToolbarMenu.tsx +++ b/frontend/src/toolbar/stats/HeatmapToolbarMenu.tsx @@ -1,5 +1,5 @@ -import { IconMagicWand } from '@posthog/icons' -import { LemonLabel, LemonSegmentedButton } from '@posthog/lemon-ui' +import { IconInfo, IconMagicWand } from '@posthog/icons' +import { LemonLabel, LemonSegmentedButton, LemonTag } from '@posthog/lemon-ui' import { useActions, useValues } from 'kea' import { CUSTOM_OPTION_KEY } from 'lib/components/DateFilter/types' import { IconSync } from 'lib/lemon-ui/icons' @@ -11,12 +11,14 @@ import { LemonSwitch } from 'lib/lemon-ui/LemonSwitch' import { Spinner } from 'lib/lemon-ui/Spinner' import { Tooltip } from 'lib/lemon-ui/Tooltip' import { dateFilterToText, dateMapping } from 'lib/utils' +import React, { useState } from 'react' import { ToolbarMenu } from '~/toolbar/bar/ToolbarMenu' import { elementsLogic } from '~/toolbar/elements/elementsLogic' import { heatmapLogic } from '~/toolbar/elements/heatmapLogic' import { currentPageLogic } from '~/toolbar/stats/currentPageLogic' +import { toolbarConfigLogic } from '../toolbarConfigLogic' import { useToolbarFeatureFlag } from '../toolbarPosthogJS' const ScrollDepthJSWarning = (): JSX.Element | null => { @@ -40,6 +42,91 @@ const ScrollDepthJSWarning = (): JSX.Element | null => { ) } +const HeatmapsJSWarning = (): JSX.Element | null => { + const { posthog } = useValues(toolbarConfigLogic) + + if (!posthog || posthog?.heatmaps?.isEnabled) { + return null + } + + return ( +

+ {!posthog.heatmaps ? ( + <>The version of posthog-js you are using does not support collecting heatmap data. + ) : !posthog.heatmaps.isEnabled ? ( + <> + Heatmap collection is disabled in your posthog-js configuration. If you do not see heatmap data then + this is likely why. + + ) : null} +

+ ) +} + +const SectionButton = ({ + children, + checked, + onChange, + loading, +}: { + children: React.ReactNode + checked: boolean + onChange: (checked: boolean) => void + loading?: boolean +}): JSX.Element => { + return ( +
+ onChange(!checked)} + sideIcon={} + > + + {children} + + {loading ? : null} + + +
+ ) +} + +const SectionSetting = ({ + children, + title, + info, +}: { + children: React.ReactNode + title: React.ReactNode + info?: React.ReactNode +}): JSX.Element => { + const [showInfo, setShowInfo] = useState(false) + return ( +
+
+ + {title} + + {info && ( + } + size="xsmall" + active={showInfo} + onClick={() => setShowInfo(!showInfo)} + noPadding + /> + )} + +
+ + {showInfo ?
{info}
: null} + + {children} +
+ ) +} + export const HeatmapToolbarMenu = (): JSX.Element => { const { wildcardHref } = useValues(currentPageLogic) const { setWildcardHref, autoWildcardHref } = useActions(currentPageLogic) @@ -109,26 +196,41 @@ export const HeatmapToolbarMenu = (): JSX.Element => { {showNewHeatmaps ? (
- Heatmaps {rawHeatmapLoading ? : null}} + patchHeatmapFilters({ enabled: e, }) } - /> + loading={rawHeatmapLoading} + checked={!!heatmapFilters.enabled} + > + Heatmaps NEW{' '} + {heatmapFilters.enabled && ( <> +

Heatmaps are calculated using additional data sent along with standard events. They are based off of general pointer interactions and might not be 100% accurate to the page you are viewing.

-
- Heatmap type + + + Select the kind of heatmap you want to view. Clicks, rageclicks, and mouse + moves options will show different "heat" based on the number of interactions + at that area of the page. Scroll depth will show how far down the page users + have reached. +
+ Scroll depth uses additional information from Pageview and Pageleave events + to indicate how far down the page users have scrolled. + + } + >
patchHeatmapFilters({ type: e })} @@ -153,19 +255,21 @@ export const HeatmapToolbarMenu = (): JSX.Element => { ]} size="small" /> + + {heatmapFilters.type === 'scrolldepth' && }
+
- {heatmapFilters.type === 'scrolldepth' && ( + -

- Scroll depth uses additional information from Pageview and Pageleave - events to indicate how far down the page users have scrolled. -

- + Heatmaps can be aggregated by total count or unique visitors. Total count + will show the total number of interactions on the page, while unique + visitors will only count each visitor once. - )} - - Aggregation + } + >
patchHeatmapFilters({ aggregation: e })} @@ -183,8 +287,23 @@ export const HeatmapToolbarMenu = (): JSX.Element => { size="small" />
+
- Viewport accuracy + + The viewport accuracy setting will determine how closely the loaded data + will be to your current viewport. +
+ For example if you set this to 100%, only visitors whose viewport width is + identical to yours will be included in the heatmap. +
+ At 90% you will see data from viewports that are 10% smaller or larger than + yours. + + } + >
{ value={heatmapFilters.viewportAccuracy ?? 0} onChange={(value) => patchHeatmapFilters({ viewportAccuracy: value })} /> - - - {`${Math.round((heatmapFilters.viewportAccuracy ?? 1) * 100)}% (${ - viewportRange.min - }px - ${viewportRange.max}px)`} - - + + {`${Math.round((heatmapFilters.viewportAccuracy ?? 1) * 100)}% (${ + viewportRange.min + }px - ${viewportRange.max}px)`} +
+
- {heatmapFilters.type !== 'scrolldepth' ? ( - <> - Fixed positioning calculation -

+ {heatmapFilters.type !== 'scrolldepth' && ( + PostHog JS will attempt to detect fixed elements such as headers or modals and will therefore show those heatmap areas, ignoring the scroll value.
You can choose to show these areas as fixed, include them with scrolled data or hide them altogether. -

- - - - ) : null} -
+ + } + > + + + )} )}
@@ -250,12 +363,13 @@ export const HeatmapToolbarMenu = (): JSX.Element => {
{showNewHeatmaps ? ( - Clickmaps (autocapture) {elementStatsLoading ? : null}} + toggleClickmapsEnabled(e)} - /> + loading={elementStatsLoading} + checked={!!clickmapsEnabled} + > + Clickmaps (autocapture) + ) : null} {(clickmapsEnabled || !showNewHeatmaps) && (