From ecfc7ea68e0661f0e5c64d965c9f82549480d395 Mon Sep 17 00:00:00 2001 From: Kevin Decherf Date: Sun, 20 Mar 2022 22:10:41 +0100 Subject: [PATCH 1/5] Rename ref to prevent collision with react elements It seems that, at least in dev mode, 'ref' may incorrectly refer to react elements. Signed-off-by: Kevin Decherf --- components/metrics/ReferrersTable.js | 4 ++-- components/metrics/WebsiteChart.js | 8 ++++---- lib/filters.js | 10 ++++++---- lib/queries.js | 12 ++++++------ pages/api/website/[id]/pageviews.js | 6 +++--- pages/api/website/[id]/stats.js | 9 ++++++--- 6 files changed, 27 insertions(+), 22 deletions(-) diff --git a/components/metrics/ReferrersTable.js b/components/metrics/ReferrersTable.js index c7079e8d..93cdb956 100644 --- a/components/metrics/ReferrersTable.js +++ b/components/metrics/ReferrersTable.js @@ -19,7 +19,7 @@ export default function ReferrersTable({ websiteId, websiteDomain, showFilters, const [filter, setFilter] = useState(FILTER_COMBINED); const { resolve, - query: { ref: currentRef }, + query: { referrer: currentRef }, } = usePageQuery(); const buttons = [ @@ -37,7 +37,7 @@ export default function ReferrersTable({ websiteId, websiteDomain, showFilters, const renderLink = ({ w: link, x: label }) => { return (
- + { @@ -88,7 +88,7 @@ export default function WebsiteChart({ stickyClassName={styles.sticky} enabled={stickyHeader} > - +
diff --git a/lib/filters.js b/lib/filters.js index e9723b42..9f00d529 100644 --- a/lib/filters.js +++ b/lib/filters.js @@ -49,8 +49,10 @@ export const refFilter = (data, { domain, domainOnly, raw }) => { const regex = new RegExp(`http[s]?://([a-z0-9-]+\\.)*${domain}`); const links = {}; - const isValidRef = ref => { - return ref !== '' && ref !== null && !ref.startsWith('/') && !ref.startsWith('#'); + const isValidRef = referrer => { + return ( + referrer !== '' && referrer !== null && !referrer.startsWith('/') && !referrer.startsWith('#') + ); }; const cleanUrl = url => { @@ -71,8 +73,8 @@ export const refFilter = (data, { domain, domainOnly, raw }) => { if (protocol.startsWith('http')) { const path = removeTrailingSlash(pathname); - const ref = searchParams.get('ref'); - const query = ref ? `?ref=${ref}` : ''; + const referrer = searchParams.get('ref'); + const query = referrer ? `?referrer=${referrer}` : ''; return removeTrailingSlash(`${removeWWW(hostname)}${path}`) + query; } diff --git a/lib/queries.js b/lib/queries.js index 5bcd18ba..6b3c6c4e 100644 --- a/lib/queries.js +++ b/lib/queries.js @@ -335,7 +335,7 @@ export async function getEvents(websites, start_at) { export function getWebsiteStats(website_id, start_at, end_at, filters = {}) { const params = [website_id, start_at, end_at]; - const { url, ref } = filters; + const { url, referrer } = filters; let urlFilter = ''; let refFilter = ''; @@ -344,9 +344,9 @@ export function getWebsiteStats(website_id, start_at, end_at, filters = {}) { params.push(decodeURIComponent(url)); } - if (ref) { + if (referrer) { refFilter = `and referrer like $${params.length + 1}`; - params.push(`%${decodeURIComponent(ref)}%`); + params.push(`%${decodeURIComponent(referrer)}%`); } return rawQuery( @@ -382,7 +382,7 @@ export function getPageviewStats( filters = {}, ) { const params = [website_id, start_at, end_at]; - const { url, ref } = filters; + const { url, referrer } = filters; let urlFilter = ''; let refFilter = ''; @@ -392,9 +392,9 @@ export function getPageviewStats( params.push(decodeURIComponent(url)); } - if (ref) { + if (referrer) { refFilter = `and referrer like $${params.length + 1}`; - params.push(`%${decodeURIComponent(ref)}%`); + params.push(`%${decodeURIComponent(referrer)}%`); } return rawQuery( diff --git a/pages/api/website/[id]/pageviews.js b/pages/api/website/[id]/pageviews.js index 22966ca7..e2069f8c 100644 --- a/pages/api/website/[id]/pageviews.js +++ b/pages/api/website/[id]/pageviews.js @@ -11,7 +11,7 @@ export default async (req, res) => { return unauthorized(res); } - const { id, start_at, end_at, unit, tz, url, ref } = req.query; + const { id, start_at, end_at, unit, tz, url, referrer } = req.query; const websiteId = +id; const startDate = new Date(+start_at); @@ -22,10 +22,10 @@ export default async (req, res) => { } const [pageviews, sessions] = await Promise.all([ - getPageviewStats(websiteId, startDate, endDate, tz, unit, '*', { url, ref }), + getPageviewStats(websiteId, startDate, endDate, tz, unit, '*', { url, referrer }), getPageviewStats(websiteId, startDate, endDate, tz, unit, 'distinct session_id', { url, - ref, + referrer, }), ]); diff --git a/pages/api/website/[id]/stats.js b/pages/api/website/[id]/stats.js index 9dd82361..cdb374e2 100644 --- a/pages/api/website/[id]/stats.js +++ b/pages/api/website/[id]/stats.js @@ -8,7 +8,7 @@ export default async (req, res) => { return unauthorized(res); } - const { id, start_at, end_at, url, ref } = req.query; + const { id, start_at, end_at, url, referrer } = req.query; const websiteId = +id; const startDate = new Date(+start_at); @@ -18,8 +18,11 @@ export default async (req, res) => { const prevStartDate = new Date(+start_at - distance); const prevEndDate = new Date(+end_at - distance); - const metrics = await getWebsiteStats(websiteId, startDate, endDate, { url, ref }); - const prevPeriod = await getWebsiteStats(websiteId, prevStartDate, prevEndDate, { url, ref }); + const metrics = await getWebsiteStats(websiteId, startDate, endDate, { url, referrer }); + const prevPeriod = await getWebsiteStats(websiteId, prevStartDate, prevEndDate, { + url, + referrer, + }); const stats = Object.keys(metrics[0]).reduce((obj, key) => { obj[key] = { From bb7d26d19f56b6eb21785c7babef9ece2c2b71cc Mon Sep 17 00:00:00 2001 From: Kevin Decherf Date: Sun, 20 Mar 2022 22:12:40 +0100 Subject: [PATCH 2/5] Fix referrer filter 7530de87d233b04d88f1fefd425c822bdf7502f4 introduced a regression: the domain parameter in refFilter() contains 'https://', which bypass the new regex; thus we readd the call to getDomainName(). Signed-off-by: Kevin Decherf --- lib/filters.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/filters.js b/lib/filters.js index 9f00d529..945a6011 100644 --- a/lib/filters.js +++ b/lib/filters.js @@ -1,5 +1,5 @@ import { BROWSERS } from './constants'; -import { removeTrailingSlash, removeWWW } from './url'; +import { removeTrailingSlash, removeWWW, getDomainName } from './url'; export const urlFilter = (data, { raw }) => { const isValidUrl = url => { @@ -46,7 +46,8 @@ export const urlFilter = (data, { raw }) => { }; export const refFilter = (data, { domain, domainOnly, raw }) => { - const regex = new RegExp(`http[s]?://([a-z0-9-]+\\.)*${domain}`); + const domainName = getDomainName(domain); + const regex = new RegExp(`http[s]?://([a-z0-9-]+\\.)*${domainName}`); const links = {}; const isValidRef = referrer => { From 35f9c7ef6cb73289e553a705a955fe38d40199ad Mon Sep 17 00:00:00 2001 From: Kevin Decherf Date: Sun, 20 Mar 2022 22:14:54 +0100 Subject: [PATCH 3/5] Update metric tables when filtering on referrer Signed-off-by: Kevin Decherf --- components/metrics/MetricsTable.js | 5 +++-- lib/queries.js | 9 ++++++++- pages/api/website/[id]/metrics.js | 3 ++- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/components/metrics/MetricsTable.js b/components/metrics/MetricsTable.js index d8065fe3..e1fa6891 100644 --- a/components/metrics/MetricsTable.js +++ b/components/metrics/MetricsTable.js @@ -30,7 +30,7 @@ export default function MetricsTable({ const { resolve, router, - query: { url }, + query: { url, referrer }, } = usePageQuery(); const { data, loading, error } = useFetch( @@ -41,12 +41,13 @@ export default function MetricsTable({ start_at: +startDate, end_at: +endDate, url, + referrer, }, onDataLoad, delay: DEFAULT_ANIMATION_DURATION, headers: { [TOKEN_HEADER]: shareToken?.token }, }, - [modified], + [modified, url, referrer], ); const filteredData = useMemo(() => { diff --git a/lib/queries.js b/lib/queries.js index 6b3c6c4e..ed644874 100644 --- a/lib/queries.js +++ b/lib/queries.js @@ -444,10 +444,11 @@ export function getSessionMetrics(website_id, start_at, end_at, field, filters = export function getPageviewMetrics(website_id, start_at, end_at, field, table, filters = {}) { const params = [website_id, start_at, end_at]; - const { domain, url } = filters; + const { domain, url, referrer } = filters; let domainFilter = ''; let urlFilter = ''; + let refFilter = ''; if (domain) { domainFilter = `and referrer not like $${params.length + 1} and referrer not like '/%'`; @@ -459,6 +460,11 @@ export function getPageviewMetrics(website_id, start_at, end_at, field, table, f params.push(decodeURIComponent(url)); } + if (referrer) { + refFilter = `and referrer like $${params.length + 1}`; + params.push(`%${decodeURIComponent(referrer)}%`); + } + return rawQuery( ` select ${field} x, count(*) y @@ -467,6 +473,7 @@ export function getPageviewMetrics(website_id, start_at, end_at, field, table, f and created_at between $2 and $3 ${domainFilter} ${urlFilter} + ${refFilter} group by 1 order by 2 desc `, diff --git a/pages/api/website/[id]/metrics.js b/pages/api/website/[id]/metrics.js index 5e16e350..941b99ca 100644 --- a/pages/api/website/[id]/metrics.js +++ b/pages/api/website/[id]/metrics.js @@ -30,7 +30,7 @@ export default async (req, res) => { return unauthorized(res); } - const { id, type, start_at, end_at, url } = req.query; + const { id, type, start_at, end_at, url, referrer } = req.query; const websiteId = +id; const startDate = new Date(+start_at); @@ -75,6 +75,7 @@ export default async (req, res) => { { domain, url: type !== 'url' && url, + referrer: referrer, }, ); From 5d799a327bbe0ac43a76fcdc1aff65d5401a4ad1 Mon Sep 17 00:00:00 2001 From: Kevin Decherf Date: Thu, 24 Mar 2022 23:20:06 +0100 Subject: [PATCH 4/5] fixup! Rename ref to prevent collision with react elements Signed-off-by: Kevin Decherf --- lib/filters.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/filters.js b/lib/filters.js index 945a6011..fb6b435a 100644 --- a/lib/filters.js +++ b/lib/filters.js @@ -74,7 +74,7 @@ export const refFilter = (data, { domain, domainOnly, raw }) => { if (protocol.startsWith('http')) { const path = removeTrailingSlash(pathname); - const referrer = searchParams.get('ref'); + const referrer = searchParams.get('referrer'); const query = referrer ? `?referrer=${referrer}` : ''; return removeTrailingSlash(`${removeWWW(hostname)}${path}`) + query; From 1269bea870c02635a4bb8d7651deed9a6aab63e9 Mon Sep 17 00:00:00 2001 From: Kevin Decherf Date: Thu, 24 Mar 2022 23:20:19 +0100 Subject: [PATCH 5/5] fixup! Update metric tables when filtering on referrer Signed-off-by: Kevin Decherf --- pages/api/website/[id]/metrics.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/api/website/[id]/metrics.js b/pages/api/website/[id]/metrics.js index 941b99ca..675427db 100644 --- a/pages/api/website/[id]/metrics.js +++ b/pages/api/website/[id]/metrics.js @@ -75,7 +75,7 @@ export default async (req, res) => { { domain, url: type !== 'url' && url, - referrer: referrer, + referrer, }, );