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

QM : Report one-time-checkout value from checkouts #6448

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
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
88 changes: 83 additions & 5 deletions support-frontend/assets/helpers/tracking/quantumMetric.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { Participations } from 'helpers/abTests/abtest';
import type { ContributionType } from 'helpers/contributions';
import type { PaymentMethod } from 'helpers/forms/paymentMethods';
import type { IsoCurrency } from 'helpers/internationalisation/currency';
import type { ProductKey } from 'helpers/productCatalog';
import type { BillingPeriod } from 'helpers/productPrice/billingPeriods';
import type { ProductPrice } from 'helpers/productPrice/productPrices';
import type { SubscriptionProduct } from 'helpers/productPrice/subscriptions';
Expand All @@ -12,6 +13,8 @@ import type { ReferrerAcquisitionData } from './acquisitions';
import {
canRunQuantumMetric,
getContributionAnnualValue,
getConvertedAnnualValue,
getConvertedValue,
getSubscriptionAnnualValue,
waitForQuantumMetricAPi,
} from './quantumMetricHelpers';
Expand All @@ -22,6 +25,8 @@ type SendEventTestParticipationId = 30;

type SendEventPageViewId = 181;

type SendEventCheckoutValueId = 182;

enum SendEventAcquisitionDataFromQueryParam {
Source = 94,
ComponentId = 95,
Expand Down Expand Up @@ -70,7 +75,8 @@ type SendEventId =
| SendEventContributionCheckoutConversion
| SendEventContributionPaymentMethodUpdate
| SendEventAcquisitionDataFromQueryParam
| SendEventPageViewId;
| SendEventPageViewId
| SendEventCheckoutValueId;

// ---- sendEvent logic ---- //

Expand Down Expand Up @@ -107,6 +113,7 @@ function sendEvent(
id: SendEventId,
isConversion: boolean,
value: string,
payload?: Record<string, unknown>,
): void {
/**
* A cart value event is indicated by 64 in QM.
Expand All @@ -119,7 +126,12 @@ function sendEvent(
? 64
: 0;
if (window.QuantumMetricAPI?.isOn()) {
window.QuantumMetricAPI.sendEvent(id, qmCartValueEventId, value);
console.log('*** sendEvent ***', id, qmCartValueEventId, value, payload);
if (payload) {
window.QuantumMetricAPI.sendEvent(id, qmCartValueEventId, value, payload);
} else {
window.QuantumMetricAPI.sendEvent(id, qmCartValueEventId, value);
}
}
}

Expand Down Expand Up @@ -287,6 +299,72 @@ function sendEventSubscriptionCheckoutConversion(
}
}

function sendEventOneTimeCheckoutValue(
amount: number,
sourceCurrency: IsoCurrency,
): void {
console.log('*** sendEventOneTimeCheckoutValue ***', amount, sourceCurrency);
void ifQmPermitted(() => {
const sendEventWhenReady = () => {
const sendEventId = 182;
const convertedValue = getConvertedValue(amount, sourceCurrency);

const payload = {
product: 'ONE-OFF',
};

if (convertedValue) {
sendEvent(
sendEventId,
false,
Math.round(convertedValue).toString(),
payload,
);
}
};
sendEventWhenReadyTrigger(sendEventWhenReady);
});
}

function sendEventCheckoutValue(
amount: number,
product: ProductKey,
billingPeriod: BillingPeriod,
sourceCurrency: IsoCurrency,
): void {
console.log(
'*** sendEventCheckoutValue ***',
amount,
product,
billingPeriod,
sourceCurrency,
);
void ifQmPermitted(() => {
const sendEventWhenReady = () => {
const sendEventId = 182;
const convertedValue = getConvertedAnnualValue(
billingPeriod,
amount,
sourceCurrency,
);
const payload = {
product,
billingPeriod,
};
if (convertedValue) {
sendEvent(
sendEventId,
false,
Math.round(convertedValue).toString(),
payload,
);
}
};
sendEventWhenReadyTrigger(sendEventWhenReady);
});
}

// TODO: To be deleted with the 2-step checkout
function sendEventContributionCheckoutConversion(
amount: number,
contributionType: ContributionType,
Expand All @@ -307,11 +385,11 @@ function sendEventContributionCheckoutConversion(
sendEvent(sendEventId, true, Math.round(convertedValue).toString());
}
};

sendEventWhenReadyTrigger(sendEventWhenReady);
});
}

// TODO: To be deleted with the 2-step checkout
function sendEventContributionCartValue(
amount: string,
contributionType: ContributionType,
Expand All @@ -320,7 +398,6 @@ function sendEventContributionCartValue(
if (amount === 'other' || Number.isNaN(parseInt(amount))) {
return;
}

void ifQmPermitted(() => {
const sendEventWhenReady = () => {
const sendEventId =
Expand All @@ -336,7 +413,6 @@ function sendEventContributionCartValue(
sendEvent(sendEventId, false, Math.round(convertedValue).toString());
}
};

sendEventWhenReadyTrigger(sendEventWhenReady);
});
}
Expand Down Expand Up @@ -456,4 +532,6 @@ export {
sendEventPaymentMethodSelected,
sendEventConversionPaymentMethod,
sendEventAcquisitionDataFromQueryParamEvent,
sendEventCheckoutValue,
sendEventOneTimeCheckoutValue,
};
34 changes: 34 additions & 0 deletions support-frontend/assets/helpers/tracking/quantumMetricHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,40 @@ export function getSubscriptionAnnualValue(
return discountedAnnualPrice;
}

export function getConvertedAnnualValue(
billingPeriod: BillingPeriod,
amount: number,
sourceCurrency: IsoCurrency,
): number | undefined {
const billingMultiplier = {
Annual: 1,
Monthly: 12,
Quarterly: 4,
} as const satisfies Record<BillingPeriod, number>;
const annualAmount = amount * billingMultiplier[billingPeriod];
return getConvertedValue(annualAmount, sourceCurrency);
}

export function getConvertedValue(
annualAmount: number,
sourceCurrency: IsoCurrency,
): number | undefined {
const valueInPence = annualAmount * 100;
const targetCurrency: IsoCurrency = 'GBP';
if (window.QuantumMetricAPI?.isOn()) {
const convertedValue: number =
window.QuantumMetricAPI.currencyConvertFromToValue(
valueInPence,
sourceCurrency,
targetCurrency,
);
return convertedValue;
}

return;
}

// TODO: To be deleted with the 2-step checkout
export function getContributionAnnualValue(
contributionType: ContributionType,
amount: number,
Expand Down
38 changes: 26 additions & 12 deletions support-frontend/assets/pages/[countryGroupId]/checkout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,10 @@ import {
getSupportAbTests,
} from 'helpers/tracking/acquisitions';
import { trackComponentClick } from 'helpers/tracking/behaviour';
import { sendEventPaymentMethodSelected } from 'helpers/tracking/quantumMetric';
import {
sendEventCheckoutValue,
sendEventPaymentMethodSelected,
} from 'helpers/tracking/quantumMetric';
import { isProd } from 'helpers/urls/url';
import { logException } from 'helpers/utilities/logger';
import type { GeoId } from 'pages/geoIdConfig';
Expand Down Expand Up @@ -243,6 +246,17 @@ export function Checkout({ geoId, appConfig }: Props) {
? parseInt(contributionParam, 10)
: undefined;

/**
* This is some annoying transformation we need from
* Product API => Contributions work we need to do
*/
const billingPeriod =
ratePlan.billingPeriod === 'Quarter'
? 'Quarterly'
: ratePlan.billingPeriod === 'Month'
? 'Monthly'
: 'Annual';

let promotion;
if (productKey === 'Contribution') {
/**
Expand Down Expand Up @@ -279,17 +293,6 @@ export function Checkout({ geoId, appConfig }: Props) {
? appConfig.allProductPrices[productKey]
: undefined;

/**
* This is some annoying transformation we need from
* Product API => Contributions work we need to do
*/
const billingPeriod =
ratePlan.billingPeriod === 'Quarter'
? 'Quarterly'
: ratePlan.billingPeriod === 'Month'
? 'Monthly'
: 'Annual';

const getFulfilmentOptions = (productKey: string): FulfilmentOptions => {
switch (productKey) {
case 'SupporterPlus':
Expand Down Expand Up @@ -398,6 +401,17 @@ export function Checkout({ geoId, appConfig }: Props) {
* a country that doesn't correspond to the countryGroup a product is in.
*/
const forcedCountry = urlSearchParams.get('country') ?? undefined;

/**
* Notify QM of checkout value
*/
sendEventCheckoutValue(
payment.finalAmount,
productKey,
billingPeriod,
currencyKey,
);

return (
<Elements stripe={stripePromise} options={elementsOptions}>
<CheckoutComponent
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,10 @@ import {
getReferrerAcquisitionData,
} from 'helpers/tracking/acquisitions';
import { trackComponentLoad } from 'helpers/tracking/behaviour';
import { sendEventPaymentMethodSelected } from 'helpers/tracking/quantumMetric';
import {
sendEventOneTimeCheckoutValue,
sendEventPaymentMethodSelected,
} from 'helpers/tracking/quantumMetric';
import { payPalCancelUrl, payPalReturnUrl } from 'helpers/urls/routes';
import { logException } from 'helpers/utilities/logger';
import { type GeoId, getGeoIdConfig } from 'pages/geoIdConfig';
Expand Down Expand Up @@ -275,6 +278,9 @@ function OneTimeCheckoutComponent({
// valid final amount, set amount, enable Express checkout
elements?.update({ amount: finalAmount * 100 });
setStripeExpressCheckoutEnable(true);

// Track amount selection with QM
sendEventOneTimeCheckoutValue(finalAmount, currencyKey);
} else {
// invalid final amount, disable Express checkout
setStripeExpressCheckoutEnable(false);
Expand Down
1 change: 1 addition & 0 deletions support-frontend/window.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ declare global {
id: SendEventId,
isConversion: 0 | 1 | 64,
value: string,
payload?: Record<string, unknown>,
) => void;
currencyConvertFromToValue: (
value: number,
Expand Down