Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
32 changes: 3 additions & 29 deletions src/app/analytics/ga.service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,6 @@ describe('Testing GA Service', () => {

vi.mocked(localStorageService.get).mockImplementation((key) => {
const store: Record<string, string> = {
subscriptionId: 'sub_12345',
paymentIntentId: '',
priceId: 'price_yearly_2tb',
currency: 'EUR',
Expand All @@ -236,7 +235,7 @@ describe('Testing GA Service', () => {
expect(event).toMatchObject({
event: 'purchase',
ecommerce: {
transaction_id: 'sub_12345',
transaction_id: 'user_uuid_123',
currency: 'EUR',
value: 95.9,
items: [
Expand All @@ -260,7 +259,6 @@ describe('Testing GA Service', () => {
vi.mocked(localStorageService.getUser).mockReturnValue({ uuid: 'user_uuid' } as any);
vi.mocked(localStorageService.get).mockImplementation((key) => {
if (key === 'paymentIntentId') return 'pi_999';
if (key === 'subscriptionId') return 'sub_888';
if (key === 'amountPaid') return '100';
if (key === 'itemOriginalPrice') return '119.88';
if (key === 'checkout_item_data')
Expand All @@ -279,34 +277,10 @@ describe('Testing GA Service', () => {
expect(event.ecommerce.transaction_id).toBe('pi_999');
});

it('should use subscription ID when payment intent is not available', () => {
vi.mocked(localStorageService.getUser).mockReturnValue({ uuid: 'user_uuid' } as any);
vi.mocked(localStorageService.get).mockImplementation((key) => {
if (key === 'paymentIntentId') return null;
if (key === 'subscriptionId') return 'sub_888';
if (key === 'amountPaid') return '100';
if (key === 'itemOriginalPrice') return '119.88';
if (key === 'checkout_item_data')
return JSON.stringify({
item_name: '2TB Year Plan',
item_category: 'Individual',
item_variant: 'year',
discount: 0,
});
return '';
});

gaService.trackPurchase();

const event = globalThis.window.dataLayer[0] as any;
expect(event.ecommerce.transaction_id).toBe('sub_888');
});

it('should fallback to user UUID when neither payment intent nor subscription ID are available', () => {
it('should fallback to user UUID when payment intent is not available', () => {
vi.mocked(localStorageService.getUser).mockReturnValue({ uuid: 'user_fallback_uuid' } as any);
vi.mocked(localStorageService.get).mockImplementation((key) => {
if (key === 'paymentIntentId') return null;
if (key === 'subscriptionId') return null;
if (key === 'amountPaid') return '100';
if (key === 'itemOriginalPrice') return '119.88';
if (key === 'checkout_item_data')
Expand Down Expand Up @@ -513,4 +487,4 @@ describe('Testing GA Service', () => {
});
});
});
});
});
5 changes: 2 additions & 3 deletions src/app/analytics/ga.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ function trackBeginCheckout(params: TrackBeginCheckoutParams): void {
}
}

function trackPurchase(): void {
function trackPurchase(): void {
try {
const userSettings = localStorageService.getUser() as UserSettings;
if (!userSettings) {
Expand All @@ -154,7 +154,6 @@ function trackBeginCheckout(params: TrackBeginCheckoutParams): void {
return;
}

const subscriptionId = localStorageService.get('subscriptionId');
const paymentIntentId = localStorageService.get('paymentIntentId');
const priceId = localStorageService.get('priceId');
const currency = localStorageService.get('currency');
Expand All @@ -173,7 +172,7 @@ function trackBeginCheckout(params: TrackBeginCheckoutParams): void {
console.error('[GA Service] Error parsing checkout_item_data:', parseError);
}

const transactionId = paymentIntentId || subscriptionId || uuid;
const transactionId = paymentIntentId || uuid;
const currencyCode = currency ?? 'EUR';

const itemName = checkoutItemData?.item_name || 'Unknown Plan';
Expand Down
55 changes: 25 additions & 30 deletions src/app/analytics/impact.service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ vi.mock('services/error.service', () => ({
},
}));

const subId = 'sub_123';
const paymentIntentId = 'py_123';
const mockedUserUuid = '00000000-0000-0000-0000-0000000000';
const mockImpactApiUrl = 'mock-impact-api-url';
Expand Down Expand Up @@ -93,7 +92,6 @@ beforeEach(() => {

vi.spyOn(localStorageService, 'get').mockImplementation((key) => {
if (key === 'paymentIntentId') return paymentIntentId;
if (key === 'subscriptionId') return subId;
if (key === 'productName') return planName;
if (key === 'priceId') return product.price.id;
if (key === 'currency') return product.price.currency;
Expand All @@ -110,7 +108,6 @@ describe('Testing Impact Service', () => {
const setToLocalStorageSpy = vi.spyOn(localStorageService, 'set');

savePaymentDataInLocalStorage({
subscriptionId: subId,
paymentIntentId,
selectedPlan: product as PriceWithTax,
users: 1,
Expand All @@ -121,32 +118,12 @@ describe('Testing Impact Service', () => {
expect(setToLocalStorageSpy).toHaveBeenCalledWith('amountPaid', expectedAmount);
});

it('should save subscription ID when plan is not lifetime', () => {
it('should save payment intent ID if provided', () => {
const setToLocalStorageSpy = vi.spyOn(localStorageService, 'set');

savePaymentDataInLocalStorage({
subscriptionId: subId,
paymentIntentId: undefined,
selectedPlan: product as PriceWithTax,
users: 1,
couponCodeData: promoCode,
isFirstPurchase: true,
});

expect(setToLocalStorageSpy).toHaveBeenCalledWith('subscriptionId', subId);
});

it('should save payment intent ID when plan is lifetime', () => {
const setToLocalStorageSpy = vi.spyOn(localStorageService, 'set');
const lifetimeProduct = {
...product,
price: { ...product.price, interval: 'lifetime' },
};

savePaymentDataInLocalStorage({
subscriptionId: undefined,
paymentIntentId,
selectedPlan: lifetimeProduct as PriceWithTax,
selectedPlan: product as PriceWithTax,
users: 1,
couponCodeData: promoCode,
isFirstPurchase: true,
Expand All @@ -159,7 +136,6 @@ describe('Testing Impact Service', () => {
const setToLocalStorageSpy = vi.spyOn(localStorageService, 'set');

savePaymentDataInLocalStorage({
subscriptionId: subId,
paymentIntentId,
selectedPlan: product as PriceWithTax,
users: 1,
Expand All @@ -176,7 +152,6 @@ describe('Testing Impact Service', () => {
const setToLocalStorageSpy = vi.spyOn(localStorageService, 'set');

savePaymentDataInLocalStorage({
subscriptionId: subId,
paymentIntentId,
selectedPlan: product as PriceWithTax,
users: 1,
Expand All @@ -191,7 +166,6 @@ describe('Testing Impact Service', () => {
const setToLocalStorageSpy = vi.spyOn(localStorageService, 'set');

savePaymentDataInLocalStorage({
subscriptionId: subId,
paymentIntentId,
selectedPlan: product as PriceWithTax,
users: 1,
Expand Down Expand Up @@ -287,7 +261,6 @@ describe('Testing Impact Service', () => {
timestamp: expect.any(String),
properties: expect.objectContaining({
impact_value: parseFloat(expectedAmount),
subscription_id: subId,
payment_intent: paymentIntentId,
order_promo_code: promoCode.codeName,
}),
Expand All @@ -301,7 +274,6 @@ describe('Testing Impact Service', () => {
it('should use minimum value of 0.01 when amount is 0 (free purchase)', async () => {
vi.spyOn(localStorageService, 'get').mockImplementation((key) => {
if (key === 'amountPaid') return '0';
if (key === 'subscriptionId') return subId;
if (key === 'couponCode') return promoCode.codeName;
if (key === 'isFirstPurchase') return 'true';
return null;
Expand Down Expand Up @@ -353,6 +325,29 @@ describe('Testing Impact Service', () => {
expect(axiosSpy).not.toHaveBeenCalled();
});

it('should send to Impact when source is direct but coupon code is present', async () => {
const getCookieMock = await import('./utils');
vi.mocked(getCookieMock.getCookie).mockImplementation((key) => {
if (key === 'impactSource') return 'direct';
if (key === 'impactAnonymousId') return '';
return '';
});
vi.spyOn(localStorageService, 'get').mockImplementation((key) => {
if (key === 'couponCode') return 'CNINTERNXT';
if (key === 'amountPaid') return expectedAmount;
if (key === 'isFirstPurchase') return 'true';
return null;
});
const axiosSpy = vi.spyOn(axios, 'post').mockResolvedValue({});

await trackPaymentConversion();

expect(axiosSpy).toHaveBeenCalledTimes(1);
const callArgs = axiosSpy.mock.calls[0][1] as { properties: Record<string, unknown>; anonymousId: string };
expect(callArgs.properties).toHaveProperty('order_promo_code', 'CNINTERNXT');
expect(callArgs.anonymousId).toBe('');
});

it('should not send to Impact when isFirstPurchase is false', async () => {
vi.spyOn(localStorageService, 'get').mockImplementation((key) => {
if (key === 'isFirstPurchase') return 'false';
Expand Down
10 changes: 1 addition & 9 deletions src/app/analytics/impact.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import { sendAddShoppersConversion } from './addShoppers.services';
*
*/
export interface SavePaymentDataParams {
subscriptionId: string | undefined;
paymentIntentId: string | undefined;
selectedPlan: PriceWithTax | undefined;
users: number;
Expand All @@ -38,18 +37,13 @@ export interface SavePaymentDataParams {
}

export function savePaymentDataInLocalStorage({
subscriptionId,
paymentIntentId,
selectedPlan,
users,
couponCodeData,
isFirstPurchase,
}: SavePaymentDataParams) {
if (subscriptionId && selectedPlan?.price.interval !== 'lifetime') {
localStorageService.set('subscriptionId', subscriptionId);
}

if (paymentIntentId && selectedPlan?.price.interval === 'lifetime') {
if (paymentIntentId) {
localStorageService.set('paymentIntentId', paymentIntentId);
}

Expand Down Expand Up @@ -107,7 +101,6 @@ export async function trackPaymentConversion(): Promise<void> {
}

const { uuid, email: userEmail } = userSettings;
const subscription = localStorageService.get('subscriptionId');
const paymentIntent = localStorageService.get('paymentIntentId');
const currency = localStorageService.get('currency');
const amountPaidStr = localStorageService.get('amountPaid');
Expand Down Expand Up @@ -138,7 +131,6 @@ export async function trackPaymentConversion(): Promise<void> {
timestamp: dayjs().format('YYYY-MM-DDTHH:mm:ss.sssZ'),
properties: {
impact_value: amount === 0 ? 0.01 : amount,
subscription_id: subscription,
payment_intent: paymentIntent,
...(couponCode && { order_promo_code: couponCode }),
},
Expand Down
2 changes: 0 additions & 2 deletions src/views/Checkout/hooks/useUserPayment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,6 @@ export const useUserPayment = () => {
});

savePaymentDataInLocalStorage({
subscriptionId: subscription.subscriptionId,
paymentIntentId: subscription.paymentIntentId,
selectedPlan: currentSelectedPlan,
users: seatsForBusinessSubscription,
Expand Down Expand Up @@ -225,7 +224,6 @@ export const useUserPayment = () => {
});

savePaymentDataInLocalStorage({
subscriptionId: undefined,
paymentIntentId,
selectedPlan: currentSelectedPlan,
users: 1,
Expand Down
1 change: 0 additions & 1 deletion src/views/Checkout/views/CheckoutSuccessView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import gaService from 'app/analytics/ga.service';
import metaService from 'app/analytics/meta.service';

export function removePaymentsStorage() {
localStorageService.removeItem('subscriptionId');
localStorageService.removeItem('paymentIntentId');
localStorageService.removeItem('amountPaid');
localStorageService.removeItem('productName');
Expand Down
Loading