📈(frontend) get user analytics
We will identify users by their email address. This will help us understand how users interact with the platform and improve the user experience.
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
import { renderHook, waitFor } from '@testing-library/react';
|
||||
import fetchMock from 'fetch-mock';
|
||||
import { Fragment } from 'react';
|
||||
|
||||
import { AbstractAnalytic } from '@/libs';
|
||||
import { AppWrapper } from '@/tests/utils';
|
||||
|
||||
import { useAuth } from '../useAuth';
|
||||
|
||||
const trackEventMock = jest.fn();
|
||||
const flag = true;
|
||||
class TestAnalytic extends AbstractAnalytic {
|
||||
public constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
public Provider() {
|
||||
return <Fragment />;
|
||||
}
|
||||
|
||||
public trackEvent(props: any) {
|
||||
trackEventMock(props);
|
||||
}
|
||||
|
||||
public isFeatureFlagActivated(flagName: string): boolean {
|
||||
if (flagName === 'CopyAsHTML') {
|
||||
return flag;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
jest.mock('next/router', () => ({
|
||||
...jest.requireActual('next/router'),
|
||||
useRouter: () => ({
|
||||
pathname: '/dashboard',
|
||||
replace: jest.fn(),
|
||||
}),
|
||||
}));
|
||||
|
||||
const dummyUser = { id: '123', email: 'test@example.com' };
|
||||
|
||||
describe('useAuth hook - trackEvent effect', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
fetchMock.restore();
|
||||
});
|
||||
|
||||
test('calls trackEvent when user exists, isSuccess is true, and event was not tracked yet', async () => {
|
||||
new TestAnalytic();
|
||||
|
||||
fetchMock.get('http://test.jest/api/v1.0/users/me/', {
|
||||
body: JSON.stringify(dummyUser),
|
||||
});
|
||||
|
||||
renderHook(() => useAuth(), {
|
||||
wrapper: AppWrapper,
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(trackEventMock).toHaveBeenCalledWith({
|
||||
eventName: 'user',
|
||||
id: dummyUser.id,
|
||||
email: dummyUser.email,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('does not call trackEvent if already tracked', () => {
|
||||
fetchMock.get('http://test.jest/api/v1.0/users/me/', {
|
||||
body: JSON.stringify(dummyUser),
|
||||
});
|
||||
|
||||
renderHook(() => useAuth(), {
|
||||
wrapper: AppWrapper,
|
||||
});
|
||||
|
||||
expect(trackEventMock).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -1,6 +1,8 @@
|
||||
import { useRouter } from 'next/router';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { useAnalytics } from '@/libs';
|
||||
|
||||
import { useAuthQuery } from '../api';
|
||||
|
||||
const regexpUrlsAuth = [/\/docs\/$/g, /\/docs$/g, /^\/$/g];
|
||||
@@ -8,7 +10,8 @@ const regexpUrlsAuth = [/\/docs\/$/g, /\/docs$/g, /^\/$/g];
|
||||
export const useAuth = () => {
|
||||
const { data: user, ...authStates } = useAuthQuery();
|
||||
const { pathname } = useRouter();
|
||||
|
||||
const { trackEvent } = useAnalytics();
|
||||
const [hasTracked, setHasTracked] = useState(authStates.isFetched);
|
||||
const [pathAllowed, setPathAllowed] = useState<boolean>(
|
||||
!regexpUrlsAuth.some((regexp) => !!pathname.match(regexp)),
|
||||
);
|
||||
@@ -17,6 +20,17 @@ export const useAuth = () => {
|
||||
setPathAllowed(!regexpUrlsAuth.some((regexp) => !!pathname.match(regexp)));
|
||||
}, [pathname]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!hasTracked && user && authStates.isSuccess) {
|
||||
trackEvent({
|
||||
eventName: 'user',
|
||||
id: user?.id || '',
|
||||
email: user?.email || '',
|
||||
});
|
||||
setHasTracked(true);
|
||||
}
|
||||
}, [hasTracked, authStates.isSuccess, user, trackEvent]);
|
||||
|
||||
return {
|
||||
user,
|
||||
authenticated: !!user && authStates.isSuccess,
|
||||
|
||||
@@ -3,7 +3,7 @@ import posthog from 'posthog-js';
|
||||
import { PostHogProvider as PHProvider } from 'posthog-js/react';
|
||||
import { JSX, PropsWithChildren, ReactNode, useEffect } from 'react';
|
||||
|
||||
import { AbstractAnalytic } from '@/libs/';
|
||||
import { AbstractAnalytic, AnalyticEvent } from '@/libs/';
|
||||
|
||||
export class PostHogAnalytic extends AbstractAnalytic {
|
||||
private conf?: PostHogConf = undefined;
|
||||
@@ -18,7 +18,11 @@ export class PostHogAnalytic extends AbstractAnalytic {
|
||||
return <PostHogProvider conf={this.conf}>{children}</PostHogProvider>;
|
||||
}
|
||||
|
||||
public trackEvent(): void {}
|
||||
public trackEvent(evt: AnalyticEvent): void {
|
||||
if (evt.eventName === 'user') {
|
||||
posthog.identify(evt.id, { email: evt.email });
|
||||
}
|
||||
}
|
||||
|
||||
public isFeatureFlagActivated(flagName: string): boolean {
|
||||
if (
|
||||
|
||||
Reference in New Issue
Block a user