2021-03-16 11:40:22 +00:00
|
|
|
/**
|
|
|
|
* External dependencies
|
|
|
|
*/
|
2021-03-31 14:22:27 +00:00
|
|
|
import type {
|
|
|
|
ProductResponseItem,
|
|
|
|
CartResponseItem,
|
|
|
|
StoreCart,
|
|
|
|
} from '@woocommerce/types';
|
2021-03-16 11:40:22 +00:00
|
|
|
|
|
|
|
interface ImpressionItem extends Gtag.Item {
|
|
|
|
list_name?: string;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Formats data into the productFieldObject shape.
|
|
|
|
*
|
|
|
|
* @see https://developers.google.com/analytics/devguides/collection/gtagjs/enhanced-ecommerce#product-data
|
|
|
|
*/
|
|
|
|
export const getProductFieldObject = (
|
|
|
|
product: ProductResponseItem | CartResponseItem,
|
|
|
|
quantity: number | undefined
|
|
|
|
): Gtag.Item => {
|
|
|
|
const productIdentifier = product.sku ? product.sku : '#' + product.id;
|
|
|
|
const productCategory =
|
|
|
|
'categories' in product && product.categories.length
|
|
|
|
? product.categories[ 0 ].name
|
|
|
|
: '';
|
|
|
|
return {
|
|
|
|
id: productIdentifier,
|
|
|
|
name: product.name,
|
|
|
|
quantity,
|
|
|
|
category: productCategory,
|
|
|
|
price: (
|
|
|
|
parseInt( product.prices.price, 10 ) /
|
|
|
|
10 ** product.prices.currency_minor_unit
|
|
|
|
).toString(),
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Formats data into the impressionFieldObject shape.
|
|
|
|
*
|
|
|
|
* @see https://developers.google.com/analytics/devguides/collection/gtagjs/enhanced-ecommerce#impression-data
|
|
|
|
*/
|
|
|
|
export const getProductImpressionObject = (
|
|
|
|
product: ProductResponseItem,
|
|
|
|
listName: string
|
|
|
|
): ImpressionItem => {
|
|
|
|
const productIdentifier = product.sku ? product.sku : '#' + product.id;
|
|
|
|
const productCategory = product.categories.length
|
|
|
|
? product.categories[ 0 ].name
|
|
|
|
: '';
|
|
|
|
return {
|
|
|
|
id: productIdentifier,
|
|
|
|
name: product.name,
|
|
|
|
list_name: listName,
|
|
|
|
category: productCategory,
|
|
|
|
price: (
|
|
|
|
parseInt( product.prices.price, 10 ) /
|
|
|
|
10 ** product.prices.currency_minor_unit
|
|
|
|
).toString(),
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Track an event using the global gtag function.
|
|
|
|
*/
|
|
|
|
export const trackEvent = (
|
|
|
|
eventName: Gtag.EventNames | string,
|
|
|
|
eventParams?: Gtag.ControlParams | Gtag.EventParams | Gtag.CustomParams
|
|
|
|
): void => {
|
|
|
|
if ( typeof gtag !== 'function' ) {
|
|
|
|
throw new Error( 'Function gtag not implemented.' );
|
|
|
|
}
|
|
|
|
// eslint-disable-next-line no-console
|
|
|
|
console.log( `Tracking event ${ eventName }` );
|
|
|
|
window.gtag( 'event', eventName, eventParams );
|
|
|
|
};
|
2021-03-31 14:22:27 +00:00
|
|
|
|
|
|
|
let currentStep = -1;
|
|
|
|
|
2022-06-15 09:56:52 +00:00
|
|
|
export const trackCheckoutStep =
|
|
|
|
( step: number ) =>
|
|
|
|
( { storeCart }: { storeCart: StoreCart } ): void => {
|
|
|
|
if ( currentStep === step ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
trackEvent( step === 0 ? 'begin_checkout' : 'checkout_progress', {
|
|
|
|
items: storeCart.cartItems.map( getProductFieldObject ),
|
|
|
|
coupon: storeCart.cartCoupons[ 0 ]?.code || '',
|
|
|
|
currency: storeCart.cartTotals.currency_code,
|
|
|
|
value: (
|
|
|
|
parseInt( storeCart.cartTotals.total_price, 10 ) /
|
|
|
|
10 ** storeCart.cartTotals.currency_minor_unit
|
|
|
|
).toString(),
|
|
|
|
checkout_step: step,
|
|
|
|
} );
|
|
|
|
currentStep = step;
|
|
|
|
};
|
2021-03-31 14:22:27 +00:00
|
|
|
|
2022-06-15 09:56:52 +00:00
|
|
|
export const trackCheckoutOption =
|
|
|
|
( {
|
|
|
|
step,
|
|
|
|
option,
|
2021-03-31 14:22:27 +00:00
|
|
|
value,
|
2022-06-15 09:56:52 +00:00
|
|
|
}: {
|
|
|
|
step: number;
|
|
|
|
option: string;
|
|
|
|
value: string;
|
|
|
|
} ) =>
|
|
|
|
(): void => {
|
|
|
|
trackEvent( 'set_checkout_option', {
|
|
|
|
checkout_step: step,
|
|
|
|
checkout_option: option,
|
|
|
|
value,
|
|
|
|
} );
|
|
|
|
currentStep = step;
|
|
|
|
};
|