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

View File

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

View File

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

View File

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

View File

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

View File

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