Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add countly event tracking for migration flow [WPB-11317] #5124

Merged
merged 3 commits into from
Nov 29, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"@wireapp/api-client": "27.10.1",
"@wireapp/commons": "5.3.0",
"@wireapp/react-ui-kit": "9.26.3",
"@wireapp/telemetry": "0.1.2",
"core-js": "3.39.0",
"dotenv": "16.4.5",
"dotenv-extended": "2.9.0",
Expand All @@ -14,7 +15,8 @@
"react-dom": "18.3.1",
"react-i18next": "11.18.6",
"react-router": "7.0.1",
"react-router-dom": "6.28.0"
"react-router-dom": "6.28.0",
"uuid": "11.0.3"
},
"devDependencies": {
"@babel/core": "7.26.0",
Expand All @@ -31,6 +33,7 @@
"@types/react": "18.3.12",
"@types/react-dom": "18.3.1",
"@types/react-router-dom": "5.3.3",
"@types/uuid": "10.0.0",
"@types/webpack-env": "1.18.5",
"@typescript-eslint/eslint-plugin": "8.15.0",
"@typescript-eslint/parser": "7.17.0",
Expand Down
1 change: 1 addition & 0 deletions server/Server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ class Server {
this.app.get('/favicon.ico', (_req, res) => res.sendFile(path.join(__dirname, 'img', 'favicon.ico')));
this.app.get('/robots.txt', (_req, res) => res.sendFile(path.join(__dirname, 'robots', 'robots.txt')));
this.app.use('/script', express.static(path.join(__dirname, 'static', 'script')));
this.app.use('/libs', express.static(path.join(__dirname, 'libs')));
}

initTemplateEngine(): void {
Expand Down
2 changes: 2 additions & 0 deletions server/ServerConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ export interface ServerConfig {
URL_TERMS_OF_USE_TEAMS: string;
URL_SUPPORT_BACKUP_HISTORY: string;
};
COUNTLY_SERVER_URL: string;
COUNTLY_API_KEY: string;
VERSION: string;
};
COMMIT: string;
Expand Down
6 changes: 6 additions & 0 deletions server/bin/copy_server_assets.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,15 @@ const path = require('path');

const srcFolder = '../';
const distFolder = '../dist/';
const npmModulesFolder = '../../node_modules/';

const assetFolders = ['.ebextensions/', 'img/', 'robots/', 'templates/', 'certificate'];

assetFolders.forEach(assetFolder => {
fs.copySync(path.resolve(__dirname, srcFolder, assetFolder), path.resolve(__dirname, distFolder, assetFolder));
});

fs.copySync(
path.resolve(__dirname, npmModulesFolder, '@wireapp/telemetry/lib/embed.js'),
path.resolve(__dirname, distFolder, 'libs/wire/telemetry/embed.js'),
);
2 changes: 2 additions & 0 deletions server/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ const config: ServerConfig = {
URL_SUPPORT_BACKUP_HISTORY: process.env.URL_SUPPORT_BACKUP_HISTORY,
},
VERSION: readFile(VERSION_FILE, '0.0.0'),
COUNTLY_SERVER_URL: process.env.COUNTLY_SERVER_URL,
COUNTLY_API_KEY: process.env.COUNTLY_API_KEY,
},
COMMIT: readFile(COMMIT_FILE, ''),
PIWIK_HOSTNAME: process.env.PIWIK_HOSTNAME,
Expand Down
4 changes: 3 additions & 1 deletion server/templates/index.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
<meta property="og:title" content="Wire">
<meta property="og:type" content="website">
<meta property="og:image" content="{{config.CLIENT.URL.OPEN_GRAPH_IMAGE}}">

{{#if config.CLIENT.COUNTLY_API_KEY}}
<script src="/libs/wire/telemetry/embed.js"></script>
{{/if}}
<title>Wire</title>
</head>

Expand Down
5 changes: 4 additions & 1 deletion src/script/Environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ declare global {
NEW_PASSWORD_MINIMUM_LENGTH: number;
RAYGUN_API_KEY: string;
STRIPE_API_KEY: string;
COUNTLY_SERVER_URL: string;
COUNTLY_API_KEY: string;
URL: {
ACCOUNT_DELETE_SURVEY: string;
DOWNLOAD_ANDROID_BASE: string;
Expand Down Expand Up @@ -98,4 +100,5 @@ export const SUPPORT_URL = window.wire.env.URL.SUPPORT_BASE;
export const TEAMS_URL = window.wire.env.URL.TEAMS_BASE;
export const WEBSITE_URL = window.wire.env.URL.WEBSITE_BASE;
export const URL_SUPPORT_BACKUP_HISTORY = window.wire.env.URL.URL_SUPPORT_BACKUP_HISTORY;
export const URL_TERMS_OF_USE_TEAMS = window.wire.env.URL.URL_TERMS_OF_USE_TEAMS;
export const COUNTLY_SERVER_URL = window.wire.env.COUNTLY_SERVER_URL;
export const COUNTLY_API_KEY = window.wire.env.COUNTLY_API_KEY;
3 changes: 3 additions & 0 deletions src/script/Root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {TermsAcknowledgement} from './page/migration/TermsAcknowledgement';
import {ConfirmInvitation} from './page/migration/ConfirmInvitation';
import {Welcome} from './page/migration/Welcome';
import {AcceptInvitation} from './page/migration/AcceptInvitation';
import {initializeTelemetry} from './util/Tracking/Tracking';

const LazyIndex = lazy(() => import('./page/Index'));
const LazyDeleteAccount = lazy(() => import('./page/DeleteAccount'));
Expand All @@ -45,6 +46,8 @@ const Root = () => {
const hlParam = queryParams.get(QUERY_KEY.LANG);
const userLocale = navigator.languages?.length ? navigator.languages[0] : navigator.language;

initializeTelemetry();

if (!hlParam && !userLocale.includes('en')) {
queryParams.set(QUERY_KEY.LANG, userLocale);
window.history.pushState(null, '', `?${queryParams.toString()}`);
Expand Down
19 changes: 18 additions & 1 deletion src/script/page/migration/AcceptInvitation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ import {useTranslation} from 'react-i18next';
import {LoginData} from '@wireapp/api-client/lib/auth';
import {ClientType} from '@wireapp/api-client/lib/client';
import {useActionContext} from 'script/module/action';
import {reportEvent} from 'script/util/Tracking/Tracking';
import {EventName, SegmentationKey, SegmentationValue} from 'script/util/Tracking/types';

export const AcceptInvitation = () => {
const [searchParams] = useSearchParams();
Expand All @@ -54,7 +56,15 @@ export const AcceptInvitation = () => {
const code = searchParams.get(QUERY_KEY.TEAM_CODE);
const cachedCode = getTeamInvitationCode();

const trackEvent = (step: SegmentationValue) => {
reportEvent(EventName.USER_MIGRATION_LOGIN, {
[SegmentationKey.STEP]: step,
});
};

useEffect(() => {
trackEvent(SegmentationValue.OPENED);

if (!code && !cachedCode) {
navigate(ROUTE.HOME);
}
Expand All @@ -75,6 +85,7 @@ export const AcceptInvitation = () => {
const handleLogin = async (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
setError('');
trackEvent(SegmentationValue.CONTINUE_CLICKED);

const login: LoginData = {
clientType: ClientType.PERMANENT,
Expand Down Expand Up @@ -116,6 +127,7 @@ export const AcceptInvitation = () => {
title={t('invitationPagLoginLabel')}
value={email}
data-uie-name="enter-login-identifier"
onBlur={() => trackEvent(SegmentationValue.EMAIL_ENTERED)}
/>

<Input
Expand All @@ -130,9 +142,14 @@ export const AcceptInvitation = () => {
type="password"
value={password}
data-uie-name="enter-login-password"
onBlur={() => trackEvent(SegmentationValue.PASSWORD_ENTERED)}
/>
<div css={forgotPasswordCss}>
<Link href={ROUTE.PASSWORD_FORGOT} data-uie-name="go-forgot-password">
<Link
href={ROUTE.PASSWORD_FORGOT}
onClick={() => trackEvent(SegmentationValue.PASSWORD_FORGOTTEN)}
data-uie-name="go-forgot-password"
>
{t('forgotPassword')}
</Link>
</div>
Expand Down
15 changes: 14 additions & 1 deletion src/script/page/migration/ConfirmInvitation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,14 @@ import {
useMatchMedia,
} from '@wireapp/react-ui-kit';
import {loginContainerCss, loginSubHeaderCss, headerCss, forgotPasswordCss, buttonCss} from './styles';
import React, {useState} from 'react';
import React, {useEffect, useState} from 'react';
import {ROUTE} from 'script/route';
import {useNavigate} from 'react-router-dom';
import {getTeamInvitationCode, removeTeamInvitationCode} from './utils';
import {useTranslation} from 'react-i18next';
import {useActionContext} from 'script/module/action';
import {reportEvent} from 'script/util/Tracking/Tracking';
import {EventName, SegmentationKey, SegmentationValue} from 'script/util/Tracking/types';

export const ConfirmInvitation = () => {
const isTablet = useMatchMedia(QUERY[QueryKeys.TABLET_DOWN]);
Expand All @@ -48,8 +50,14 @@ export const ConfirmInvitation = () => {
const [loading, setLoading] = useState(false);
const code = getTeamInvitationCode();

const trackEvent = (step: SegmentationValue) => {
reportEvent(EventName.USER_MIGRATION_CONFIRMATION, {
[SegmentationKey.STEP]: step,
});
};
const handleSubmit = (event: any) => {
event.preventDefault();
trackEvent(SegmentationValue.CONTINUE_CLICKED);
setLoading(true);
teamAction
.acceptInvitation({
Expand All @@ -68,6 +76,10 @@ export const ConfirmInvitation = () => {
});
};

useEffect(() => {
trackEvent(SegmentationValue.OPENED);
}, []);

return (
<div css={loginContainerCss}>
{isTablet && <Logo />}
Expand All @@ -86,6 +98,7 @@ export const ConfirmInvitation = () => {
type="password"
value={password}
data-uie-name="enter-login-password"
onBlur={() => trackEvent(SegmentationValue.PASSWORD_ENTERED)}
/>
<div css={forgotPasswordCss}>
<Link href={ROUTE.PASSWORD_FORGOT} data-uie-name="go-forgot-password">
Expand Down
18 changes: 17 additions & 1 deletion src/script/page/migration/TermsAcknowledgement.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ import {useTranslation} from 'react-i18next';
import MarkupTranslation from 'script/component/MarkupTranslation';
import {useActionContext} from 'script/module/action';
import {getTeamInvitationCode} from './utils';
import {reportEvent} from 'script/util/Tracking/Tracking';
import {EventName, SegmentationKey, SegmentationValue} from 'script/util/Tracking/types';

export const TermsAcknowledgement = () => {
const navigate = useNavigate();
Expand All @@ -66,7 +68,14 @@ export const TermsAcknowledgement = () => {
const [isTermOfUseAccepted, setIsTermOfUseAccepted] = useState(false);
const [inviterEmail, setInviterEmail] = useState('');

const trackEvent = (step: SegmentationValue) => {
reportEvent(EventName.USER_MIGRATION_TERMS_ACKNOWLEDGEMENT, {
[SegmentationKey.STEP]: step,
});
};

useEffect(() => {
trackEvent(SegmentationValue.OPENED);
teamAction
.getInvitationInfo(code)
.then(res => {
Expand All @@ -83,6 +92,11 @@ export const TermsAcknowledgement = () => {
);
}

const handleSubmit = () => {
navigate(ROUTE.CONFIRM_INVITATION);
trackEvent(SegmentationValue.CONTINUE_CLICKED);
};

return (
<div css={termsContainerCss}>
{isTablet && (
Expand Down Expand Up @@ -141,6 +155,7 @@ export const TermsAcknowledgement = () => {
checked={isMigrationAccepted}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
setIsMigrationAccepted(event.target.checked);
trackEvent(SegmentationValue.AGREE_MIGRATION_TERMS_CHECK);
}}
id="do-accept-migration"
data-uie-name="do-accept-migration"
Expand All @@ -152,6 +167,7 @@ export const TermsAcknowledgement = () => {
checked={isTermOfUseAccepted}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
setIsTermOfUseAccepted(event.target.checked);
trackEvent(SegmentationValue.AGREE_TOC_CHECK);
}}
id="do-accept-terms"
data-uie-name="do-accept-terms"
Expand All @@ -166,7 +182,7 @@ export const TermsAcknowledgement = () => {
</div>
<div css={{margin: '0 2rem'}}>
<Button
onClick={() => navigate(ROUTE.CONFIRM_INVITATION)}
onClick={handleSubmit}
disabled={!isTermOfUseAccepted || !isMigrationAccepted}
data-uie-name="do-continue"
aria-label=""
Expand Down
28 changes: 21 additions & 7 deletions src/script/page/migration/Welcome.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ import {isOwner, MemberData} from '@wireapp/api-client/lib/team/member';
import {TeamData} from '@wireapp/api-client/lib/team';
import {secureOpen} from 'script/util/urlUtil';
import MarkupTranslation from 'script/component/MarkupTranslation';
import {reportEvent} from 'script/util/Tracking/Tracking';
import {EventName, SegmentationKey, SegmentationValue} from 'script/util/Tracking/types';

export const Welcome = () => {
const [t] = useTranslation(['migration']);
Expand All @@ -61,7 +63,14 @@ export const Welcome = () => {
return {member, team};
};

const trackEvent = (step: SegmentationValue) => {
reportEvent(EventName.USER_MIGRATION_WELCOME, {
[SegmentationKey.STEP]: step,
});
};

useEffect(() => {
trackEvent(SegmentationValue.OPENED);
getData()
.then(res => {
setSelfMember(res.member);
Expand All @@ -83,19 +92,24 @@ export const Welcome = () => {
);
}

const handleAppOpen = () => {
trackEvent(SegmentationValue.OPENED_WEB_APP);
secureOpen(EXTERNAL_ROUTE.APP_WIRE);
};

const handleTMOpen = () => {
trackEvent(SegmentationValue.OPENED_TM);
secureOpen(EXTERNAL_ROUTE.TEAM_SETTINGS);
};

return (
<div css={loginContainerCss}>
{isTablet && <Logo />}
<Text css={headerCss}>{t('welcomePageHeader')}</Text>
<Text css={loginSubHeaderCss}>
<MarkupTranslation translation={t('welcomePageSubHeader', {teamName: team.name})} />
</Text>
<Button
variant={ButtonVariant.PRIMARY}
data-uie-name="do-open-app"
block
onClick={() => secureOpen(EXTERNAL_ROUTE.APP_WIRE)}
>
<Button variant={ButtonVariant.PRIMARY} data-uie-name="do-open-app" block onClick={handleAppOpen}>
{t('welcomePageAppOpenText')}
</Button>
{isOwner(selfMember.permissions) && (
Expand All @@ -118,7 +132,7 @@ export const Welcome = () => {
data-uie-name="do-go-to-team-management"
block
variant={ButtonVariant.SECONDARY}
onClick={() => secureOpen(EXTERNAL_ROUTE.TEAM_SETTINGS)}
onClick={handleTMOpen}
>
{t('welcomePageTMOpenText')}
<ArrowIcon color={COLOR.BLUE} direction="right" css={{marginLeft: 12}} />
Expand Down
Loading
Loading