Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Added heatmaps remote opt in #21807

Merged
merged 18 commits into from
Apr 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions frontend/src/lib/api.mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ export const MOCK_DEFAULT_TEAM: TeamType = {
session_replay_config: null,
capture_console_log_opt_in: true,
capture_performance_opt_in: true,
heatmaps_opt_in: true,
autocapture_exceptions_opt_in: false,
autocapture_exceptions_errors_to_ignore: [],
effective_membership_level: OrganizationMembershipLevel.Admin,
Expand Down
6 changes: 6 additions & 0 deletions frontend/src/lib/utils/eventUsageLogic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,7 @@ export const eventUsageLogic = kea<eventUsageLogicType>([
reportIngestionContinueWithoutVerifying: true,
reportAutocaptureToggled: (autocapture_opt_out: boolean) => ({ autocapture_opt_out }),
reportAutocaptureExceptionsToggled: (autocapture_opt_in: boolean) => ({ autocapture_opt_in }),
reportHeatmapsToggled: (heatmaps_opt_in: boolean) => ({ heatmaps_opt_in }),
reportFailedToCreateFeatureFlagWithCohort: (code: string, detail: string) => ({ code, detail }),
reportFeatureFlagCopySuccess: true,
reportFeatureFlagCopyFailure: (error) => ({ error }),
Expand Down Expand Up @@ -1098,6 +1099,11 @@ export const eventUsageLogic = kea<eventUsageLogicType>([
autocapture_opt_in,
})
},
reportHeatmapsToggled: ({ heatmaps_opt_in }) => {
posthog.capture('heatmaps toggled', {
heatmaps_opt_in,
})
},
reportFailedToCreateFeatureFlagWithCohort: ({ detail, code }) => {
posthog.capture('failed to create feature flag with cohort', { detail, code })
},
Expand Down
15 changes: 15 additions & 0 deletions frontend/src/scenes/onboarding/Onboarding.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useActions, useValues } from 'kea'
import { FEATURE_FLAGS, SESSION_REPLAY_MINIMUM_DURATION_OPTIONS } from 'lib/constants'
import { useFeatureFlag } from 'lib/hooks/useFeatureFlag'
import { featureFlagLogic } from 'lib/logic/featureFlagLogic'
import { useEffect, useState } from 'react'
import { AndroidInstructions } from 'scenes/onboarding/sdks/session-replay'
Expand Down Expand Up @@ -81,6 +82,8 @@ const OnboardingWrapper = ({ children }: { children: React.ReactNode }): JSX.Ele
const ProductAnalyticsOnboarding = (): JSX.Element => {
const { currentTeam } = useValues(teamLogic)

const heatmapsEnabled = useFeatureFlag('TOOLBAR_HEATMAPS')

return (
<OnboardingWrapper>
<SDKs
Expand All @@ -101,6 +104,18 @@ const ProductAnalyticsOnboarding = (): JSX.Element => {
type: 'toggle',
inverseToggle: true,
},

heatmapsEnabled
? {
title: 'Enable heatmaps',
description: `If you use our JavaScript libraries, we can capture general clicks, mouse movements,
and scrolling to create heatmaps.
No additional events are created, and you can disable this at any time.`,
teamProperty: 'heatmaps_opt_in',
value: currentTeam?.heatmaps_opt_in ?? true,
benjackwhite marked this conversation as resolved.
Show resolved Hide resolved
type: 'toggle',
}
: undefined,
]}
/>
</OnboardingWrapper>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export const OnboardingProductConfiguration = ({
options,
}: {
stepKey?: OnboardingStepKey
options: ProductConfigOption[]
options: (ProductConfigOption | undefined)[]
}): JSX.Element | null => {
const { configOptions } = useValues(onboardingProductConfigurationLogic)
const { defaultEnabledPlugins } = useValues(pluginsLogic)
Expand All @@ -58,7 +58,7 @@ export const OnboardingProductConfiguration = ({
}, [configOptions])

useEffect(() => {
setConfigOptions(options)
setConfigOptions(options.filter((option): option is ProductConfigOption => !!option))
}, [])

const combinedList: ConfigOption[] = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ import { LemonSelectOptions } from '@posthog/lemon-ui'
import { actions, connect, kea, listeners, path, reducers } from 'kea'
import { teamLogic } from 'scenes/teamLogic'

import { TeamType } from '~/types'

import type { onboardingProductConfigurationLogicType } from './onboardingProductConfigurationLogicType'

export interface ProductConfigOptionBase {
title: string
description: string
teamProperty: string
teamProperty: keyof TeamType
}

export interface ProductConfigurationToggle extends ProductConfigOptionBase {
Expand Down
9 changes: 8 additions & 1 deletion frontend/src/scenes/settings/SettingsMap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { AutocaptureSettings, ExceptionAutocaptureSettings } from './project/Aut
import { CorrelationConfig } from './project/CorrelationConfig'
import { DataAttributes } from './project/DataAttributes'
import { GroupAnalyticsConfig } from './project/GroupAnalyticsConfig'
import { HeatmapsSettings } from './project/HeatmapsSettings'
import { IPAllowListInfo } from './project/IPAllowListInfo'
import { IPCapture } from './project/IPCapture'
import { PathCleaningFiltersConfig } from './project/PathCleaningFiltersConfig'
Expand Down Expand Up @@ -76,14 +77,20 @@ export const SettingsMap: SettingSection[] = [
{
level: 'project',
id: 'project-autocapture',
title: 'Autocapture',
title: 'Autocapture & heatmaps',

settings: [
{
id: 'autocapture',
title: 'Autocapture',
component: <AutocaptureSettings />,
},
{
id: 'heatmaps',
title: 'Heatmaps',
component: <HeatmapsSettings />,
flag: 'TOOLBAR_HEATMAPS',
},
{
id: 'exception-autocapture',
title: 'Exception autocapture',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ exports[`verifiedDomainsLogic values has proper defaults 1`] = `
"effective_membership_level": 8,
"groups_on_events_querying_enabled": true,
"has_group_types": true,
"heatmaps_opt_in": true,
"id": 997,
"ingested_event": true,
"is_demo": false,
Expand Down
40 changes: 40 additions & 0 deletions frontend/src/scenes/settings/project/HeatmapsSettings.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { LemonSwitch } from '@posthog/lemon-ui'
import { useActions, useValues } from 'kea'
import { eventUsageLogic } from 'lib/utils/eventUsageLogic'
import { teamLogic } from 'scenes/teamLogic'
import { userLogic } from 'scenes/userLogic'

export function HeatmapsSettings(): JSX.Element {
const { userLoading } = useValues(userLogic)
const { currentTeam } = useValues(teamLogic)
const { updateCurrentTeam } = useActions(teamLogic)
const { reportHeatmapsToggled } = useActions(eventUsageLogic)

return (
<>
<p>
If you use our JavaScript libraries, we can capture general clicks, mouse movements, and scrolling to
create heatmaps. No additional events are created, and you can disable this at any time.
<br />
Whereas Autocapture creates events whenever it can uniquely identify an interacted element, heatmaps are
generated based on overall mouse or touch positions and are useful for understanding more general user
behavior across your site.
benjackwhite marked this conversation as resolved.
Show resolved Hide resolved
</p>
<div className="space-y-2">
<LemonSwitch
id="posthog-heatmaps-switch"
onChange={(checked) => {
updateCurrentTeam({
heatmaps_opt_in: checked,
})
reportHeatmapsToggled(checked)
}}
checked={!!currentTeam?.heatmaps_opt_in}
disabled={userLoading}
label="Enable heatmaps for web"
bordered
/>
</div>
</>
)
}
1 change: 1 addition & 0 deletions frontend/src/scenes/settings/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ export type SettingId =
| 'optout'
| 'theme'
| 'replay-ai-config'
| 'heatmaps'

export type Setting = {
id: SettingId
Expand Down
5 changes: 4 additions & 1 deletion frontend/src/scenes/teamActivityDescriber.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,10 @@ const teamActionsMapping: Record<
autocapture_exceptions_errors_to_ignore: () => null,
autocapture_exceptions_opt_in: () => null,
autocapture_opt_out(change: ActivityChange | undefined): ChangeMapping | null {
return { description: [<>{change?.after ? 'enabled' : 'disabled'} autocapture</>] }
return { description: [<>{change?.after ? 'opted in to' : 'opted out of'} autocapture</>] }
},
heatmaps_opt_in(change: ActivityChange | undefined): ChangeMapping | null {
return { description: [<>{change?.after ? 'enabled' : 'disabled'} heatmaps</>] }
},
// and.... many more
name(change: ActivityChange | undefined): ChangeMapping | null {
Expand Down
1 change: 1 addition & 0 deletions frontend/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,7 @@ export interface TeamType extends TeamBasicType {
session_replay_config: { record_canvas?: boolean; ai_config?: SessionRecordingAIConfig } | undefined | null
autocapture_exceptions_opt_in: boolean
surveys_opt_in?: boolean
heatmaps_opt_in?: boolean
autocapture_exceptions_errors_to_ignore: string[]
test_account_filters: AnyPropertyFilter[]
test_account_filters_default_checked: boolean
Expand Down
2 changes: 1 addition & 1 deletion latest_migrations.manifest
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ contenttypes: 0002_remove_content_type_name
ee: 0016_rolemembership_organization_member
otp_static: 0002_throttling
otp_totp: 0002_auto_20190420_0723
posthog: 0404_remove_propertydefinition_property_type_is_valid_and_more
posthog: 0405_team_heatmaps_opt_in
sessions: 0001_initial
social_django: 0010_uid_db_index
two_factor: 0007_auto_20201201_1019
5 changes: 2 additions & 3 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions posthog/api/decide.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ def get_decide(request: HttpRequest):
response["sessionRecording"] = _session_recording_config_response(request, team)

response["surveys"] = True if team.surveys_opt_in else False
response["heatmaps"] = True if team.heatmaps_opt_in else False

site_apps = []
# errors mean the database is unavailable, bail in this case
Expand Down
2 changes: 2 additions & 0 deletions posthog/api/team.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ class Meta:
"recording_domains",
"inject_web_apps",
"surveys_opt_in",
"heatmaps_opt_in",
]


Expand Down Expand Up @@ -166,6 +167,7 @@ class Meta:
"extra_settings",
"has_completed_onboarding_for",
"surveys_opt_in",
"heatmaps_opt_in",
)
read_only_fields = (
"id",
Expand Down
3 changes: 3 additions & 0 deletions posthog/api/test/__snapshots__/test_action.ambr
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"posthog_team"."capture_console_log_opt_in",
"posthog_team"."capture_performance_opt_in",
"posthog_team"."surveys_opt_in",
"posthog_team"."heatmaps_opt_in",
"posthog_team"."session_recording_version",
"posthog_team"."signup_token",
"posthog_team"."is_demo",
Expand Down Expand Up @@ -220,6 +221,7 @@
"posthog_team"."capture_console_log_opt_in",
"posthog_team"."capture_performance_opt_in",
"posthog_team"."surveys_opt_in",
"posthog_team"."heatmaps_opt_in",
"posthog_team"."session_recording_version",
"posthog_team"."signup_token",
"posthog_team"."is_demo",
Expand Down Expand Up @@ -563,6 +565,7 @@
"posthog_team"."capture_console_log_opt_in",
"posthog_team"."capture_performance_opt_in",
"posthog_team"."surveys_opt_in",
"posthog_team"."heatmaps_opt_in",
"posthog_team"."session_recording_version",
"posthog_team"."signup_token",
"posthog_team"."is_demo",
Expand Down
3 changes: 3 additions & 0 deletions posthog/api/test/__snapshots__/test_annotation.ambr
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"posthog_team"."capture_console_log_opt_in",
"posthog_team"."capture_performance_opt_in",
"posthog_team"."surveys_opt_in",
"posthog_team"."heatmaps_opt_in",
"posthog_team"."session_recording_version",
"posthog_team"."signup_token",
"posthog_team"."is_demo",
Expand Down Expand Up @@ -142,6 +143,7 @@
"posthog_team"."capture_console_log_opt_in",
"posthog_team"."capture_performance_opt_in",
"posthog_team"."surveys_opt_in",
"posthog_team"."heatmaps_opt_in",
"posthog_team"."session_recording_version",
"posthog_team"."signup_token",
"posthog_team"."is_demo",
Expand Down Expand Up @@ -479,6 +481,7 @@
"posthog_team"."capture_console_log_opt_in",
"posthog_team"."capture_performance_opt_in",
"posthog_team"."surveys_opt_in",
"posthog_team"."heatmaps_opt_in",
"posthog_team"."session_recording_version",
"posthog_team"."signup_token",
"posthog_team"."is_demo",
Expand Down
4 changes: 4 additions & 0 deletions posthog/api/test/__snapshots__/test_decide.ambr
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
"posthog_team"."capture_console_log_opt_in",
"posthog_team"."capture_performance_opt_in",
"posthog_team"."surveys_opt_in",
"posthog_team"."heatmaps_opt_in",
"posthog_team"."session_recording_version",
"posthog_team"."signup_token",
"posthog_team"."is_demo",
Expand Down Expand Up @@ -311,6 +312,7 @@
"posthog_team"."capture_console_log_opt_in",
"posthog_team"."capture_performance_opt_in",
"posthog_team"."surveys_opt_in",
"posthog_team"."heatmaps_opt_in",
"posthog_team"."session_recording_version",
"posthog_team"."signup_token",
"posthog_team"."is_demo",
Expand Down Expand Up @@ -473,6 +475,7 @@
"posthog_team"."capture_console_log_opt_in",
"posthog_team"."capture_performance_opt_in",
"posthog_team"."surveys_opt_in",
"posthog_team"."heatmaps_opt_in",
"posthog_team"."session_recording_version",
"posthog_team"."signup_token",
"posthog_team"."is_demo",
Expand Down Expand Up @@ -628,6 +631,7 @@
"posthog_team"."capture_console_log_opt_in",
"posthog_team"."capture_performance_opt_in",
"posthog_team"."surveys_opt_in",
"posthog_team"."heatmaps_opt_in",
"posthog_team"."session_recording_version",
"posthog_team"."signup_token",
"posthog_team"."is_demo",
Expand Down
2 changes: 2 additions & 0 deletions posthog/api/test/__snapshots__/test_early_access_feature.ambr
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"posthog_team"."capture_console_log_opt_in",
"posthog_team"."capture_performance_opt_in",
"posthog_team"."surveys_opt_in",
"posthog_team"."heatmaps_opt_in",
"posthog_team"."session_recording_version",
"posthog_team"."signup_token",
"posthog_team"."is_demo",
Expand Down Expand Up @@ -164,6 +165,7 @@
"posthog_team"."capture_console_log_opt_in",
"posthog_team"."capture_performance_opt_in",
"posthog_team"."surveys_opt_in",
"posthog_team"."heatmaps_opt_in",
"posthog_team"."session_recording_version",
"posthog_team"."signup_token",
"posthog_team"."is_demo",
Expand Down
1 change: 1 addition & 0 deletions posthog/api/test/__snapshots__/test_element.ambr
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"posthog_team"."capture_console_log_opt_in",
"posthog_team"."capture_performance_opt_in",
"posthog_team"."surveys_opt_in",
"posthog_team"."heatmaps_opt_in",
"posthog_team"."session_recording_version",
"posthog_team"."signup_token",
"posthog_team"."is_demo",
Expand Down
Loading
Loading