1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-01-25 00:07:47 +01:00

feat: add plausible for onboarding (#8352)

Tracking events for

1. Onboarding started/project created
2. Onboarding finishes
3. API token generated
4. Sdk example clicked

Not tracking events that can happen multiple times and results are
skewed

1. Moving between onboarding steps
This commit is contained in:
Jaanus Sellin 2024-10-03 14:41:50 +03:00 committed by GitHub
parent 0bf385d601
commit 0077a56ef6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 55 additions and 4 deletions

View File

@ -19,7 +19,7 @@ import useProjectOverview from 'hooks/api/getters/useProjectOverview/useProjectO
interface IConnectSDKDialogProps { interface IConnectSDKDialogProps {
open: boolean; open: boolean;
onClose: () => void; onClose: () => void;
onFinish: () => void; onFinish: (sdkName: string) => void;
project: string; project: string;
environments: string[]; environments: string[];
feature?: string; feature?: string;
@ -169,7 +169,12 @@ export const ConnectSdkDialog = ({
</Button> </Button>
) : null} ) : null}
<Button variant='contained' onClick={onFinish}> <Button
variant='contained'
onClick={() => {
onFinish(sdk.name);
}}
>
Complete Complete
</Button> </Button>
</NextStepSectionSpacedContainer> </NextStepSectionSpacedContainer>

View File

@ -18,6 +18,7 @@ import { useEffect } from 'react';
import { SectionHeader, StepperBox } from './SharedComponents'; import { SectionHeader, StepperBox } from './SharedComponents';
import { Stepper } from './Stepper'; import { Stepper } from './Stepper';
import { Badge } from 'component/common/Badge/Badge'; import { Badge } from 'component/common/Badge/Badge';
import { usePlausibleTracker } from '../../../hooks/usePlausibleTracker';
const ChooseEnvironment = ({ const ChooseEnvironment = ({
environments, environments,
@ -194,6 +195,7 @@ export const GenerateApiKey = ({
onEnvSelect, onEnvSelect,
onApiKey, onApiKey,
}: GenerateApiKeyProps) => { }: GenerateApiKeyProps) => {
const { trackEvent } = usePlausibleTracker();
const { tokens, refetch: refreshTokens } = useProjectApiTokens(project); const { tokens, refetch: refreshTokens } = useProjectApiTokens(project);
const { createToken, loading: creatingToken } = useProjectApiTokensApi(); const { createToken, loading: creatingToken } = useProjectApiTokensApi();
const currentEnvironmentToken = tokens.find( const currentEnvironmentToken = tokens.find(
@ -220,11 +222,20 @@ export const GenerateApiKey = ({
project, project,
); );
refreshTokens(); refreshTokens();
trackGenerate();
} catch (error: unknown) { } catch (error: unknown) {
setToastApiError(formatUnknownError(error)); setToastApiError(formatUnknownError(error));
} }
}; };
const trackGenerate = () => {
trackEvent('onboarding', {
props: {
eventType: 'api-key-generated',
},
});
};
return ( return (
<SpacedContainer> <SpacedContainer>
<Typography variant='h2'>Connect an SDK to Unleash</Typography> <Typography variant='h2'>Connect an SDK to Unleash</Typography>

View File

@ -9,6 +9,7 @@ import { Link } from 'react-router-dom';
import { useLocalStorageState } from 'hooks/useLocalStorageState'; import { useLocalStorageState } from 'hooks/useLocalStorageState';
import Select from 'component/common/select'; import Select from 'component/common/select';
import { allSdks, type SdkName } from '../dialog/sharedTypes'; import { allSdks, type SdkName } from '../dialog/sharedTypes';
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
const TitleContainer = styled('div')(({ theme }) => ({ const TitleContainer = styled('div')(({ theme }) => ({
display: 'flex', display: 'flex',
@ -51,6 +52,8 @@ type exampleDirectories =
| 'Vue'; | 'Vue';
export const SdkExample = () => { export const SdkExample = () => {
const { trackEvent } = usePlausibleTracker();
const sdkOptions = allSdks.map((sdk) => ({ const sdkOptions = allSdks.map((sdk) => ({
key: sdk.name, key: sdk.name,
label: sdk.name, label: sdk.name,
@ -64,6 +67,15 @@ export const SdkExample = () => {
setSelectedSdk(event.target.value as SdkName); setSelectedSdk(event.target.value as SdkName);
}; };
const trackClick = () => {
trackEvent('onboarding', {
props: {
eventType: 'sdk-example-opened',
sdk: selectedSdk,
},
});
};
return ( return (
<> <>
<TitleContainer>View SDK Example</TitleContainer> <TitleContainer>View SDK Example</TitleContainer>
@ -88,6 +100,7 @@ export const SdkExample = () => {
component={Link} component={Link}
variant='text' variant='text'
color='primary' color='primary'
onClick={trackClick}
> >
Go to example Go to example
</StyledButton> </StyledButton>

View File

@ -27,6 +27,7 @@ import { useStickinessOptions } from 'hooks/useStickinessOptions';
import { ChangeRequestTableConfigButton } from './ConfigButtons/ChangeRequestTableConfigButton'; import { ChangeRequestTableConfigButton } from './ConfigButtons/ChangeRequestTableConfigButton';
import { StyledDefinitionList } from './CreateProjectDialog.styles'; import { StyledDefinitionList } from './CreateProjectDialog.styles';
import { ProjectIcon } from 'component/common/ProjectIcon/ProjectIcon'; import { ProjectIcon } from 'component/common/ProjectIcon/ProjectIcon';
import { useUiFlag } from '../../../../../hooks/useUiFlag';
interface ICreateProjectDialogProps { interface ICreateProjectDialogProps {
open: boolean; open: boolean;
@ -118,6 +119,7 @@ export const CreateProjectDialog = ({
const { setToastData, setToastApiError } = useToast(); const { setToastData, setToastApiError } = useToast();
const navigate = useNavigate(); const navigate = useNavigate();
const { trackEvent } = usePlausibleTracker(); const { trackEvent } = usePlausibleTracker();
const onboardingUIEnabled = useUiFlag('onboardingUI');
const { const {
projectName, projectName,
projectDesc, projectDesc,
@ -190,6 +192,11 @@ export const CreateProjectDialog = ({
trackEvent('project-mode', { trackEvent('project-mode', {
props: { mode: projectMode, action: 'added' }, props: { mode: projectMode, action: 'added' },
}); });
if (onboardingUIEnabled) {
trackEvent('onboarding', {
props: { eventType: 'onboarding-started' },
});
}
} catch (error: unknown) { } catch (error: unknown) {
setToastApiError(formatUnknownError(error)); setToastApiError(formatUnknownError(error));
} }

View File

@ -46,6 +46,7 @@ import { ConnectSdkDialog } from '../../../onboarding/dialog/ConnectSdkDialog';
import { ProjectOnboarding } from '../../../onboarding/flow/ProjectOnboarding'; import { ProjectOnboarding } from '../../../onboarding/flow/ProjectOnboarding';
import { useLocalStorageState } from 'hooks/useLocalStorageState'; import { useLocalStorageState } from 'hooks/useLocalStorageState';
import { ProjectOnboarded } from 'component/onboarding/flow/ProjectOnboarded'; import { ProjectOnboarded } from 'component/onboarding/flow/ProjectOnboarded';
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
interface IPaginatedProjectFeatureTogglesProps { interface IPaginatedProjectFeatureTogglesProps {
environments: string[]; environments: string[];
@ -66,6 +67,7 @@ const Container = styled('div')(({ theme }) => ({
export const ProjectFeatureToggles = ({ export const ProjectFeatureToggles = ({
environments, environments,
}: IPaginatedProjectFeatureTogglesProps) => { }: IPaginatedProjectFeatureTogglesProps) => {
const { trackEvent } = usePlausibleTracker();
const onboardingUIEnabled = useUiFlag('onboardingUI'); const onboardingUIEnabled = useUiFlag('onboardingUI');
const projectId = useRequiredPathParam('projectId'); const projectId = useRequiredPathParam('projectId');
const { project } = useProjectOverview(projectId); const { project } = useProjectOverview(projectId);
@ -135,6 +137,17 @@ export const ProjectFeatureToggles = ({
const showFeaturesTable = const showFeaturesTable =
(total !== undefined && total > 0) || notOnboarding; (total !== undefined && total > 0) || notOnboarding;
const trackOnboardingFinish = (sdkName: string) => {
if (!isOnboarding) {
trackEvent('onboarding', {
props: {
eventType: 'onboarding-finished',
onboardedSdk: sdkName,
},
});
}
};
const columns = useMemo( const columns = useMemo(
() => [ () => [
columnHelper.display({ columnHelper.display({
@ -557,9 +570,10 @@ export const ProjectFeatureToggles = ({
onClose={() => { onClose={() => {
setConnectSdkOpen(false); setConnectSdkOpen(false);
}} }}
onFinish={() => { onFinish={(sdkName: string) => {
setConnectSdkOpen(false); setConnectSdkOpen(false);
setSetupCompletedState('show-setup'); setSetupCompletedState('show-setup');
trackOnboardingFinish(sdkName);
}} }}
project={projectId} project={projectId}
environments={environments} environments={environments}

View File

@ -69,7 +69,8 @@ export type CustomEvents =
| 'events-exported' | 'events-exported'
| 'event-timeline-open' | 'event-timeline-open'
| 'event-timeline-close' | 'event-timeline-close'
| 'event-timeline-event-hover'; | 'event-timeline-event-hover'
| 'onboarding';
export const usePlausibleTracker = () => { export const usePlausibleTracker = () => {
const plausible = useContext(PlausibleContext); const plausible = useContext(PlausibleContext);