1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-02-09 00:18:00 +01:00

feat: add user tracking to demo (#3637)

https://linear.app/unleash/issue/2-946/explore-and-implement-options-for-user-tracking

Adds user tracking to the interactive demo, so we can measure how users
are using this feature and improve it in the feature.

## Events

- **start** - When the user starts the demo by clicking on the "Try
Unleash Demo" button;
- **finish** - When the user finishes the demo by seeing the "You
finished the demo" dialog;
- **restart** - When the user decides to restart the demo on the "You
finished the demo" dialog;
- **close** - When the user closes a demo dialog;
- **topic** - In what topic this happened (topic title, can also be
`start` if user closes on the start dialog);
- **step** - In what step this happened (step number, `1` would mean
first step);
- **start_topic** - When the user decides to start a specific topic by
clicking it in the list;
  - **topic** - What topic was clicked (topic title);
- **ask_questions** - When the user decides to ask questions by clicking
the appropriate option in the top banner;
- **see_plans** - When the user decides to see the plans by clicking the
appropriate option in the top banner;
- **plan** - What plan was clicked (one of: `open_source`, `pro`,
`enterprise` or `compare_plans`);
- **open_demo_web** - User decided to open the demo website using the
link on the start dialog;
- **view_demo_link** - User decided to open the start dialog again on
the bottom of the topics list;

Relates to [roadmap](https://github.com/orgs/Unleash/projects/10) item:
#3537
This commit is contained in:
Nuno Góis 2023-04-27 14:12:02 +01:00 committed by GitHub
parent 9deff83d74
commit 3c48171c78
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 260 additions and 131 deletions

View File

@ -8,6 +8,7 @@ import { DemoDialogFinish } from './DemoDialog/DemoDialogFinish/DemoDialogFinish
import { DemoDialogPlans } from './DemoDialog/DemoDialogPlans/DemoDialogPlans'; import { DemoDialogPlans } from './DemoDialog/DemoDialogPlans/DemoDialogPlans';
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
import { DemoBanner } from './DemoBanner/DemoBanner'; import { DemoBanner } from './DemoBanner/DemoBanner';
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
const defaultProgress = { const defaultProgress = {
welcomeOpen: true, welcomeOpen: true,
@ -22,6 +23,7 @@ interface IDemoProps {
export const Demo = ({ children }: IDemoProps): JSX.Element => { export const Demo = ({ children }: IDemoProps): JSX.Element => {
const { uiConfig } = useUiConfig(); const { uiConfig } = useUiConfig();
const { trackEvent } = usePlausibleTracker();
const { value: storedProgress, setValue: setStoredProgress } = const { value: storedProgress, setValue: setStoredProgress } =
createLocalStorage('Tutorial:v1', defaultProgress); createLocalStorage('Tutorial:v1', defaultProgress);
@ -66,6 +68,12 @@ export const Demo = ({ children }: IDemoProps): JSX.Element => {
if (completedSteps === totalSteps) { if (completedSteps === totalSteps) {
setFinishOpen(true); setFinishOpen(true);
trackEvent('demo', {
props: {
eventType: 'finish',
},
});
} }
}; };
@ -76,6 +84,12 @@ export const Demo = ({ children }: IDemoProps): JSX.Element => {
<DemoBanner <DemoBanner
onPlans={() => { onPlans={() => {
setPlansOpen(true); setPlansOpen(true);
trackEvent('demo', {
props: {
eventType: 'see_plans',
},
});
}} }}
/> />
{children} {children}
@ -84,10 +98,23 @@ export const Demo = ({ children }: IDemoProps): JSX.Element => {
onClose={() => { onClose={() => {
setWelcomeOpen(false); setWelcomeOpen(false);
setExpanded(false); setExpanded(false);
trackEvent('demo', {
props: {
eventType: 'close',
topic: 'start',
},
});
}} }}
onStart={() => { onStart={() => {
setWelcomeOpen(false); setWelcomeOpen(false);
onStart(); onStart();
trackEvent('demo', {
props: {
eventType: 'start',
},
});
}} }}
/> />
<DemoDialogFinish <DemoDialogFinish
@ -99,6 +126,12 @@ export const Demo = ({ children }: IDemoProps): JSX.Element => {
onRestart={() => { onRestart={() => {
setFinishOpen(false); setFinishOpen(false);
onStart(); onStart();
trackEvent('demo', {
props: {
eventType: 'restart',
},
});
}} }}
/> />
<DemoDialogPlans <DemoDialogPlans
@ -117,9 +150,24 @@ export const Demo = ({ children }: IDemoProps): JSX.Element => {
newSteps[topic] = 0; newSteps[topic] = 0;
return newSteps; return newSteps;
}); });
trackEvent('demo', {
props: {
eventType: 'start_topic',
step: TOPICS[topic].title,
},
});
}} }}
topics={TOPICS} topics={TOPICS}
onWelcome={() => setWelcomeOpen(true)} onWelcome={() => {
setWelcomeOpen(true);
trackEvent('demo', {
props: {
eventType: 'view_demo_link',
},
});
}}
/> />
<DemoSteps <DemoSteps
setExpanded={setExpanded} setExpanded={setExpanded}

View File

@ -1,4 +1,5 @@
import { Button, styled } from '@mui/material'; import { Button, styled } from '@mui/material';
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
const StyledBanner = styled('div')(({ theme }) => ({ const StyledBanner = styled('div')(({ theme }) => ({
position: 'sticky', position: 'sticky',
@ -30,17 +31,27 @@ interface IDemoBannerProps {
onPlans: () => void; onPlans: () => void;
} }
export const DemoBanner = ({ onPlans }: IDemoBannerProps) => ( export const DemoBanner = ({ onPlans }: IDemoBannerProps) => {
const { trackEvent } = usePlausibleTracker();
return (
<StyledBanner> <StyledBanner>
<span> <span>
This is a <strong>demo of Unleash</strong>. Play around as much as This is a <strong>demo of Unleash</strong>. Play around as much
you want. Reach out when you're ready. as you want. Reach out when you're ready.
</span> </span>
<StyledQuestionsButton <StyledQuestionsButton
variant="outlined" variant="outlined"
sx={{ ml: 1 }} sx={{ ml: 1 }}
href="https://slack.unleash.run/" href="https://slack.unleash.run/"
target="_blank" target="_blank"
onClick={() => {
trackEvent('demo', {
props: {
eventType: 'ask_questions',
},
});
}}
> >
Ask questions Ask questions
</StyledQuestionsButton> </StyledQuestionsButton>
@ -48,4 +59,5 @@ export const DemoBanner = ({ onPlans }: IDemoBannerProps) => (
Get Unleash Get Unleash
</StyledButton> </StyledButton>
</StyledBanner> </StyledBanner>
); );
};

View File

@ -2,6 +2,7 @@ import { Button, Typography, styled } from '@mui/material';
import { DemoDialog } from '../DemoDialog'; import { DemoDialog } from '../DemoDialog';
import { GitHub } from '@mui/icons-material'; import { GitHub } from '@mui/icons-material';
import { Launch } from '@mui/icons-material'; import { Launch } from '@mui/icons-material';
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
const StyledDemoDialog = styled(DemoDialog)(({ theme }) => ({ const StyledDemoDialog = styled(DemoDialog)(({ theme }) => ({
'& .MuiDialog-paper': { '& .MuiDialog-paper': {
@ -51,9 +52,14 @@ interface IDemoDialogPlansProps {
onClose: () => void; onClose: () => void;
} }
export const DemoDialogPlans = ({ open, onClose }: IDemoDialogPlansProps) => ( export const DemoDialogPlans = ({ open, onClose }: IDemoDialogPlansProps) => {
const { trackEvent } = usePlausibleTracker();
return (
<StyledDemoDialog open={open} onClose={onClose}> <StyledDemoDialog open={open} onClose={onClose}>
<DemoDialog.Header>Want to keep going with Unleash?</DemoDialog.Header> <DemoDialog.Header>
Want to keep going with Unleash?
</DemoDialog.Header>
<StyledPlans> <StyledPlans>
<StyledPlan> <StyledPlan>
<Typography variant="h5" fontWeight="bold"> <Typography variant="h5" fontWeight="bold">
@ -71,6 +77,14 @@ export const DemoDialogPlans = ({ open, onClose }: IDemoDialogPlansProps) => (
startIcon={<GitHub />} startIcon={<GitHub />}
href="https://github.com/unleash/unleash" href="https://github.com/unleash/unleash"
target="_blank" target="_blank"
onClick={() => {
trackEvent('demo', {
props: {
eventType: 'see_plan',
plan: 'open_source',
},
});
}}
> >
View project on GitHub View project on GitHub
</Button> </Button>
@ -80,19 +94,30 @@ export const DemoDialogPlans = ({ open, onClose }: IDemoDialogPlansProps) => (
Pro Pro
</Typography> </Typography>
<Typography variant="body2" color="textSecondary"> <Typography variant="body2" color="textSecondary">
Free your team to collaborate. We'll do the heavy lifting. Free your team to collaborate. We'll do the heavy
lifting.
</Typography> </Typography>
<div> <div>
<Typography variant="h6" fontWeight="normal"> <Typography variant="h6" fontWeight="normal">
$80/month $80/month
</Typography> </Typography>
<Typography variant="body2">includes 5 seats</Typography> <Typography variant="body2">
includes 5 seats
</Typography>
</div> </div>
<Button <Button
variant="contained" variant="contained"
color="primary" color="primary"
href="https://www.getunleash.io/plans/pro" href="https://www.getunleash.io/plans/pro"
target="_blank" target="_blank"
onClick={() => {
trackEvent('demo', {
props: {
eventType: 'see_plan',
plan: 'pro',
},
});
}}
> >
Start 14-day free trial Start 14-day free trial
</Button> </Button>
@ -102,7 +127,8 @@ export const DemoDialogPlans = ({ open, onClose }: IDemoDialogPlansProps) => (
Enterprise Enterprise
</Typography> </Typography>
<Typography variant="body2" color="textSecondary"> <Typography variant="body2" color="textSecondary">
Security, compliance, and development controls for scale. Security, compliance, and development controls for
scale.
</Typography> </Typography>
<div> <div>
<Typography variant="h6" fontWeight="normal"> <Typography variant="h6" fontWeight="normal">
@ -115,6 +141,14 @@ export const DemoDialogPlans = ({ open, onClose }: IDemoDialogPlansProps) => (
color="web" color="web"
href="https://www.getunleash.io/plans/enterprise" href="https://www.getunleash.io/plans/enterprise"
target="_blank" target="_blank"
onClick={() => {
trackEvent('demo', {
props: {
eventType: 'see_plan',
plan: 'enterprise',
},
});
}}
> >
Contact sales Contact sales
</Button> </Button>
@ -123,8 +157,17 @@ export const DemoDialogPlans = ({ open, onClose }: IDemoDialogPlansProps) => (
<StyledCompareLink <StyledCompareLink
href="https://www.getunleash.io/plans" href="https://www.getunleash.io/plans"
target="_blank" target="_blank"
onClick={() => {
trackEvent('demo', {
props: {
eventType: 'see_plan',
plan: 'compare_plans',
},
});
}}
> >
Compare plans <Launch /> Compare plans <Launch />
</StyledCompareLink> </StyledCompareLink>
</StyledDemoDialog> </StyledDemoDialog>
); );
};

View File

@ -3,6 +3,7 @@ import qrImage from 'assets/img/demo_qr.png';
import { formatAssetPath } from 'utils/formatPath'; import { formatAssetPath } from 'utils/formatPath';
import { Launch } from '@mui/icons-material'; import { Launch } from '@mui/icons-material';
import { DemoDialog } from '../DemoDialog'; import { DemoDialog } from '../DemoDialog';
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
const StyledDemoPane = styled('div')(({ theme }) => ({ const StyledDemoPane = styled('div')(({ theme }) => ({
display: 'flex', display: 'flex',
@ -55,25 +56,38 @@ export const DemoDialogWelcome = ({
open, open,
onClose, onClose,
onStart, onStart,
}: IDemoDialogWelcomeProps) => ( }: IDemoDialogWelcomeProps) => {
const { trackEvent } = usePlausibleTracker();
return (
<DemoDialog open={open} onClose={onClose}> <DemoDialog open={open} onClose={onClose}>
<DemoDialog.Header>Explore Unleash</DemoDialog.Header> <DemoDialog.Header>Explore Unleash</DemoDialog.Header>
<Typography color="textSecondary" sx={{ mt: 2 }}> <Typography color="textSecondary" sx={{ mt: 2 }}>
You can explore Unleash on your own, however for the best experience You can explore Unleash on your own, however for the best
it's recommended you follow our interactive demo. To get started, experience it's recommended you follow our interactive demo. To
you will need to open the demo website below. get started, you will need to open the demo website below.
</Typography> </Typography>
<StyledDemoPane> <StyledDemoPane>
<StyledScanMessage> <StyledScanMessage>
Scan the QR code with your phone Scan the QR code with your phone
</StyledScanMessage> </StyledScanMessage>
<StyledQRCode src={formatAssetPath(qrImage)} alt="Demo QR Code" /> <StyledQRCode
src={formatAssetPath(qrImage)}
alt="Demo QR Code"
/>
<StyledDivider>OR</StyledDivider> <StyledDivider>OR</StyledDivider>
<Typography> <Typography>
Open demo website in another tab:{' '} Open demo website in another tab:{' '}
<StyledLink <StyledLink
href="https://demo.unleash-hosted.com/" href="https://demo.unleash-hosted.com/"
target="_blank" target="_blank"
onClick={() => {
trackEvent('demo', {
props: {
eventType: 'open_demo_web',
},
});
}}
> >
demo.unleash-hosted.com <Launch /> demo.unleash-hosted.com <Launch />
</StyledLink> </StyledLink>
@ -90,4 +104,5 @@ export const DemoDialogWelcome = ({
Try Unleash demo Try Unleash demo
</StyledStartButton> </StyledStartButton>
</DemoDialog> </DemoDialog>
); );
};

View File

@ -8,6 +8,7 @@ import { ITutorialTopic, ITutorialTopicStep } from '../demo-topics';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { useLocation, useNavigate } from 'react-router-dom'; import { useLocation, useNavigate } from 'react-router-dom';
import { DemoStepTooltip } from './DemoStepTooltip/DemoStepTooltip'; import { DemoStepTooltip } from './DemoStepTooltip/DemoStepTooltip';
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
interface IDemoStepsProps { interface IDemoStepsProps {
setExpanded: React.Dispatch<React.SetStateAction<boolean>>; setExpanded: React.Dispatch<React.SetStateAction<boolean>>;
@ -31,6 +32,7 @@ export const DemoSteps = ({
const theme = useTheme(); const theme = useTheme();
const navigate = useNavigate(); const navigate = useNavigate();
const location = useLocation(); const location = useLocation();
const { trackEvent } = usePlausibleTracker();
const [run, setRun] = useState(false); const [run, setRun] = useState(false);
const [flow, setFlow] = useState<'next' | 'back' | 'load'>('load'); const [flow, setFlow] = useState<'next' | 'back' | 'load'>('load');
@ -51,6 +53,14 @@ export const DemoSteps = ({
const close = () => { const close = () => {
abortController.abort(); abortController.abort();
setTopicStep(-1); setTopicStep(-1);
trackEvent('demo', {
props: {
eventType: 'close',
topic: topics[topic].title,
step: steps[topic] + 1,
},
});
}; };
const back = () => { const back = () => {

View File

@ -24,7 +24,8 @@ export type CustomEvents =
| 'project_stickiness_set' | 'project_stickiness_set'
| 'notifications' | 'notifications'
| 'batch_operations' | 'batch_operations'
| 'strategyTitle'; | 'strategyTitle'
| 'demo';
export const usePlausibleTracker = () => { export const usePlausibleTracker = () => {
const plausible = useContext(PlausibleContext); const plausible = useContext(PlausibleContext);