Updated summary query. Added visit time.

This commit is contained in:
Mike Cao 2020-07-29 21:40:26 -07:00
parent da2d383b71
commit efdbd1c632
4 changed files with 69 additions and 24 deletions

View File

@ -1,11 +1,12 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import MetricCard from './MetricCard'; import MetricCard from './MetricCard';
import { get } from '../lib/web'; import { get } from '../lib/web';
import { formatShortTime } from 'lib/format';
import styles from './WebsiteSummary.module.css'; import styles from './WebsiteSummary.module.css';
export default function WebsiteSummary({ websiteId, startDate, endDate }) { export default function WebsiteSummary({ websiteId, startDate, endDate }) {
const [data, setData] = useState({}); const [data, setData] = useState({});
const { pageviews, uniques, bounces } = data; const { pageviews, uniques, bounces, totaltime } = data;
async function loadData() { async function loadData() {
setData( setData(
@ -29,6 +30,11 @@ export default function WebsiteSummary({ websiteId, startDate, endDate }) {
value={uniques ? (bounces / uniques) * 100 : 0} value={uniques ? (bounces / uniques) * 100 : 0}
format={n => Number(n).toFixed(0) + '%'} format={n => Number(n).toFixed(0) + '%'}
/> />
<MetricCard
label="Average visit time"
value={totaltime && pageviews ? totaltime / (pageviews - bounces) : 0}
format={n => formatShortTime(n, ['m', 's'], ' ')}
/>
</div> </div>
); );
} }

View File

@ -184,28 +184,21 @@ export async function getSummary(website_id, start_at, end_at) {
return runQuery( return runQuery(
prisma.queryRaw( prisma.queryRaw(
` `
select select sum(t.c) as "pageviews",
(select count(*) count(distinct t.session_id) as "uniques",
from pageview sum(case when t.c = 1 then t.c else 0 end) as "bounces",
where website_id=${website_id} sum(t.time) as "totaltime"
and created_at between '${start_at}' and '${end_at}' from (
) as "pageviews", select session_id,
(select date_trunc('hour', created_at),
count(distinct session_id) count(*) c,
from pageview floor(extract(epoch from max(created_at) - min(created_at))) as "time"
where website_id=${website_id} from pageview
and created_at between '${start_at}' and '${end_at}' where website_id=${website_id}
) as "uniques", and created_at between '${start_at}' and '${end_at}'
(select sum(t.c) from group by 1, 2
(select count(*) c ) t;
from pageview `,
where website_id=${website_id}
and created_at between '${start_at}' and '${end_at}'
group by session_id
having count(*) = 1
) t
) as "bounces"
`,
), ),
); );
} }

41
lib/format.js Normal file
View File

@ -0,0 +1,41 @@
export function parseTime(val) {
const days = ~~(val / 86400);
const hours = ~~(val / 3600) - days * 24;
const minutes = ~~(val / 60) - days * 1440 - hours * 60;
const seconds = ~~val - days * 86400 - hours * 3600 - minutes * 60;
const ms = (val - ~~val) * 1000;
return {
days,
hours,
minutes,
seconds,
ms,
};
}
export function formatTime(val) {
const { hour, minutes, seconds } = parseTime(val);
const h = hour > 0 ? `${hour}:` : '';
const m = hour > 0 ? minutes.toString().padStart(2, '0') : minutes;
const s = seconds.toString().padStart(2, '0');
return `${h}${m}:${s}`;
}
export function formatShortTime(val, formats = ['m', 's'], space = '') {
if (val === 0) {
return `0${formats[formats.length - 1]}`;
}
const { days, hours, minutes, seconds, ms } = parseTime(val);
let t = '';
if (days > 0 && formats.indexOf('d') !== -1) t += `${days}d${space}`;
if (hours > 0 && formats.indexOf('h') !== -1) t += `${hours}h${space}`;
if (minutes > 0 && formats.indexOf('m') !== -1) t += `${minutes}m${space}`;
if (seconds > 0 && formats.indexOf('s') !== -1) t += `${seconds}s${space}`;
if (ms > 0 && formats.indexOf('ms') !== -1) t += `${ms}ms`;
return t;
}

View File

@ -13,5 +13,10 @@ export default async (req, res) => {
format(new Date(+end_at), 'yyyy-MM-dd hh:mm:ss'), format(new Date(+end_at), 'yyyy-MM-dd hh:mm:ss'),
); );
return res.status(200).json(summary[0]); const stats = Object.keys(summary[0]).reduce((obj, key) => {
obj[key] = +summary[0][key];
return obj;
}, {});
return res.status(200).json(stats);
}; };