analytics/examples/ecommerce/cart-analytics.ts
2026-01-29 08:20:58 -08:00

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,
},
});
}