Skip to content

Commit

Permalink
feat(web-analytics): Add compare option to web overview (#20315)
Browse files Browse the repository at this point in the history
Add compare option to web overview
  • Loading branch information
robbie-c authored Feb 14, 2024
1 parent 5e874b8 commit f2b8462
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 22 deletions.
3 changes: 3 additions & 0 deletions frontend/src/queries/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -4993,6 +4993,9 @@
"WebOverviewQuery": {
"additionalProperties": false,
"properties": {
"compare": {
"type": "boolean"
},
"dateRange": {
"$ref": "#/definitions/DateRange"
},
Expand Down
1 change: 1 addition & 0 deletions frontend/src/queries/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -968,6 +968,7 @@ export interface WebAnalyticsQueryBase {
export interface WebOverviewQuery extends WebAnalyticsQueryBase {
kind: NodeKind.WebOverviewQuery
response?: WebOverviewQueryResponse
compare?: boolean
}

export interface WebOverviewItem {
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/scenes/web-analytics/webAnalyticsLogic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ export const webAnalyticsLogic = kea<webAnalyticsLogicType>([
date_from: dateFrom,
date_to: dateTo,
}
const compare = !!(dateRange.date_from && dateRange.date_to)
const compare = !!dateRange.date_from && dateRange.date_from !== 'all'

const sampling = {
enabled: !!values.featureFlags[FEATURE_FLAGS.WEB_ANALYTICS_SAMPLING],
Expand All @@ -428,6 +428,7 @@ export const webAnalyticsLogic = kea<webAnalyticsLogicType>([
properties: webAnalyticsFilters,
dateRange,
sampling,
compare,
},
insightProps: createInsightProps(TileId.OVERVIEW),
canOpenModal: false,
Expand Down
11 changes: 6 additions & 5 deletions posthog/hogql_queries/web_analytics/test/test_web_overview.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,11 @@ def _create_events(self, data, event="$pageview"):
)
return person_result

def _run_web_overview_query(self, date_from, date_to):
def _run_web_overview_query(self, date_from, date_to, compare=True):
query = WebOverviewQuery(
dateRange=DateRange(date_from=date_from, date_to=date_to),
properties=[],
compare=compare,
)
runner = WebOverviewQueryRunner(team=self.team, query=query)
return runner.calculate()
Expand Down Expand Up @@ -95,24 +96,24 @@ def test_all_time(self):
]
)

results = self._run_web_overview_query("all", "2023-12-15").results
results = self._run_web_overview_query("all", "2023-12-15", compare=False).results

visitors = results[0]
self.assertEqual("visitors", visitors.key)
self.assertEqual(2, visitors.value)
self.assertEqual(0, visitors.previous)
self.assertEqual(None, visitors.previous)
self.assertEqual(None, visitors.changeFromPreviousPct)

views = results[1]
self.assertEqual("views", views.key)
self.assertEqual(4, views.value)
self.assertEqual(0, views.previous)
self.assertEqual(None, views.previous)
self.assertEqual(None, views.changeFromPreviousPct)

sessions = results[2]
self.assertEqual("sessions", sessions.key)
self.assertEqual(3, sessions.value)
self.assertEqual(0, sessions.previous)
self.assertEqual(None, sessions.previous)
self.assertEqual(None, sessions.changeFromPreviousPct)

duration_s = results[3]
Expand Down
98 changes: 82 additions & 16 deletions posthog/hogql_queries/web_analytics/web_overview.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ def to_query(self) -> ast.SelectQuery | ast.SelectUnionQuery:
mid = self.query_date_range.date_from_as_hogql()
end = self.query_date_range.date_to_as_hogql()
with self.timings.measure("overview_stats_query"):
query = parse_select(
"""
if self.query.compare:
return parse_select(
"""
WITH pages_query AS (
SELECT
uniq(if(timestamp >= {mid} AND timestamp < {end}, events.person_id, NULL)) AS unique_users,
Expand Down Expand Up @@ -86,21 +87,86 @@ def to_query(self) -> ast.SelectQuery | ast.SelectUnionQuery:
FROM pages_query
CROSS JOIN sessions_query
""",
timings=self.timings,
placeholders={
"start": start,
"mid": mid,
"end": end,
"event_properties": self.event_properties(),
"session_where": self.session_where(include_previous_period=True),
"session_having": self.session_having(include_previous_period=True),
"sample_rate": self._sample_ratio,
"sample_expr": ast.SampleExpr(sample_value=self._sample_ratio),
},
backend="cpp",
)
timings=self.timings,
placeholders={
"start": start,
"mid": mid,
"end": end,
"event_properties": self.event_properties(),
"session_where": self.session_where(include_previous_period=True),
"session_having": self.session_having(include_previous_period=True),
"sample_rate": self._sample_ratio,
},
)
else:
return parse_select(
"""
WITH pages_query AS (
SELECT
uniq(events.person_id) AS unique_users,
count() AS current_pageviews,
uniq(events.properties.$session_id) AS unique_sessions
FROM
events
SAMPLE {sample_rate}
WHERE
event = '$pageview' AND
timestamp >= {mid} AND
timestamp < {end} AND
{event_properties}
),
sessions_query AS (
SELECT
avg(duration_s) AS avg_duration_s,
avg(is_bounce) AS bounce_rate
FROM (SELECT
events.properties.`$session_id` AS session_id,
min(events.timestamp) AS min_timestamp,
max(events.timestamp) AS max_timestamp,
dateDiff('second', min_timestamp, max_timestamp) AS duration_s,
countIf(events.event == '$pageview') AS num_pageviews,
countIf(events.event == '$autocapture') AS num_autocaptures,
return query
-- definition of a GA4 bounce from here https://support.google.com/analytics/answer/12195621?hl=en
(num_autocaptures == 0 AND num_pageviews <= 1 AND duration_s < 10) AS is_bounce
FROM
events
SAMPLE {sample_rate}
WHERE
session_id IS NOT NULL
AND (events.event == '$pageview' OR events.event == '$autocapture' OR events.event == '$pageleave')
AND ({session_where})
GROUP BY
events.properties.`$session_id`
HAVING
({session_having})
)
)
SELECT
unique_users,
NULL as previous_unique_users,
current_pageviews,
NULL as previous_pageviews,
unique_sessions,
NULL as previous_unique_sessions,
avg_duration_s,
NULL as prev_avg_duration_s,
bounce_rate,
NULL as prev_bounce_rate
FROM pages_query
CROSS JOIN sessions_query
""",
timings=self.timings,
placeholders={
"start": start,
"mid": mid,
"end": end,
"event_properties": self.event_properties(),
"session_where": self.session_where(include_previous_period=False),
"session_having": self.session_having(include_previous_period=False),
"sample_rate": self._sample_ratio,
},
)

def calculate(self):
response = execute_hogql_query(
Expand Down
1 change: 1 addition & 0 deletions posthog/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -1540,6 +1540,7 @@ class WebOverviewQuery(BaseModel):
model_config = ConfigDict(
extra="forbid",
)
compare: Optional[bool] = None
dateRange: Optional[DateRange] = None
kind: Literal["WebOverviewQuery"] = "WebOverviewQuery"
properties: List[Union[EventPropertyFilter, PersonPropertyFilter]]
Expand Down

0 comments on commit f2b8462

Please sign in to comment.