diff --git a/src/platform/cloud/subscription/components/SubscriptionRequiredDialogContent.vue b/src/platform/cloud/subscription/components/SubscriptionRequiredDialogContent.vue index 48787a4ee4..cbb085b95c 100644 --- a/src/platform/cloud/subscription/components/SubscriptionRequiredDialogContent.vue +++ b/src/platform/cloud/subscription/components/SubscriptionRequiredDialogContent.vue @@ -236,6 +236,7 @@ watch( () => isActiveSubscription.value, (isActive) => { if (isActive && showCustomPricingTable.value) { + telemetry?.trackMonthlySubscriptionSucceeded() emit('close', true) } } diff --git a/src/platform/workspace/stores/billingOperationStore.test.ts b/src/platform/workspace/stores/billingOperationStore.test.ts index 005ba56f7d..7df5eb6128 100644 --- a/src/platform/workspace/stores/billingOperationStore.test.ts +++ b/src/platform/workspace/stores/billingOperationStore.test.ts @@ -47,6 +47,14 @@ vi.mock('@/stores/dialogStore', () => ({ }) })) +const mockTrackMonthlySubscriptionSucceeded = vi.fn() + +vi.mock('@/platform/telemetry', () => ({ + useTelemetry: () => ({ + trackMonthlySubscriptionSucceeded: mockTrackMonthlySubscriptionSucceeded + }) +})) + import { workspaceApi } from '@/platform/workspace/api/workspaceApi' import { useBillingOperationStore } from './billingOperationStore' @@ -159,6 +167,37 @@ describe('billingOperationStore', () => { }) }) + it('fires purchase telemetry on subscription success', async () => { + vi.mocked(workspaceApi.getBillingOpStatus).mockResolvedValue({ + id: 'op-1', + status: 'succeeded', + started_at: new Date().toISOString(), + completed_at: new Date().toISOString() + }) + + const store = useBillingOperationStore() + store.startOperation('op-1', 'subscription') + + await vi.advanceTimersByTimeAsync(0) + + expect(mockTrackMonthlySubscriptionSucceeded).toHaveBeenCalledOnce() + }) + + it('does not fire purchase telemetry on topup success', async () => { + vi.mocked(workspaceApi.getBillingOpStatus).mockResolvedValue({ + id: 'op-1', + status: 'succeeded', + started_at: new Date().toISOString() + }) + + const store = useBillingOperationStore() + store.startOperation('op-1', 'topup') + + await vi.advanceTimersByTimeAsync(0) + + expect(mockTrackMonthlySubscriptionSucceeded).not.toHaveBeenCalled() + }) + it('shows topup success message for topup operations', async () => { vi.mocked(workspaceApi.getBillingOpStatus).mockResolvedValue({ id: 'op-1', diff --git a/src/platform/workspace/stores/billingOperationStore.ts b/src/platform/workspace/stores/billingOperationStore.ts index cebcd520fe..af94f2880e 100644 --- a/src/platform/workspace/stores/billingOperationStore.ts +++ b/src/platform/workspace/stores/billingOperationStore.ts @@ -4,6 +4,7 @@ import { computed, ref } from 'vue' import { useBillingContext } from '@/composables/billing/useBillingContext' import { t } from '@/i18n' +import { useTelemetry } from '@/platform/telemetry' import { useToastStore } from '@/platform/updates/common/toastStore' import { workspaceApi } from '@/platform/workspace/api/workspaceApi' import { useSettingsDialog } from '@/platform/settings/composables/useSettingsDialog' @@ -133,6 +134,10 @@ export const useBillingOperationStore = defineStore('billingOperation', () => { updateOperationStatus(opId, 'succeeded', null) cleanup(opId) + if (operation.type === 'subscription') { + useTelemetry()?.trackMonthlySubscriptionSucceeded() + } + const billingContext = useBillingContext() await Promise.all([ billingContext.fetchStatus(),