From 3d63089cb2a78fd7fd216d458cf33b4cf45b7c95 Mon Sep 17 00:00:00 2001 From: Mateusz Kwasniewski Date: Tue, 3 Sep 2024 15:24:33 +0200 Subject: [PATCH] feat: ignore onboarding events for existing customers (#8064) --- .../onboarding/onboarding-service.e2e.test.ts | 15 +++++++ .../features/onboarding/onboarding-service.ts | 41 +++++++++++++------ 2 files changed, 43 insertions(+), 13 deletions(-) diff --git a/src/lib/features/onboarding/onboarding-service.e2e.test.ts b/src/lib/features/onboarding/onboarding-service.e2e.test.ts index 5cc5b2ccbefe..cc4ab8382d1c 100644 --- a/src/lib/features/onboarding/onboarding-service.e2e.test.ts +++ b/src/lib/features/onboarding/onboarding-service.e2e.test.ts @@ -76,6 +76,21 @@ test('Default project should take first user created instead of project created ]); }); +test('Ignore events for existing customers', async () => { + jest.useFakeTimers(); + jest.setSystemTime(new Date(2024, 8, 2)); // day before we added metrics + const { userStore } = stores; + await userStore.insert({}); + + jest.setSystemTime(new Date()); + await onboardingService.insert({ type: 'first-user-login' }); + + const { rows: instanceEvents } = await db.rawDatabase.raw( + 'SELECT * FROM onboarding_events_instance', + ); + expect(instanceEvents).toMatchObject([]); +}); + test('Ignore system user in onboarding events', async () => { // system users are not counted towards onboarding metrics await db.rawDatabase.raw('INSERT INTO users (is_system) VALUES (true)'); diff --git a/src/lib/features/onboarding/onboarding-service.ts b/src/lib/features/onboarding/onboarding-service.ts index 2ac13322aa38..a5394653d07a 100644 --- a/src/lib/features/onboarding/onboarding-service.ts +++ b/src/lib/features/onboarding/onboarding-service.ts @@ -13,7 +13,9 @@ import type { IOnboardingStore, ProjectEvent, } from './onboarding-store-type'; -import { millisecondsToSeconds } from 'date-fns'; +import { isBefore, millisecondsToSeconds } from 'date-fns'; + +const START_ONBOARDING_TRACKING_DATE = new Date(2024, 8, 3); export class OnboardingService { private flagResolver: IFlagResolver; @@ -92,18 +94,28 @@ export class OnboardingService { | { flag: string; type: ProjectEvent['type'] } | { type: 'first-user-login' | 'second-user-login' }, ): Promise { - await this.insertInstanceEvent(event); + const firstInstanceUserDate = await this.userStore.getFirstUserDate(); + // the time we introduced onboarding tracking + if ( + firstInstanceUserDate && + isBefore(firstInstanceUserDate, START_ONBOARDING_TRACKING_DATE) + ) + return; + + await this.insertInstanceEvent(event, firstInstanceUserDate); if ('flag' in event) { - await this.insertProjectEvent(event); + await this.insertProjectEvent(event, firstInstanceUserDate); } this.eventBus.emit('onboarding-event'); } - private async insertInstanceEvent(event: { - flag?: string; - type: InstanceEvent['type']; - }): Promise { - const firstInstanceUserDate = await this.userStore.getFirstUserDate(); + private async insertInstanceEvent( + event: { + flag?: string; + type: InstanceEvent['type']; + }, + firstInstanceUserDate: Date | null, + ): Promise { if (!firstInstanceUserDate) return; const timeToEvent = millisecondsToSeconds( @@ -115,10 +127,13 @@ export class OnboardingService { }); } - private async insertProjectEvent(event: { - flag: string; - type: ProjectEvent['type']; - }): Promise { + private async insertProjectEvent( + event: { + flag: string; + type: ProjectEvent['type']; + }, + firstInstanceUserDate: Date | null, + ): Promise { const project = await this.projectReadModel.getFeatureProject( event.flag, ); @@ -126,7 +141,7 @@ export class OnboardingService { const startDate = project.project === 'default' - ? await this.userStore.getFirstUserDate() + ? firstInstanceUserDate : project.createdAt || null; if (!startDate) return;