207 lines
5.7 KiB
TypeScript
207 lines
5.7 KiB
TypeScript
/**
|
|
* Cart Analytics - Shopping cart event tracking
|
|
*
|
|
* Track cart additions, removals, updates, and abandonment.
|
|
*/
|
|
|
|
import type { AnalyticsClient } from '@analytics/client';
|
|
|
|
import type { Product } from './product-analytics';
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
// Types
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
export interface CartItem extends Product {
|
|
quantity: number;
|
|
}
|
|
|
|
export interface Cart {
|
|
items: CartItem[];
|
|
subtotal: number;
|
|
currency: string;
|
|
}
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
// Cart Tracking Functions
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
/**
|
|
* Track when a product is added to cart.
|
|
*/
|
|
export function trackCartAdd(
|
|
client: AnalyticsClient,
|
|
product: Product,
|
|
quantity: number,
|
|
cart: Cart,
|
|
): void {
|
|
client.trackEngagement({
|
|
type: 'ecommerce',
|
|
action: 'cart_add',
|
|
metadata: {
|
|
productId: product.id,
|
|
productName: product.name,
|
|
price: product.price,
|
|
quantity,
|
|
itemTotal: product.price * quantity,
|
|
currency: cart.currency,
|
|
// Cart state after addition
|
|
cartItemCount: cart.items.length,
|
|
cartSubtotal: cart.subtotal,
|
|
},
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Track when a product is removed from cart.
|
|
*/
|
|
export function trackCartRemove(
|
|
client: AnalyticsClient,
|
|
product: Product,
|
|
quantity: number,
|
|
cart: Cart,
|
|
): void {
|
|
client.trackEngagement({
|
|
type: 'ecommerce',
|
|
action: 'cart_remove',
|
|
metadata: {
|
|
productId: product.id,
|
|
productName: product.name,
|
|
price: product.price,
|
|
quantity,
|
|
currency: cart.currency,
|
|
// Cart state after removal
|
|
cartItemCount: cart.items.length,
|
|
cartSubtotal: cart.subtotal,
|
|
},
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Track when cart item quantity is updated.
|
|
*/
|
|
export function trackCartUpdate(
|
|
client: AnalyticsClient,
|
|
product: Product,
|
|
previousQuantity: number,
|
|
newQuantity: number,
|
|
cart: Cart,
|
|
): void {
|
|
const quantityDelta = newQuantity - previousQuantity;
|
|
|
|
client.trackEngagement({
|
|
type: 'ecommerce',
|
|
action: 'cart_update',
|
|
metadata: {
|
|
productId: product.id,
|
|
productName: product.name,
|
|
previousQuantity,
|
|
newQuantity,
|
|
quantityDelta,
|
|
direction: quantityDelta > 0 ? 'increase' : 'decrease',
|
|
cartItemCount: cart.items.length,
|
|
cartSubtotal: cart.subtotal,
|
|
},
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Track when user views their cart.
|
|
*/
|
|
export function trackCartView(client: AnalyticsClient, cart: Cart): void {
|
|
client.trackEngagement({
|
|
type: 'ecommerce',
|
|
action: 'cart_view',
|
|
metadata: {
|
|
itemCount: cart.items.length,
|
|
subtotal: cart.subtotal,
|
|
currency: cart.currency,
|
|
products: cart.items.map((item) => ({
|
|
productId: item.id,
|
|
productName: item.name,
|
|
quantity: item.quantity,
|
|
price: item.price,
|
|
})),
|
|
},
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Track when checkout is initiated from cart.
|
|
*/
|
|
export function trackCheckoutStart(client: AnalyticsClient, cart: Cart): void {
|
|
client.trackEngagement({
|
|
type: 'ecommerce',
|
|
action: 'checkout_start',
|
|
metadata: {
|
|
itemCount: cart.items.length,
|
|
subtotal: cart.subtotal,
|
|
currency: cart.currency,
|
|
products: cart.items.map((item) => ({
|
|
productId: item.id,
|
|
quantity: item.quantity,
|
|
price: item.price,
|
|
})),
|
|
// This is a key conversion event
|
|
isConversion: true,
|
|
funnelStep: 'checkout_initiated',
|
|
},
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Track cart abandonment.
|
|
*
|
|
* Call this when:
|
|
* - User navigates away from cart without checking out
|
|
* - User closes browser with items in cart (via beforeunload)
|
|
* - Cart times out (server-side)
|
|
*/
|
|
export function trackCartAbandonment(
|
|
client: AnalyticsClient,
|
|
cart: Cart,
|
|
reason?: 'navigation' | 'timeout' | 'browser_close',
|
|
): void {
|
|
client.trackEngagement({
|
|
type: 'ecommerce',
|
|
action: 'cart_abandonment',
|
|
metadata: {
|
|
itemCount: cart.items.length,
|
|
abandonedValue: cart.subtotal,
|
|
currency: cart.currency,
|
|
reason,
|
|
products: cart.items.map((item) => ({
|
|
productId: item.id,
|
|
productName: item.name,
|
|
quantity: item.quantity,
|
|
price: item.price,
|
|
})),
|
|
},
|
|
});
|
|
}
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
// Promo Code Tracking
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
/**
|
|
* Track promo code application.
|
|
*/
|
|
export function trackPromoCodeApply(
|
|
client: AnalyticsClient,
|
|
code: string,
|
|
success: boolean,
|
|
discount?: number,
|
|
errorMessage?: string,
|
|
): void {
|
|
client.trackEngagement({
|
|
type: 'ecommerce',
|
|
action: 'promo_code_apply',
|
|
metadata: {
|
|
code,
|
|
success,
|
|
discount,
|
|
errorMessage,
|
|
},
|
|
});
|
|
}
|