Skip to content

Commit

Permalink
feat(hogql): add funnel correlation actor queries (#20726)
Browse files Browse the repository at this point in the history
  • Loading branch information
thmsobrmlr authored Mar 12, 2024
1 parent 587bcfb commit 2bd43f2
Show file tree
Hide file tree
Showing 18 changed files with 6,807 additions and 854 deletions.
50 changes: 43 additions & 7 deletions frontend/src/queries/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@
{
"$ref": "#/definitions/FunnelsActorsQuery"
},
{
"$ref": "#/definitions/FunnelCorrelationActorsQuery"
},
{
"$ref": "#/definitions/HogQLQuery"
}
Expand Down Expand Up @@ -1564,6 +1567,38 @@
"enum": ["second", "minute", "hour", "day", "week", "month"],
"type": "string"
},
"FunnelCorrelationActorsQuery": {
"additionalProperties": false,
"properties": {
"funnelCorrelationPersonConverted": {
"type": "boolean"
},
"funnelCorrelationPersonEntity": {
"$ref": "#/definitions/AnyEntityNode"
},
"funnelCorrelationPropertyValues": {
"items": {
"$ref": "#/definitions/AnyPropertyFilter"
},
"type": "array"
},
"includeRecordings": {
"type": "boolean"
},
"kind": {
"const": "FunnelCorrelationActorsQuery",
"type": "string"
},
"response": {
"$ref": "#/definitions/ActorsQueryResponse"
},
"source": {
"$ref": "#/definitions/FunnelCorrelationQuery"
}
},
"required": ["kind", "source"],
"type": "object"
},
"FunnelCorrelationQuery": {
"additionalProperties": false,
"properties": {
Expand Down Expand Up @@ -1643,9 +1678,7 @@
"type": "array"
},
"types": {
"items": {
"type": "string"
},
"items": {},
"type": "array"
}
},
Expand Down Expand Up @@ -1983,7 +2016,7 @@
"type": "boolean"
},
"kind": {
"const": "InsightActorsQuery",
"const": "FunnelsActorsQuery",
"type": "string"
},
"response": {
Expand Down Expand Up @@ -2663,6 +2696,9 @@
},
{
"$ref": "#/definitions/FunnelsActorsQuery"
},
{
"$ref": "#/definitions/FunnelCorrelationActorsQuery"
}
]
}
Expand Down Expand Up @@ -3118,6 +3154,8 @@
"HogQLMetadata",
"HogQLAutocomplete",
"ActorsQuery",
"FunnelsActorsQuery",
"FunnelCorrelationActorsQuery",
"SessionsTimelineQuery",
"DataTableNode",
"DataVisualizationNode",
Expand Down Expand Up @@ -4266,9 +4304,7 @@
"type": "array"
},
"types": {
"items": {
"type": "string"
},
"items": {},
"type": "array"
}
},
Expand Down
18 changes: 14 additions & 4 deletions frontend/src/queries/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ export enum NodeKind {
HogQLMetadata = 'HogQLMetadata',
HogQLAutocomplete = 'HogQLAutocomplete',
ActorsQuery = 'ActorsQuery',
FunnelsActorsQuery = 'FunnelsActorsQuery',
FunnelCorrelationActorsQuery = 'FunnelCorrelationActorsQuery',
SessionsTimelineQuery = 'SessionsTimelineQuery',

// Interface nodes
Expand Down Expand Up @@ -921,7 +923,7 @@ export interface ActorsQueryResponse {

export interface ActorsQuery extends DataNode {
kind: NodeKind.ActorsQuery
source?: InsightActorsQuery | FunnelsActorsQuery | HogQLQuery
source?: InsightActorsQuery | FunnelsActorsQuery | FunnelCorrelationActorsQuery | HogQLQuery
select?: HogQLExpression[]
search?: string
properties?: AnyPropertyFilter[]
Expand Down Expand Up @@ -1090,7 +1092,7 @@ export interface InsightActorsQuery<T extends InsightsQueryBase = InsightQuerySo
}

export interface FunnelsActorsQuery extends InsightActorsQueryBase {
kind: NodeKind.InsightActorsQuery
kind: NodeKind.FunnelsActorsQuery
source: FunnelsQuery
/** Index of the step for which we want to get the timestamp for, per person.
* Positive for converted persons, negative for dropped of persons. */
Expand All @@ -1105,6 +1107,14 @@ export interface FunnelsActorsQuery extends InsightActorsQueryBase {
funnelTrendsEntrancePeriodStart?: string
}

export interface FunnelCorrelationActorsQuery extends InsightActorsQueryBase {
kind: NodeKind.FunnelCorrelationActorsQuery
source: FunnelCorrelationQuery
funnelCorrelationPersonConverted?: boolean
funnelCorrelationPersonEntity?: AnyEntityNode
funnelCorrelationPropertyValues?: AnyPropertyFilter[]
}

export interface EventDefinition {
event: string
properties: Record<string, any>
Expand All @@ -1127,7 +1137,7 @@ export interface FunnelCorrelationResult {
export interface FunnelCorrelationResponse {
results: FunnelCorrelationResult
columns?: any[]
types?: string[]
types?: any[]
hogql?: string
timings?: QueryTiming[]
hasMore?: boolean
Expand Down Expand Up @@ -1188,7 +1198,7 @@ export interface InsightActorsQueryOptionsResponse {

export interface InsightActorsQueryOptions {
kind: NodeKind.InsightActorsQueryOptions
source: InsightActorsQuery | FunnelsActorsQuery
source: InsightActorsQuery | FunnelsActorsQuery | FunnelCorrelationActorsQuery
response?: InsightActorsQueryOptionsResponse
}

Expand Down
2 changes: 1 addition & 1 deletion frontend/src/scenes/funnels/FunnelLineGraph.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export function FunnelLineGraph({

if (hogQLInsightsFunnelsFlagEnabled) {
const query: FunnelsActorsQuery = {
kind: NodeKind.InsightActorsQuery,
kind: NodeKind.FunnelsActorsQuery,
source: querySource,
funnelTrendsDropOff: false,
funnelTrendsEntrancePeriodStart: dayjs(day).format('YYYY-MM-DD HH:mm:ss'),
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/scenes/funnels/funnelCorrelationLogic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export const funnelCorrelationLogic = kea<funnelCorrelationLogicType>([
try {
if (values.hogQLInsightsFunnelsFlagEnabled) {
const actorsQuery: FunnelsActorsQuery = {
kind: NodeKind.InsightActorsQuery,
kind: NodeKind.FunnelsActorsQuery,
source: values.querySource!,
}
const query: FunnelCorrelationQuery = {
Expand Down Expand Up @@ -93,7 +93,7 @@ export const funnelCorrelationLogic = kea<funnelCorrelationLogicType>([
loadEventWithPropertyCorrelations: async (eventName: string) => {
if (values.hogQLInsightsFunnelsFlagEnabled) {
const actorsQuery: FunnelsActorsQuery = {
kind: NodeKind.InsightActorsQuery,
kind: NodeKind.FunnelsActorsQuery,
source: values.querySource!,
}
const query: FunnelCorrelationQuery = {
Expand Down
164 changes: 145 additions & 19 deletions frontend/src/scenes/funnels/funnelPersonsModalLogic.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
import { actions, connect, kea, key, listeners, path, props, selectors } from 'kea'
import { elementsToAction } from 'scenes/events/createActionFromEvent'
import { insightLogic } from 'scenes/insights/insightLogic'
import { keyForInsightLogicProps } from 'scenes/insights/sharedUtils'
import { funnelTitle } from 'scenes/trends/persons-modal/persons-modal-utils'
import { openPersonsModal } from 'scenes/trends/persons-modal/PersonsModal'

import { FunnelsActorsQuery, NodeKind } from '~/queries/schema'
import {
EventsNode,
FunnelCorrelationActorsQuery,
FunnelCorrelationQuery,
FunnelsActorsQuery,
NodeKind,
} from '~/queries/schema'
import {
AnyPropertyFilter,
FunnelCorrelation,
FunnelCorrelationResultsType,
FunnelStep,
FunnelStepWithConversionMetrics,
InsightLogicProps,
PropertyFilterType,
PropertyOperator,
} from '~/types'

import { funnelDataLogic } from './funnelDataLogic'
Expand Down Expand Up @@ -99,7 +109,7 @@ export const funnelPersonsModalLogic = kea<funnelPersonsModalLogicType>([
// openPersonsModalForStep is for the baseline - for breakdown series use openPersonsModalForSeries
if (values.hogQLInsightsFunnelsFlagEnabled) {
const query: FunnelsActorsQuery = {
kind: NodeKind.InsightActorsQuery,
kind: NodeKind.FunnelsActorsQuery,
source: values.querySource!,
funnelStep: converted ? stepNo : -stepNo,
includeRecordings: true,
Expand Down Expand Up @@ -131,7 +141,7 @@ export const funnelPersonsModalLogic = kea<funnelPersonsModalLogicType>([
// Version of openPersonsModalForStep that accurately handles breakdown series
if (values.hogQLInsightsFunnelsFlagEnabled) {
const query: FunnelsActorsQuery = {
kind: NodeKind.InsightActorsQuery,
kind: NodeKind.FunnelsActorsQuery,
source: values.querySource!,
funnelStep: converted ? stepNo : -stepNo,
funnelStepBreakdown: series.breakdown_value === 'Baseline' ? null : series.breakdown_value,
Expand All @@ -152,26 +162,142 @@ export const funnelPersonsModalLogic = kea<funnelPersonsModalLogicType>([

if (correlation.result_type === FunnelCorrelationResultsType.Properties) {
const { breakdown, breakdown_value } = parseBreakdownValue(correlation.event.event)
openPersonsModal({
url: success ? correlation.success_people_url : correlation.failure_people_url,
title: funnelTitle({
converted: success,
step: values.steps.length,
breakdown_value,
label: breakdown,
}),
const title = funnelTitle({
converted: success,
step: values.steps.length,
breakdown_value,
label: breakdown,
})

if (values.hogQLInsightsFunnelsFlagEnabled) {
// properties
const [propertyName, propertyValue] = correlation.event.event.split('::')
const propType = values.querySource?.aggregation_group_type_index ? 'group' : 'person'
const actorsQuery: FunnelsActorsQuery = {
kind: NodeKind.FunnelsActorsQuery,
source: values.querySource!,
funnelStep: 1,
includeRecordings: true,
}
const correlationQuery: FunnelCorrelationQuery = {
kind: NodeKind.FunnelCorrelationQuery,
source: actorsQuery,
funnelCorrelationType: correlation.result_type,
}
const query: FunnelCorrelationActorsQuery = {
kind: NodeKind.FunnelCorrelationActorsQuery,
source: correlationQuery,
funnelCorrelationPersonConverted: success,
funnelCorrelationPropertyValues: [
{
key: propertyName,
value: propertyValue,
type: propType === 'person' ? PropertyFilterType.Person : PropertyFilterType.Group,
operator: PropertyOperator.Exact,
group_type_index: values.querySource?.aggregation_group_type_index,
},
],
}
openPersonsModal({
title,
query,
additionalSelect: { matched_recordings: 'matched_recordings' },
})
} else {
openPersonsModal({
url: success ? correlation.success_people_url : correlation.failure_people_url,
title,
})
}
} else {
const { name } = parseEventAndProperty(correlation.event)

openPersonsModal({
url: success ? correlation.success_people_url : correlation.failure_people_url,
title: funnelTitle({
converted: success,
step: values.steps.length,
label: name,
}),
const title = funnelTitle({
converted: success,
step: values.steps.length,
label: name,
})

if (values.hogQLInsightsFunnelsFlagEnabled) {
const actorsQuery: FunnelsActorsQuery = {
kind: NodeKind.FunnelsActorsQuery,
source: values.querySource!,
funnelStep: 1,
includeRecordings: true,
}
const correlationQuery: FunnelCorrelationQuery = {
kind: NodeKind.FunnelCorrelationQuery,
source: actorsQuery,
funnelCorrelationType: correlation.result_type,
}

let entity: EventsNode
if (correlation.result_type === FunnelCorrelationResultsType.Events) {
// events
entity = {
event: correlation.event.event,
kind: NodeKind.EventsNode,
}
} else {
// events with properties
const eventName = correlation.event.event.split('::')[0]

let properties: AnyPropertyFilter[]
if (eventName === '$autocapture') {
// If we have an $autocapture event, we need to
// convert the `elements` chain into an "action".
const elements = correlation.event.elements
const elementsAsAction = elementsToAction(elements)
properties = Object.entries(elementsAsAction)
.map(([propertyKey, propertyValue]) => {
if (propertyValue !== null) {
return {
key: propertyKey,
value: [propertyValue],
type: 'element',
operator: 'exact',
}
}
})
.filter(Boolean) as AnyPropertyFilter[]
} else {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [_, propertyName, propertyValue] = correlation.event.event.split('::')

properties = [
{
key: propertyName,
value: propertyValue,
type: PropertyFilterType.Event,
operator: PropertyOperator.Exact,
},
]
}

entity = {
kind: NodeKind.EventsNode,
event: eventName,
properties,
}
}

const query: FunnelCorrelationActorsQuery = {
kind: NodeKind.FunnelCorrelationActorsQuery,
source: correlationQuery,
funnelCorrelationPersonConverted: success,
funnelCorrelationPersonEntity: entity,
}

openPersonsModal({
title,
query,
additionalSelect: { matched_recordings: 'matched_recordings' },
})
} else {
openPersonsModal({
url: success ? correlation.success_people_url : correlation.failure_people_url,
title,
})
}
}
},
})),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export const funnelPropertyCorrelationLogic = kea<funnelPropertyCorrelationLogic
try {
if (values.hogQLInsightsFunnelsFlagEnabled) {
const actorsQuery: FunnelsActorsQuery = {
kind: NodeKind.InsightActorsQuery,
kind: NodeKind.FunnelsActorsQuery,
source: values.querySource!,
}
const query: FunnelCorrelationQuery = {
Expand Down
Loading

0 comments on commit 2bd43f2

Please sign in to comment.