Skip to content
Draft
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
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ function BrowserVersionsModal() {
<Modal>
<BreakdownModal
reportInfo={reportInfo}
metrics={chooseMetrics(query)}
metrics={chooseMetrics(query, site)}
getFilterInfo={getFilterInfo}
addSearchFilter={addSearchFilter}
renderIcon={renderIcon}
Expand Down
2 changes: 1 addition & 1 deletion assets/js/dashboard/stats/modals/devices/browsers-modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ function BrowsersModal() {
<Modal>
<BreakdownModal
reportInfo={reportInfo}
metrics={chooseMetrics(query)}
metrics={chooseMetrics(query, site)}
getFilterInfo={getFilterInfo}
addSearchFilter={addSearchFilter}
renderIcon={renderIcon}
Expand Down
12 changes: 9 additions & 3 deletions assets/js/dashboard/stats/modals/devices/choose-metrics.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,24 @@ import {
hasConversionGoalFilter,
isRealTimeDashboard
} from '../../../util/filters'
import { revenueAvailable } from '../../../query'
import * as metrics from '../../reports/metrics'

export default function chooseMetrics(query) {
export default function chooseMetrics(query, site) {
/*global BUILD_EXTRA*/
const showRevenueMetrics = BUILD_EXTRA && revenueAvailable(query, site)

if (hasConversionGoalFilter(query)) {
return [
metrics.createTotalVisitors(),
metrics.createVisitors({
renderLabel: (_query) => 'Conversions',
width: 'w-28'
}),
metrics.createConversionRate()
]
metrics.createConversionRate(),
showRevenueMetrics && metrics.createTotalRevenue(),
showRevenueMetrics && metrics.createAverageRevenue()
].filter((metric) => !!metric)
}

if (isRealTimeDashboard(query)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ function OperatingSystemVersionsModal() {
<Modal>
<BreakdownModal
reportInfo={reportInfo}
metrics={chooseMetrics(query)}
metrics={chooseMetrics(query, site)}
getFilterInfo={getFilterInfo}
addSearchFilter={addSearchFilter}
renderIcon={renderIcon}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ function OperatingSystemsModal() {
<Modal>
<BreakdownModal
reportInfo={reportInfo}
metrics={chooseMetrics(query)}
metrics={chooseMetrics(query, site)}
getFilterInfo={getFilterInfo}
addSearchFilter={addSearchFilter}
renderIcon={renderIcon}
Expand Down
2 changes: 1 addition & 1 deletion assets/js/dashboard/stats/modals/devices/screen-sizes.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ function ScreenSizesModal() {
<Modal>
<BreakdownModal
reportInfo={reportInfo}
metrics={chooseMetrics(query)}
metrics={chooseMetrics(query, site)}
getFilterInfo={getFilterInfo}
searchEnabled={false}
renderIcon={renderIcon}
Expand Down
11 changes: 8 additions & 3 deletions assets/js/dashboard/stats/modals/entry-pages.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
hasConversionGoalFilter,
isRealTimeDashboard
} from '../../util/filters'
import { addFilter } from '../../query'
import { addFilter, revenueAvailable } from '../../query'
import BreakdownModal from './breakdown-modal'
import * as metrics from '../reports/metrics'
import * as url from '../../util/url'
Expand All @@ -16,6 +16,9 @@ function EntryPagesModal() {
const { query } = useQueryContext()
const site = useSiteContext()

/*global BUILD_EXTRA*/
const showRevenueMetrics = BUILD_EXTRA && revenueAvailable(query, site)

const reportInfo = {
title: 'Entry Pages',
dimension: 'entry_page',
Expand Down Expand Up @@ -54,8 +57,10 @@ function EntryPagesModal() {
renderLabel: (_query) => 'Conversions',
width: 'w-28'
}),
metrics.createConversionRate()
]
metrics.createConversionRate(),
showRevenueMetrics && metrics.createTotalRevenue(),
showRevenueMetrics && metrics.createAverageRevenue()
].filter((metric) => !!metric)
}

if (isRealTimeDashboard(query)) {
Expand Down
11 changes: 8 additions & 3 deletions assets/js/dashboard/stats/modals/exit-pages.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useCallback } from 'react'
import Modal from './modal'
import { hasConversionGoalFilter } from '../../util/filters'
import { addFilter } from '../../query'
import { addFilter, revenueAvailable } from '../../query'
import BreakdownModal from './breakdown-modal'
import * as metrics from '../reports/metrics'
import * as url from '../../util/url'
Expand All @@ -13,6 +13,9 @@ function ExitPagesModal() {
const { query } = useQueryContext()
const site = useSiteContext()

/*global BUILD_EXTRA*/
const showRevenueMetrics = BUILD_EXTRA && revenueAvailable(query, site)

const reportInfo = {
title: 'Exit Pages',
dimension: 'exit_page',
Expand Down Expand Up @@ -51,8 +54,10 @@ function ExitPagesModal() {
renderLabel: (_query) => 'Conversions',
width: 'w-28'
}),
metrics.createConversionRate()
]
metrics.createConversionRate(),
showRevenueMetrics && metrics.createTotalRevenue(),
showRevenueMetrics && metrics.createAverageRevenue()
].filter((metric) => !!metric)
}

if (query.period === 'realtime') {
Expand Down
11 changes: 8 additions & 3 deletions assets/js/dashboard/stats/modals/locations-modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import * as metrics from '../reports/metrics'
import * as url from '../../util/url'
import { useQueryContext } from '../../query-context'
import { useSiteContext } from '../../site-context'
import { addFilter } from '../../query'
import { addFilter, revenueAvailable } from '../../query'
import { SortDirection } from '../../hooks/use-order-by'

const VIEWS = {
Expand Down Expand Up @@ -38,6 +38,9 @@ function LocationsModal({ currentView }) {
const { query } = useQueryContext()
const site = useSiteContext()

/*global BUILD_EXTRA*/
const showRevenueMetrics = BUILD_EXTRA && revenueAvailable(query, site)

let reportInfo = VIEWS[currentView]
reportInfo = {
...reportInfo,
Expand Down Expand Up @@ -75,8 +78,10 @@ function LocationsModal({ currentView }) {
renderLabel: (_query) => 'Conversions',
width: 'w-28'
}),
metrics.createConversionRate()
]
metrics.createConversionRate(),
showRevenueMetrics && metrics.createTotalRevenue(),
showRevenueMetrics && metrics.createAverageRevenue()
].filter((metric) => !!metric)
}

if (query.period === 'realtime') {
Expand Down
11 changes: 8 additions & 3 deletions assets/js/dashboard/stats/modals/pages.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
hasConversionGoalFilter,
isRealTimeDashboard
} from '../../util/filters'
import { addFilter } from '../../query'
import { addFilter, revenueAvailable } from '../../query'
import BreakdownModal from './breakdown-modal'
import * as metrics from '../reports/metrics'
import * as url from '../../util/url'
Expand All @@ -16,6 +16,9 @@ function PagesModal() {
const { query } = useQueryContext()
const site = useSiteContext()

/*global BUILD_EXTRA*/
const showRevenueMetrics = BUILD_EXTRA && revenueAvailable(query, site)

const reportInfo = {
title: 'Top Pages',
dimension: 'page',
Expand Down Expand Up @@ -54,8 +57,10 @@ function PagesModal() {
renderLabel: (_query) => 'Conversions',
width: 'w-28'
}),
metrics.createConversionRate()
]
metrics.createConversionRate(),
showRevenueMetrics && metrics.createTotalRevenue(),
showRevenueMetrics && metrics.createAverageRevenue()
].filter((metric) => !!metric)
}

if (isRealTimeDashboard(query)) {
Expand Down
11 changes: 8 additions & 3 deletions assets/js/dashboard/stats/modals/referrer-drilldown.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
import BreakdownModal from './breakdown-modal'
import * as metrics from '../reports/metrics'
import * as url from '../../util/url'
import { addFilter } from '../../query'
import { addFilter, revenueAvailable } from '../../query'
import { useQueryContext } from '../../query-context'
import { useSiteContext } from '../../site-context'
import { SortDirection } from '../../hooks/use-order-by'
Expand All @@ -20,6 +20,9 @@ function ReferrerDrilldownModal() {
const { query } = useQueryContext()
const site = useSiteContext()

/*global BUILD_EXTRA*/
const showRevenueMetrics = BUILD_EXTRA && revenueAvailable(query, site)

const reportInfo = {
title: 'Referrer Drilldown',
dimension: 'referrer',
Expand Down Expand Up @@ -61,8 +64,10 @@ function ReferrerDrilldownModal() {
renderLabel: (_query) => 'Conversions',
width: 'w-28'
}),
metrics.createConversionRate()
]
metrics.createConversionRate(),
showRevenueMetrics && metrics.createTotalRevenue(),
showRevenueMetrics && metrics.createAverageRevenue()
].filter((metric) => !!metric)
}

if (isRealTimeDashboard(query)) {
Expand Down
11 changes: 8 additions & 3 deletions assets/js/dashboard/stats/modals/sources.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
import BreakdownModal from './breakdown-modal'
import * as metrics from '../reports/metrics'
import * as url from '../../util/url'
import { addFilter } from '../../query'
import { addFilter, revenueAvailable } from '../../query'
import { useQueryContext } from '../../query-context'
import { useSiteContext } from '../../site-context'
import { SortDirection } from '../../hooks/use-order-by'
Expand Down Expand Up @@ -91,6 +91,9 @@ function SourcesModal({ currentView }) {
const { query } = useQueryContext()
const site = useSiteContext()

/*global BUILD_EXTRA*/
const showRevenueMetrics = BUILD_EXTRA && revenueAvailable(query, site)

let reportInfo = VIEWS[currentView].info
reportInfo = {
...reportInfo,
Expand Down Expand Up @@ -127,8 +130,10 @@ function SourcesModal({ currentView }) {
renderLabel: (_query) => 'Conversions',
width: 'w-28'
}),
metrics.createConversionRate()
]
metrics.createConversionRate(),
showRevenueMetrics && metrics.createTotalRevenue(),
showRevenueMetrics && metrics.createAverageRevenue()
].filter((metric) => !!metric)
}

if (isRealTimeDashboard(query)) {
Expand Down
33 changes: 33 additions & 0 deletions lib/plausible/stats/sql/expression.ex
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,39 @@ defmodule Plausible.Stats.SQL.Expression do
def select_dimension(q, key, "visit:city_name", _table, _query),
do: select_merge_as(q, [t], %{key => t.city_name})

@dimension_columns %{
"event:name" => :name,
"event:page" => :pathname,
"event:hostname" => :hostname,
"visit:entry_page" => :entry_page,
"visit:entry_page_hostname" => :entry_page_hostname,
"visit:exit_page" => :exit_page,
"visit:exit_page_hostname" => :exit_page_hostname
}

def select_dimension_internal(q, dimension) do
if column = Map.get(@dimension_columns, dimension) do
select_merge_as(q, [t], %{column => fragment("any(?)", field(t, ^column))})
else
q
end
end

def select_dimension_from_join(q, key, "event:name"),
do: select_merge_as(q, [..., t], %{key => t.name})

def select_dimension_from_join(q, key, "event:page"),
do: select_merge_as(q, [..., t], %{key => t.pathname})

def select_dimension_from_join(q, key, "event:hostname"),
do: select_merge_as(q, [..., t], %{key => t.hostname})

def select_dimension_from_join(q, key, "visit:entry_page"),
do: select_merge_as(q, [..., t], %{key => t.entry_page})

def select_dimension_from_join(q, key, "visit:exit_page"),
do: select_merge_as(q, [..., t], %{key => t.exit_page})

def event_metric(:pageviews, _query) do
wrap_alias([e], %{
pageviews: scale_sample(fragment("countIf(? = 'pageview')", e.name))
Expand Down
33 changes: 31 additions & 2 deletions lib/plausible/stats/sql/query_builder.ex
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ defmodule Plausible.Stats.SQL.QueryBuilder do

defp join_sessions_if_needed(q, query) do
if TableDecider.events_join_sessions?(query) do
%{session: dimensions} = TableDecider.partition_dimensions(query)

sessions_q =
from(
s in "sessions_v2",
Expand All @@ -81,6 +83,11 @@ defmodule Plausible.Stats.SQL.QueryBuilder do
group_by: s.session_id
)

sessions_q =
Enum.reduce(dimensions, sessions_q, fn dimension, acc ->
Plausible.Stats.SQL.Expression.select_dimension_internal(acc, dimension)
end)

on_ee do
sessions_q = Plausible.Stats.Sampling.add_query_hint(sessions_q, query)
end
Expand Down Expand Up @@ -131,8 +138,30 @@ defmodule Plausible.Stats.SQL.QueryBuilder do
|> Enum.reduce(%{}, &Map.merge/2)
end

def build_group_by(q, table, query) do
Enum.reduce(query.dimensions, q, &dimension_group_by(&2, table, query, &1))
def build_group_by(q, :events, query) do
%{session: session_only_dimensions} = TableDecider.partition_dimensions(query)
event_dimensions = query.dimensions -- session_only_dimensions

q =
Enum.reduce(event_dimensions, q, &dimension_group_by(&2, :events, query, &1))

Enum.reduce(
session_only_dimensions,
q,
&dimension_group_by_join(&2, query, &1)
)
end

def build_group_by(q, :sessions, query) do
Enum.reduce(query.dimensions, q, &dimension_group_by(&2, :sessions, query, &1))
end

defp dimension_group_by_join(q, query, dimension) do
key = shortname(query, dimension)

q
|> Expression.select_dimension_from_join(key, dimension)
|> group_by([], selected_as(^key))
end

defp dimension_group_by(q, :events, query, "event:goal" = dimension) do
Expand Down
4 changes: 4 additions & 0 deletions lib/plausible/stats/table_decider.ex
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ defmodule Plausible.Stats.TableDecider do
end
end

def partition_dimensions(query) do
partition(query.dimensions, query, &dimension_partitioner/2)
end

@type table_type() :: :events | :sessions
@type metric() :: String.t()

Expand Down
Loading
Loading