implement URL pageview metric/expanded metric
This commit is contained in:
@@ -49,6 +49,7 @@ export const CATEGORIES = [
|
||||
|
||||
const METRIC_TYPES = [
|
||||
{ label: 'Path', value: 'path' },
|
||||
{ label: 'URL', value: 'fullPath' },
|
||||
{ label: 'Entry page', value: 'entry' },
|
||||
{ label: 'Exit page', value: 'exit' },
|
||||
{ label: 'Title', value: 'title' },
|
||||
|
||||
@@ -10,7 +10,7 @@ import { WebsiteChart } from '@/app/(main)/websites/[websiteId]/WebsiteChart';
|
||||
import { PageBody } from '@/components/common/PageBody';
|
||||
import { Panel } from '@/components/common/Panel';
|
||||
|
||||
const excludedIds = ['path', 'entry', 'exit', 'title', 'language', 'screen', 'event'];
|
||||
const excludedIds = ['path', 'fullPath', 'entry', 'exit', 'title', 'language', 'screen', 'event'];
|
||||
|
||||
export function LinkPage({
|
||||
linkId,
|
||||
|
||||
@@ -10,7 +10,7 @@ import { WebsiteChart } from '@/app/(main)/websites/[websiteId]/WebsiteChart';
|
||||
import { PageBody } from '@/components/common/PageBody';
|
||||
import { Panel } from '@/components/common/Panel';
|
||||
|
||||
const excludedIds = ['path', 'entry', 'exit', 'title', 'language', 'screen', 'event'];
|
||||
const excludedIds = ['path', 'fullPath', 'entry', 'exit', 'title', 'language', 'screen', 'event'];
|
||||
|
||||
export function PixelPage({
|
||||
pixelId,
|
||||
|
||||
@@ -25,6 +25,7 @@ import {
|
||||
Tag,
|
||||
Target,
|
||||
Type,
|
||||
Waypoints,
|
||||
} from '@/components/icons';
|
||||
import { Lightning } from '@/components/svg';
|
||||
|
||||
@@ -45,7 +46,7 @@ export function WebsiteExpandedMenu({
|
||||
|
||||
const items = [
|
||||
{
|
||||
label: 'URL',
|
||||
label: t(labels.pages),
|
||||
items: [
|
||||
{
|
||||
id: 'path',
|
||||
@@ -53,6 +54,12 @@ export function WebsiteExpandedMenu({
|
||||
path: updateParams({ view: 'path' }),
|
||||
icon: <SquareSlash />,
|
||||
},
|
||||
{
|
||||
id: 'fullPath',
|
||||
label: t(labels.url),
|
||||
path: updateParams({ view: 'fullPath' }),
|
||||
icon: <Waypoints />,
|
||||
},
|
||||
{
|
||||
id: 'entry',
|
||||
label: t(labels.entry),
|
||||
|
||||
@@ -17,6 +17,7 @@ export function WebsiteExpandedView({
|
||||
const {
|
||||
query: { view },
|
||||
} = useNavigation();
|
||||
const title = view === 'fullPath' ? t(labels.url) : t(labels[view]);
|
||||
|
||||
return (
|
||||
<Column height="100%" overflow="hidden" gap>
|
||||
@@ -44,12 +45,7 @@ export function WebsiteExpandedView({
|
||||
<WebsiteExpandedMenu excludedIds={excludedIds} />
|
||||
</Column>
|
||||
<Column id="metrics-expanded-table" overflow="hidden">
|
||||
<MetricsExpandedTable
|
||||
title={t(labels[view])}
|
||||
type={view}
|
||||
websiteId={websiteId}
|
||||
onClose={onClose}
|
||||
/>
|
||||
<MetricsExpandedTable title={title} type={view} websiteId={websiteId} onClose={onClose} />
|
||||
</Column>
|
||||
</Grid>
|
||||
</Column>
|
||||
|
||||
@@ -26,12 +26,16 @@ export function WebsitePanels({ websiteId }: { websiteId: string }) {
|
||||
<Tabs>
|
||||
<TabList>
|
||||
<Tab id="path">{t(labels.path)}</Tab>
|
||||
<Tab id="fullPath">{t(labels.url)}</Tab>
|
||||
<Tab id="entry">{t(labels.entry)}</Tab>
|
||||
<Tab id="exit">{t(labels.exit)}</Tab>
|
||||
</TabList>
|
||||
<TabPanel id="path">
|
||||
<MetricsTable type="path" title={t(labels.path)} {...tableProps} />
|
||||
</TabPanel>
|
||||
<TabPanel id="fullPath">
|
||||
<MetricsTable type="fullPath" title={t(labels.url)} {...tableProps} />
|
||||
</TabPanel>
|
||||
<TabPanel id="entry">
|
||||
<MetricsTable type="entry" title={t(labels.path)} {...tableProps} />
|
||||
</TabPanel>
|
||||
|
||||
@@ -94,6 +94,9 @@ export function MetricLabel({ type, data }: MetricLabelProps) {
|
||||
/>
|
||||
);
|
||||
|
||||
case 'fullPath':
|
||||
return label || `(${t(labels.none)})`;
|
||||
|
||||
case 'device':
|
||||
return (
|
||||
<FilterLink
|
||||
|
||||
@@ -37,6 +37,7 @@ export const UNIT_TYPES = ['year', 'month', 'hour', 'day', 'minute'];
|
||||
|
||||
export const EVENT_COLUMNS = [
|
||||
'path',
|
||||
'fullPath',
|
||||
'entry',
|
||||
'exit',
|
||||
'referrer',
|
||||
|
||||
@@ -36,7 +36,7 @@ async function relationalQuery(
|
||||
filters: QueryFilters,
|
||||
): Promise<PageviewExpandedMetricsData[]> {
|
||||
const { type, limit = 500, offset = 0 } = parameters;
|
||||
let column = FILTER_COLUMNS[type] || type;
|
||||
let column = getPageviewColumn(type);
|
||||
const { rawQuery, parseFilters, getTimestampDiffSQL } = prisma;
|
||||
const { filterQuery, joinSessionQuery, cohortQuery, excludeBounceQuery, queryParams } =
|
||||
parseFilters(
|
||||
@@ -49,8 +49,6 @@ async function relationalQuery(
|
||||
|
||||
let entryExitQuery = '';
|
||||
let excludeDomain = '';
|
||||
const isPathType = type === 'path' || type === 'entry' || type === 'exit';
|
||||
|
||||
if (column === 'referrer_domain') {
|
||||
excludeDomain = `and website_event.referrer_domain != regexp_replace(website_event.hostname, '^www.', '')
|
||||
and website_event.referrer_domain != ''`;
|
||||
@@ -77,11 +75,11 @@ async function relationalQuery(
|
||||
`;
|
||||
}
|
||||
|
||||
const selectColumn = isPathType
|
||||
const selectColumn = type === 'fullPath'
|
||||
? `case when website_event.url_query != '' then website_event.url_path || '?' || website_event.url_query else website_event.url_path end`
|
||||
: column;
|
||||
|
||||
const groupByColumn = isPathType
|
||||
const groupByColumn = type === 'fullPath'
|
||||
? `case when website_event.url_query != '' then website_event.url_path || '?' || website_event.url_query else website_event.url_path end`
|
||||
: column;
|
||||
|
||||
@@ -131,7 +129,7 @@ async function clickhouseQuery(
|
||||
filters: QueryFilters,
|
||||
): Promise<{ x: string; y: number }[]> {
|
||||
const { type, limit = 500, offset = 0 } = parameters;
|
||||
let column = FILTER_COLUMNS[type] || type;
|
||||
let column = getPageviewColumn(type);
|
||||
const { rawQuery, parseFilters } = clickhouse;
|
||||
const { filterQuery, cohortQuery, excludeBounceQuery, queryParams } = parseFilters({
|
||||
...filters,
|
||||
@@ -140,7 +138,6 @@ async function clickhouseQuery(
|
||||
|
||||
let excludeDomain = '';
|
||||
let entryExitQuery = '';
|
||||
const isPathType = type === 'path' || type === 'entry' || type === 'exit';
|
||||
let selectColumn = column;
|
||||
|
||||
if (column === 'referrer_domain') {
|
||||
@@ -165,8 +162,8 @@ async function clickhouseQuery(
|
||||
group by visit_id) x
|
||||
ON x.visit_id = website_event.visit_id`;
|
||||
|
||||
selectColumn = `if(x.url_query != '', concat(x.url_path, '?', x.url_query), x.url_path)`;
|
||||
} else if (isPathType) {
|
||||
selectColumn = `x.url_path`;
|
||||
} else if (type === 'fullPath') {
|
||||
selectColumn = `if(url_query != '', concat(url_path, '?', url_query), url_path)`;
|
||||
}
|
||||
|
||||
@@ -244,3 +241,11 @@ export function toPostgresGroupedReferrer(
|
||||
function toPostgresLikeClause(column: string, arr: string[]) {
|
||||
return arr.map(val => `${column} ilike '%${val.replace(/'/g, "''")}%'`).join(' OR\n ');
|
||||
}
|
||||
|
||||
function getPageviewColumn(type: string) {
|
||||
if (type === 'fullPath') {
|
||||
return 'url_path';
|
||||
}
|
||||
|
||||
return FILTER_COLUMNS[type] || type;
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ async function relationalQuery(
|
||||
filters: QueryFilters,
|
||||
): Promise<PageviewMetricsData[]> {
|
||||
const { type, limit = 500, offset = 0 } = parameters;
|
||||
let column = FILTER_COLUMNS[type] || type;
|
||||
let column = getPageviewColumn(type);
|
||||
const { rawQuery, parseFilters } = prisma;
|
||||
const { filterQuery, joinSessionQuery, cohortQuery, excludeBounceQuery, queryParams } =
|
||||
parseFilters(
|
||||
@@ -45,8 +45,6 @@ async function relationalQuery(
|
||||
|
||||
let entryExitQuery = '';
|
||||
let excludeDomain = '';
|
||||
const isPathType = type === 'path' || type === 'entry' || type === 'exit';
|
||||
|
||||
if (column === 'referrer_domain') {
|
||||
excludeDomain = `and website_event.referrer_domain != regexp_replace(website_event.hostname, '^www.', '')
|
||||
and website_event.referrer_domain != ''`;
|
||||
@@ -70,12 +68,10 @@ async function relationalQuery(
|
||||
on x.visit_id = website_event.visit_id
|
||||
`;
|
||||
|
||||
column = isPathType
|
||||
? `case when x.url_query != '' then x.url_path || '?' || x.url_query else x.url_path end`
|
||||
: `x.${FILTER_COLUMNS[type] || type}`;
|
||||
column = `x.${FILTER_COLUMNS[type] || type}`;
|
||||
}
|
||||
|
||||
const selectColumn = isPathType && type !== 'entry' && type !== 'exit'
|
||||
const selectColumn = type === 'fullPath'
|
||||
? `case when website_event.url_query != '' then website_event.url_path || '?' || website_event.url_query else website_event.url_path end`
|
||||
: column;
|
||||
|
||||
@@ -110,7 +106,7 @@ async function clickhouseQuery(
|
||||
filters: QueryFilters,
|
||||
): Promise<{ x: string; y: number }[]> {
|
||||
const { type, limit = 500, offset = 0 } = parameters;
|
||||
let column = FILTER_COLUMNS[type] || type;
|
||||
let column = getPageviewColumn(type);
|
||||
const { rawQuery, parseFilters } = clickhouse;
|
||||
const { filterQuery, cohortQuery, excludeBounceQuery, queryParams } = parseFilters({
|
||||
...filters,
|
||||
@@ -119,9 +115,7 @@ async function clickhouseQuery(
|
||||
|
||||
let sql = '';
|
||||
let excludeDomain = '';
|
||||
const isPathType = type === 'path' || type === 'entry' || type === 'exit';
|
||||
|
||||
if (EVENT_COLUMNS.some(item => Object.keys(filters).includes(item))) {
|
||||
if (type === 'fullPath' || EVENT_COLUMNS.some(item => Object.keys(filters).includes(item))) {
|
||||
let entryExitQuery = '';
|
||||
let selectColumn = column;
|
||||
|
||||
@@ -143,8 +137,9 @@ async function clickhouseQuery(
|
||||
group by visit_id) x
|
||||
ON x.visit_id = website_event.visit_id`;
|
||||
|
||||
selectColumn = `if(x.url_query != '', concat(x.url_path, '?', x.url_query), x.url_path)`;
|
||||
} else if (isPathType) {
|
||||
column = `x.url_path`;
|
||||
selectColumn = `x.url_path`;
|
||||
} else if (type === 'fullPath') {
|
||||
selectColumn = `if(url_query != '', concat(url_path, '?', url_query), url_path)`;
|
||||
}
|
||||
|
||||
@@ -210,3 +205,11 @@ async function clickhouseQuery(
|
||||
|
||||
return rawQuery(sql, { ...queryParams, ...parameters }, FUNCTION_NAME);
|
||||
}
|
||||
|
||||
function getPageviewColumn(type: string) {
|
||||
if (type === 'fullPath') {
|
||||
return 'url_path';
|
||||
}
|
||||
|
||||
return FILTER_COLUMNS[type] || type;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user