diff --git a/frontend/src/lib/taxonomy.tsx b/frontend/src/lib/taxonomy.tsx
index 595374cd33a8b2..4afbee8789f021 100644
--- a/frontend/src/lib/taxonomy.tsx
+++ b/frontend/src/lib/taxonomy.tsx
@@ -3,8 +3,31 @@ import { CoreFilterDefinition, PropertyFilterValue } from '~/types'
import { TaxonomicFilterGroupType } from './components/TaxonomicFilter/types'
import { Link } from './lemon-ui/Link'
+/** Same as https://github.com/PostHog/posthog-js/blob/master/src/utils/event-utils.ts */
+// Ideally this would be imported from posthog-js, we just need to start exporting the list there
+const CAMPAIGN_PROPERTIES: string[] = [
+ 'utm_source',
+ 'utm_medium',
+ 'utm_campaign',
+ 'utm_content',
+ 'utm_term',
+ 'gclid', // google ads
+ 'gad_source', // google ads
+ 'gclsrc', // google ads 360
+ 'dclid', // google display ads
+ 'gbraid', // google ads, web to app
+ 'wbraid', // google ads, app to web
+ 'fbclid', // facebook
+ 'msclkid', // microsoft
+ 'twclid', // twitter
+ 'li_fat_id', // linkedin
+ 'mc_cid', // mailchimp campaign id
+ 'igshid', // instagram
+ 'ttclid', // tiktok
+]
+
// copy from https://github.com/PostHog/posthog/blob/29ac8d6b2ba5de4b65a148136b681b8e52e20429/plugin-server/src/utils/db/utils.ts#L44
-const eventToPersonProperties = new Set([
+const PERSON_PROPERTIES_ADAPTED_FROM_EVENT = new Set([
// mobile params
'$app_build',
'$app_name',
@@ -20,21 +43,11 @@ const eventToPersonProperties = new Set([
'$os_version',
'$referring_domain',
'$referrer',
- // campaign params - automatically added by posthog-js here https://github.com/PostHog/posthog-js/blob/master/src/utils/event-utils.ts
- 'utm_source',
- 'utm_medium',
- 'utm_campaign',
- 'utm_content',
- 'utm_name',
- 'utm_term',
- 'gclid',
- 'gad_source',
- 'gbraid',
- 'wbraid',
- 'fbclid',
- 'msclkid',
+ ...CAMPAIGN_PROPERTIES,
])
+const SESSION_PROPERTIES_ADAPTED_FROM_EVENT = new Set(['$referrering_domain', ...CAMPAIGN_PROPERTIES])
+
// If adding event properties with labels, check whether they should be added to
// PROPERTY_NAME_ALIASES in posthog/api/property_definition.py
// see code to output JSON below this
@@ -941,101 +954,11 @@ export const CORE_FILTER_DEFINITIONS_BY_GROUP = {
description: The last URL visited in this session,
examples: ['https://example.com/interesting-article?parameter=true'],
},
- $initial_utm_source: {
- label: 'Initial UTM source',
- description: The UTM source (if any) of the first URL visited during this session,
- examples: ['Google', 'Bing', 'Twitter', 'Facebook'],
- },
- $initial_utm_medium: {
- label: 'Initial UTM medium',
- description: The UTM medium (if any) of the first URL visited during this session,
- examples: ['Social', 'Organic', 'Paid', 'Email'],
- },
- $initial_utm_campaign: {
- label: 'Initial UTM campaign',
- description: The UTM campaign (if any) of the first URL visited during this session,
- examples: ['feature launch', 'discount'],
- },
- $initial_utm_content: {
- label: 'Initial UTM content',
- description: The UTM content (if any) of the first URL visited during this session,
- examples: ['bottom link', 'second button'],
- },
- $initial_utm_term: {
- label: 'Initial UTM term',
- description: The UTM term (if any) of the first URL visited during this session,
- examples: ['free goodies'],
- },
$initial_referrering_domain: {
label: 'Initial referrer',
description: Domain of where the user came from.,
examples: ['google.com', 'facebook.com'],
},
- $initial_gclid: {
- label: 'Initial gclid',
- description: The gclid (Google Click ID) of this session,
- examples: ['123xyz'],
- },
- $initial_gad_source: {
- label: 'Initial gad_source',
- description: The gad_source (Google Ad source) of this session,
- examples: ['123xyz'],
- },
- $initial_gclsrc: {
- label: 'Initial gclsrc',
- description: The gclsrc (Google Search Ads 360 click source) of this session,
- examples: ['123xyz'],
- },
- $initial_dclid: {
- label: 'Initial dclid',
- description: The dclid (DoubleClick Id) of this session,
- examples: ['123xyz'],
- },
- $initial_gbraid: {
- label: 'Initial gBraid',
- description: The gBraid (Google App-to-web Measurement ID ) of this session,
- examples: ['123xyz'],
- },
- $initial_wbraid: {
- label: 'Initial wBraid',
- description: The wBraid (Google Web-to-app Measurement ID) of this session,
- examples: ['123xyz'],
- },
- $initial_fbclid: {
- label: 'Initial fbclid',
- description: The fbclid (Facebook Click ID) of this session,
- examples: ['123xyz'],
- },
- $initial_msclkid: {
- label: 'Initial msclkid',
- description: The msclkid (Microsoft Click ID) of this session,
- examples: ['123xyz'],
- },
- $initial_twclid: {
- label: 'Initial twclid',
- description: The twclid (Twitter Click ID) of this session,
- examples: ['123xyz'],
- },
- $initial_li_fat_id: {
- label: 'Initial li_fat_id',
- description: The twclid (LinkedIn First-Party Ad Tracking ID) of this session,
- examples: ['123xyz'],
- },
- $initial_mc_cid: {
- label: 'Initial mc_cid',
- description: The mc_cid (MailChimp Campaign ID) of this session,
- examples: ['123xyz'],
- },
- $initial_igshid: {
- label: 'Initial igshid',
- description: The igshid (Instagram Share ID) of this session,
- examples: ['123xyz'],
- },
- $initial_ttclid: {
- label: 'Initial ttclid',
- description: The twclid (Twitter Click ID) of this session,
- examples: ['123xyz'],
- },
$pageview_count: {
label: 'Pageview count',
description: The number of page view events in this session,
@@ -1063,36 +986,42 @@ export const CORE_FILTER_DEFINITIONS_BY_GROUP = {
CORE_FILTER_DEFINITIONS_BY_GROUP.numerical_event_properties = CORE_FILTER_DEFINITIONS_BY_GROUP.event_properties
// add distinct_id to event properties before copying to person properties so it exists in person properties as well
CORE_FILTER_DEFINITIONS_BY_GROUP.event_properties.distinct_id = CORE_FILTER_DEFINITIONS_BY_GROUP.metadata.distinct_id
-CORE_FILTER_DEFINITIONS_BY_GROUP.person_properties = Object.fromEntries(
- Object.entries(CORE_FILTER_DEFINITIONS_BY_GROUP.event_properties).flatMap(([key, value]) =>
- eventToPersonProperties.has(key) || key.startsWith('$geoip_')
- ? [
- [
- key,
- {
- ...value,
- label: `Latest ${value.label}`,
- description:
- 'description' in value
- ? `${value.description} Data from the last time this user was seen.`
- : 'Data from the last time this user was seen.',
- },
- ],
- [
- `$initial_${key.replace(/^\$/, '')}`,
- {
- ...value,
- label: `Initial ${value.label}`,
- description:
- 'description' in value
- ? `${value.description} Data from the first time this user was seen.`
- : 'Data from the first time this user was seen.',
- },
- ],
- ]
- : [[key, value]]
- )
-)
+
+CORE_FILTER_DEFINITIONS_BY_GROUP.person_properties = {}
+
+for (const [key, value] of Object.entries(CORE_FILTER_DEFINITIONS_BY_GROUP.event_properties)) {
+ if (PERSON_PROPERTIES_ADAPTED_FROM_EVENT.has(key) || key.startsWith('$geoip_')) {
+ CORE_FILTER_DEFINITIONS_BY_GROUP.person_properties[key] = {
+ ...value,
+ label: `Latest ${value.label}`,
+ description:
+ 'description' in value
+ ? `${value.description} Data from the last time this user was seen.`
+ : 'Data from the last time this user was seen.',
+ }
+
+ CORE_FILTER_DEFINITIONS_BY_GROUP.person_properties[`$initial_${key.replace(/^\$/, '')}`] = {
+ ...value,
+ label: `Initial ${value.label}`,
+ description:
+ 'description' in value
+ ? `${value.description} Data from the first time this user was seen.`
+ : 'Data from the first time this user was seen.',
+ }
+ } else {
+ CORE_FILTER_DEFINITIONS_BY_GROUP.person_properties[key] = value
+ }
+ if (SESSION_PROPERTIES_ADAPTED_FROM_EVENT.has(key)) {
+ CORE_FILTER_DEFINITIONS_BY_GROUP.sessions[`$initial_${key.replace(/^\$/, '')}`] = {
+ ...value,
+ label: `Initial ${value.label}`,
+ description:
+ 'description' in value
+ ? `${value.description} First value seen in the session.`
+ : 'First value seen in the session.',
+ }
+ }
+}
// We treat `$session_duration` as an event property in the context of series `math`, but it's fake in a sense
CORE_FILTER_DEFINITIONS_BY_GROUP.event_properties.$session_duration =
CORE_FILTER_DEFINITIONS_BY_GROUP.sessions.$session_duration