Skip to content

Commit

Permalink
feat: add dead clicks functionality (#25810)
Browse files Browse the repository at this point in the history
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
  • Loading branch information
pauldambra and github-actions[bot] authored Oct 31, 2024
1 parent e646260 commit ccc2056
Show file tree
Hide file tree
Showing 38 changed files with 306 additions and 4 deletions.
1 change: 1 addition & 0 deletions bin/copy-posthog-js
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ cp node_modules/posthog-js/dist/recorder-v2.js* frontend/dist/
cp node_modules/posthog-js/dist/surveys.js* frontend/dist/
cp node_modules/posthog-js/dist/exception-autocapture.js* frontend/dist/
cp node_modules/posthog-js/dist/web-vitals.js* frontend/dist/
cp node_modules/posthog-js/dist/dead-clicks-autocapture.js* frontend/dist/
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.
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.
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 @@ -90,6 +90,7 @@ export const MOCK_DEFAULT_TEAM: TeamType = {
live_events_columns: null,
person_on_events_querying_enabled: true,
live_events_token: '123',
capture_dead_clicks: false,
}

export const MOCK_DEFAULT_PROJECT: ProjectType = {
Expand Down
1 change: 1 addition & 0 deletions frontend/src/lib/constants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ export const FEATURE_FLAGS = {
EXPERIMENTS_HOLDOUTS: 'experiments-holdouts', // owner: @jurajmajerik #team-experiments
MESSAGING: 'messaging', // owner @mariusandra #team-cdp
SESSION_REPLAY_URL_BLOCKLIST: 'session-replay-url-blocklist', // owner: @richard-better #team-replay
DEAD_CLICKS_AUTOCAPTURE: 'dead-clicks-autocapture', // owner: @pauldambra #team-replay
} as const
export type FeatureFlagKey = (typeof FEATURE_FLAGS)[keyof typeof FEATURE_FLAGS]

Expand Down
45 changes: 45 additions & 0 deletions frontend/src/lib/taxonomy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,10 @@ export const CORE_FILTER_DEFINITIONS_BY_GROUP = {
label: 'Rageclick',
description: 'A user has rapidly and repeatedly clicked in a single place',
},
$dead_click: {
label: 'Dead click',
description: 'A user has clicked on something that is probably not clickable',
},
$exception: {
label: 'Exception',
description: 'Automatically captured exceptions from the client Sentry integration',
Expand Down Expand Up @@ -1216,6 +1220,47 @@ export const CORE_FILTER_DEFINITIONS_BY_GROUP = {
label: 'Surveys Activated',
description: 'The surveys that were activated for this event.',
},
$dead_click_scroll_delay_ms: {
label: 'Dead click scroll delay in milliseconds',
description: 'The delay between a click and the next scroll event',
},
$dead_click_mutation_delay_ms: {
label: 'Dead click mutation delay in milliseconds',
description: 'The delay between a click and the next mutation event',
},
$dead_click_absolute_delay_ms: {
label: 'Dead click absolute delay in milliseconds',
description: 'The delay between a click and having seen no activity at all',
},
$dead_click_selection_changed_delay_ms: {
label: 'Dead click selection changed delay in milliseconds',
description: 'The delay between a click and the next text selection change event',
},
$dead_click_last_mutation_timestamp: {
label: 'Dead click last mutation timestamp',
description: 'debug signal time of the last mutation seen by dead click autocapture',
},
$dead_click_event_timestamp: {
label: 'Dead click event timestamp',
description: 'debug signal time of the event that triggered dead click autocapture',
},
$dead_click_scroll_timeout: {
label: 'Dead click scroll timeout',
description: 'whether the dead click autocapture passed the threshold for waiting for a scroll event',
},
$dead_click_mutation_timeout: {
label: 'Dead click mutation timeout',
description: 'whether the dead click autocapture passed the threshold for waiting for a mutation event',
},
$dead_click_absolute_timeout: {
label: 'Dead click absolute timeout',
description: 'whether the dead click autocapture passed the threshold for waiting for any activity',
},
$dead_click_selection_changed_timeout: {
label: 'Dead click selection changed timeout',
description:
'whether the dead click autocapture passed the threshold for waiting for a text selection change event',
},
},
numerical_event_properties: {}, // Same as event properties, see assignment below
person_properties: {}, // Currently person properties are the same as event properties, see assignment below
Expand Down
13 changes: 10 additions & 3 deletions frontend/src/scenes/settings/SettingsMap.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { BounceRatePageViewModeSetting } from 'scenes/settings/environment/BounceRatePageViewMode'
import { DeadClicksAutocaptureSettings } from 'scenes/settings/environment/DeadClicksAutocaptureSettings'
import { PersonsJoinMode } from 'scenes/settings/environment/PersonsJoinMode'
import { PersonsOnEvents } from 'scenes/settings/environment/PersonsOnEvents'
import { SessionsTableVersion } from 'scenes/settings/environment/SessionsTableVersion'
Expand Down Expand Up @@ -101,6 +102,11 @@ export const SETTINGS_MAP: SettingSection[] = [
title: 'Autocapture',
component: <AutocaptureSettings />,
},
{
id: 'autocapture-data-attributes',
title: 'Data attributes',
component: <DataAttributes />,
},
{
id: 'heatmaps',
title: 'Heatmaps',
Expand All @@ -118,9 +124,10 @@ export const SETTINGS_MAP: SettingSection[] = [
component: <WebVitalsAutocaptureSettings />,
},
{
id: 'autocapture-data-attributes',
title: 'Data attributes',
component: <DataAttributes />,
id: 'dead-clicks-autocapture',
title: 'Dead clicks autocapture',
component: <DeadClicksAutocaptureSettings />,
flag: 'DEAD_CLICKS_AUTOCAPTURE',
},
],
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { LemonSwitch } from '@posthog/lemon-ui'
import { useActions, useValues } from 'kea'
import posthog from 'posthog-js'
import { teamLogic } from 'scenes/teamLogic'
import { userLogic } from 'scenes/userLogic'

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

return (
<>
<p>
A dead click is a click that doesn't result in any action. E.g. an image that looks like a button. Your
user clicks it, nothing happens, they get frustrated and close the tab, and you missed a sale.
</p>
<p>
We track clicks that aren't followed by a scroll, text selection change, or DOM mutation and report them
so you can see where your users are getting stuck.
</p>
<div className="space-y-2">
<LemonSwitch
id="posthog-deadclicks-switch"
onChange={(checked) => {
updateCurrentTeam({
capture_dead_clicks: checked,
})
posthog.capture('dead_clicks_autocapture_toggled', { isEnabled: checked })
}}
checked={!!currentTeam?.capture_dead_clicks}
disabled={userLoading}
label="Enable dead clicks autocapture"
bordered
/>
</div>
</>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ exports[`verifiedDomainsLogic values has proper defaults 1`] = `
"autocapture_opt_out": true,
"autocapture_web_vitals_opt_in": false,
"capture_console_log_opt_in": true,
"capture_dead_clicks": false,
"capture_performance_opt_in": true,
"completed_snippet_onboarding": true,
"correlation_config": {
Expand Down
1 change: 1 addition & 0 deletions frontend/src/scenes/settings/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ export type SettingId =
| 'bounce-rate-page-view-mode'
| 'session-table-version'
| 'web-vitals-autocapture'
| 'dead-clicks-autocapture'

type FeatureFlagKey = keyof typeof FEATURE_FLAGS

Expand Down
5 changes: 5 additions & 0 deletions frontend/src/scenes/teamActivityDescriber.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ const teamActionsMapping: Record<
],
}
},
capture_dead_clicks(change: ActivityChange | undefined): ChangeMapping | null {
return {
description: [<>{change?.after ? 'enabled' : 'disabled'} dead clicks autocapture</>],
}
},
recording_domains(change: ActivityChange | undefined): ChangeMapping | null {
const before: string[] | null = Array.isArray(change?.before) ? change!.before : null
const after: string[] | null = Array.isArray(change?.after) ? change!.after : 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 @@ -504,6 +504,7 @@ export interface TeamType extends TeamBasicType {
// These fields in the database accept null values and were previously set to NULL by default
capture_console_log_opt_in: boolean | null
capture_performance_opt_in: boolean | null
capture_dead_clicks: boolean | null
// a string representation of the decimal value between 0 and 1
session_recording_sample_rate: string
session_recording_minimum_duration_milliseconds: number | null
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: 0503_experimentsavedmetric_experimenttosavedmetric_and_more
posthog: 0504_add_dead_clicks_setting
sessions: 0001_initial
social_django: 0010_uid_db_index
two_factor: 0007_auto_20201201_1019
2 changes: 2 additions & 0 deletions posthog/api/decide.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,8 @@ def get_decide(request: HttpRequest):
else:
response["featureFlags"] = {}

response["captureDeadClicks"] = True if team.capture_dead_clicks else False

capture_network_timing = True if team.capture_performance_opt_in else False
capture_web_vitals = True if team.autocapture_web_vitals_opt_in else False
autocapture_web_vitals_allowed_metrics = None
Expand Down
2 changes: 2 additions & 0 deletions posthog/api/team.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ class Meta:
"inject_web_apps",
"surveys_opt_in",
"heatmaps_opt_in",
"capture_dead_clicks",
]


Expand Down Expand Up @@ -184,6 +185,7 @@ class Meta:
"heatmaps_opt_in",
"live_events_token",
"product_intents",
"capture_dead_clicks",
)
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 @@ -64,6 +64,7 @@
"posthog_team"."survey_config",
"posthog_team"."capture_console_log_opt_in",
"posthog_team"."capture_performance_opt_in",
"posthog_team"."capture_dead_clicks",
"posthog_team"."surveys_opt_in",
"posthog_team"."heatmaps_opt_in",
"posthog_team"."session_recording_version",
Expand Down Expand Up @@ -157,6 +158,7 @@
"posthog_team"."survey_config",
"posthog_team"."capture_console_log_opt_in",
"posthog_team"."capture_performance_opt_in",
"posthog_team"."capture_dead_clicks",
"posthog_team"."surveys_opt_in",
"posthog_team"."heatmaps_opt_in",
"posthog_team"."session_recording_version",
Expand Down Expand Up @@ -482,6 +484,7 @@
"posthog_team"."survey_config",
"posthog_team"."capture_console_log_opt_in",
"posthog_team"."capture_performance_opt_in",
"posthog_team"."capture_dead_clicks",
"posthog_team"."surveys_opt_in",
"posthog_team"."heatmaps_opt_in",
"posthog_team"."session_recording_version",
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 @@ -64,6 +64,7 @@
"posthog_team"."survey_config",
"posthog_team"."capture_console_log_opt_in",
"posthog_team"."capture_performance_opt_in",
"posthog_team"."capture_dead_clicks",
"posthog_team"."surveys_opt_in",
"posthog_team"."heatmaps_opt_in",
"posthog_team"."session_recording_version",
Expand Down Expand Up @@ -125,6 +126,7 @@
"posthog_team"."survey_config",
"posthog_team"."capture_console_log_opt_in",
"posthog_team"."capture_performance_opt_in",
"posthog_team"."capture_dead_clicks",
"posthog_team"."surveys_opt_in",
"posthog_team"."heatmaps_opt_in",
"posthog_team"."session_recording_version",
Expand Down Expand Up @@ -383,6 +385,7 @@
"posthog_team"."survey_config",
"posthog_team"."capture_console_log_opt_in",
"posthog_team"."capture_performance_opt_in",
"posthog_team"."capture_dead_clicks",
"posthog_team"."surveys_opt_in",
"posthog_team"."heatmaps_opt_in",
"posthog_team"."session_recording_version",
Expand Down
8 changes: 8 additions & 0 deletions posthog/api/test/__snapshots__/test_decide.ambr
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,7 @@
"posthog_team"."survey_config",
"posthog_team"."capture_console_log_opt_in",
"posthog_team"."capture_performance_opt_in",
"posthog_team"."capture_dead_clicks",
"posthog_team"."surveys_opt_in",
"posthog_team"."heatmaps_opt_in",
"posthog_team"."session_recording_version",
Expand Down Expand Up @@ -475,6 +476,7 @@
"posthog_team"."survey_config",
"posthog_team"."capture_console_log_opt_in",
"posthog_team"."capture_performance_opt_in",
"posthog_team"."capture_dead_clicks",
"posthog_team"."surveys_opt_in",
"posthog_team"."heatmaps_opt_in",
"posthog_team"."session_recording_version",
Expand Down Expand Up @@ -581,6 +583,7 @@
"posthog_team"."survey_config",
"posthog_team"."capture_console_log_opt_in",
"posthog_team"."capture_performance_opt_in",
"posthog_team"."capture_dead_clicks",
"posthog_team"."surveys_opt_in",
"posthog_team"."heatmaps_opt_in",
"posthog_team"."session_recording_version",
Expand Down Expand Up @@ -682,6 +685,7 @@
"posthog_team"."survey_config",
"posthog_team"."capture_console_log_opt_in",
"posthog_team"."capture_performance_opt_in",
"posthog_team"."capture_dead_clicks",
"posthog_team"."surveys_opt_in",
"posthog_team"."heatmaps_opt_in",
"posthog_team"."session_recording_version",
Expand Down Expand Up @@ -842,6 +846,7 @@
"posthog_team"."survey_config",
"posthog_team"."capture_console_log_opt_in",
"posthog_team"."capture_performance_opt_in",
"posthog_team"."capture_dead_clicks",
"posthog_team"."surveys_opt_in",
"posthog_team"."heatmaps_opt_in",
"posthog_team"."session_recording_version",
Expand Down Expand Up @@ -943,6 +948,7 @@
"posthog_team"."survey_config",
"posthog_team"."capture_console_log_opt_in",
"posthog_team"."capture_performance_opt_in",
"posthog_team"."capture_dead_clicks",
"posthog_team"."surveys_opt_in",
"posthog_team"."heatmaps_opt_in",
"posthog_team"."session_recording_version",
Expand Down Expand Up @@ -1108,6 +1114,7 @@
"posthog_team"."survey_config",
"posthog_team"."capture_console_log_opt_in",
"posthog_team"."capture_performance_opt_in",
"posthog_team"."capture_dead_clicks",
"posthog_team"."surveys_opt_in",
"posthog_team"."heatmaps_opt_in",
"posthog_team"."session_recording_version",
Expand Down Expand Up @@ -1227,6 +1234,7 @@
"posthog_team"."survey_config",
"posthog_team"."capture_console_log_opt_in",
"posthog_team"."capture_performance_opt_in",
"posthog_team"."capture_dead_clicks",
"posthog_team"."surveys_opt_in",
"posthog_team"."heatmaps_opt_in",
"posthog_team"."session_recording_version",
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 @@ -32,6 +32,7 @@
"posthog_team"."survey_config",
"posthog_team"."capture_console_log_opt_in",
"posthog_team"."capture_performance_opt_in",
"posthog_team"."capture_dead_clicks",
"posthog_team"."surveys_opt_in",
"posthog_team"."heatmaps_opt_in",
"posthog_team"."session_recording_version",
Expand Down Expand Up @@ -178,6 +179,7 @@
"posthog_team"."survey_config",
"posthog_team"."capture_console_log_opt_in",
"posthog_team"."capture_performance_opt_in",
"posthog_team"."capture_dead_clicks",
"posthog_team"."surveys_opt_in",
"posthog_team"."heatmaps_opt_in",
"posthog_team"."session_recording_version",
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 @@ -64,6 +64,7 @@
"posthog_team"."survey_config",
"posthog_team"."capture_console_log_opt_in",
"posthog_team"."capture_performance_opt_in",
"posthog_team"."capture_dead_clicks",
"posthog_team"."surveys_opt_in",
"posthog_team"."heatmaps_opt_in",
"posthog_team"."session_recording_version",
Expand Down
Loading

0 comments on commit ccc2056

Please sign in to comment.