From 6d5a4d6e3f1ea52ff41c07d6cd1160fc8ffd6fb4 Mon Sep 17 00:00:00 2001 From: James Grugett Date: Tue, 22 Mar 2022 16:24:26 -0500 Subject: [PATCH] Week-on-week retention graph --- web/components/analytics/charts.tsx | 48 +++++++++++++++++++++++++++++ web/pages/analytics.tsx | 42 ++++++++++++++++++++++++- 2 files changed, 89 insertions(+), 1 deletion(-) diff --git a/web/components/analytics/charts.tsx b/web/components/analytics/charts.tsx index 1f627475..47e5b203 100644 --- a/web/components/analytics/charts.tsx +++ b/web/components/analytics/charts.tsx @@ -47,3 +47,51 @@ export function DailyCountChart(props: { ) } + +export function DailyPercentChart(props: { + startDate: number + dailyPercent: number[] + small?: boolean +}) { + const { dailyPercent, startDate, small } = props + const { width } = useWindowSize() + + const dates = dailyPercent.map((_, i) => + dayjs(startDate).add(i, 'day').toDate() + ) + + const points = _.zip(dates, dailyPercent).map(([date, betCount]) => ({ + x: date, + y: betCount, + })) + const data = [{ id: 'Percent', data: points, color: '#11b981' }] + + return ( +
= 800) ? 400 : 250 }} + > + `${value}%`, + }} + axisBottom={{ + format: (date) => dayjs(date).format('MMM DD'), + }} + colors={{ datum: 'color' }} + pointSize={0} + pointBorderWidth={1} + pointBorderColor="#fff" + enableSlices="x" + enableGridX={!!width && width >= 800} + enableArea + margin={{ top: 20, right: 28, bottom: 22, left: 40 }} + /> +
+ ) +} diff --git a/web/pages/analytics.tsx b/web/pages/analytics.tsx index e87fd086..6c0e428d 100644 --- a/web/pages/analytics.tsx +++ b/web/pages/analytics.tsx @@ -1,7 +1,10 @@ import dayjs from 'dayjs' import _ from 'lodash' import { IS_PRIVATE_MANIFOLD } from '../../common/envs/constants' -import { DailyCountChart } from '../components/analytics/charts' +import { + DailyCountChart, + DailyPercentChart, +} from '../components/analytics/charts' import { Col } from '../components/layout/col' import { Spacer } from '../components/layout/spacer' import { Page } from '../components/page' @@ -58,6 +61,31 @@ export async function getStaticPropz() { return uniques.size }) + const weekOnWeekRetention = dailyUserIds.map((_userId, i) => { + const twoWeeksAgo = { + start: Math.max(0, i - 13), + end: Math.max(0, i - 7), + } + const lastWeek = { + start: Math.max(0, i - 6), + end: i, + } + + const activeTwoWeeksAgo = new Set() + for (let j = twoWeeksAgo.start; j <= twoWeeksAgo.end; j++) { + dailyUserIds[j].forEach((userId) => activeTwoWeeksAgo.add(userId)) + } + const activeLastWeek = new Set() + for (let j = lastWeek.start; j <= lastWeek.end; j++) { + dailyUserIds[j].forEach((userId) => activeLastWeek.add(userId)) + } + const retainedCount = _.sumBy(Array.from(activeTwoWeeksAgo), (userId) => + activeLastWeek.has(userId) ? 1 : 0 + ) + const retainedFrac = retainedCount / activeTwoWeeksAgo.size + return Math.round(retainedFrac * 100 * 100) / 100 + }) + return { props: { startDate: startDate.valueOf(), @@ -67,6 +95,7 @@ export async function getStaticPropz() { dailyBetCounts, dailyContractCounts, dailyCommentCounts, + weekOnWeekRetention, }, revalidate: 12 * 60 * 60, // regenerate after half a day } @@ -80,6 +109,7 @@ export default function Analytics(props: { dailyBetCounts: number[] dailyContractCounts: number[] dailyCommentCounts: number[] + weekOnWeekRetention: number[] }) { props = usePropz(props, getStaticPropz) ?? { startDate: 0, @@ -89,6 +119,7 @@ export default function Analytics(props: { dailyBetCounts: [], dailyContractCounts: [], dailyCommentCounts: [], + weekOnWeekRetention: [], } return ( @@ -107,6 +138,7 @@ export function CustomAnalytics(props: { dailyBetCounts: number[] dailyContractCounts: number[] dailyCommentCounts: number[] + weekOnWeekRetention: number[] }) { const { startDate, @@ -116,6 +148,7 @@ export function CustomAnalytics(props: { dailyCommentCounts, weeklyActiveUsers, monthlyActiveUsers, + weekOnWeekRetention, } = props return ( @@ -140,6 +173,13 @@ export function CustomAnalytics(props: { small /> + + <DailyPercentChart + dailyPercent={weekOnWeekRetention} + startDate={startDate} + small + /> + <Title text="Trades" /> <DailyCountChart dailyCounts={dailyBetCounts}