220 lines
5.6 KiB
TypeScript
220 lines
5.6 KiB
TypeScript
|
|
/**
|
||
|
|
* Product Analytics - Track product interactions
|
||
|
|
*
|
||
|
|
* Provides functions for tracking product views, impressions,
|
||
|
|
* and user interactions with products.
|
||
|
|
*/
|
||
|
|
|
||
|
|
import type { AnalyticsClient } from '@analytics/client';
|
||
|
|
|
||
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
||
|
|
// Types
|
||
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
||
|
|
|
||
|
|
export interface Product {
|
||
|
|
id: string;
|
||
|
|
name: string;
|
||
|
|
price: number;
|
||
|
|
currency?: string;
|
||
|
|
category?: string;
|
||
|
|
brand?: string;
|
||
|
|
variant?: string;
|
||
|
|
sku?: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface ProductImpression extends Product {
|
||
|
|
listName: string;
|
||
|
|
position: number;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
||
|
|
// Product Tracking Functions
|
||
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Track when a user views a product detail page.
|
||
|
|
*/
|
||
|
|
export function trackProductView(client: AnalyticsClient, product: Product): void {
|
||
|
|
client.trackEngagement({
|
||
|
|
type: 'ecommerce',
|
||
|
|
action: 'product_view',
|
||
|
|
metadata: {
|
||
|
|
productId: product.id,
|
||
|
|
productName: product.name,
|
||
|
|
price: product.price,
|
||
|
|
currency: product.currency || 'USD',
|
||
|
|
category: product.category,
|
||
|
|
brand: product.brand,
|
||
|
|
variant: product.variant,
|
||
|
|
sku: product.sku,
|
||
|
|
},
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Track product impressions in a list (search results, category page, etc.)
|
||
|
|
*/
|
||
|
|
export function trackProductImpressions(
|
||
|
|
client: AnalyticsClient,
|
||
|
|
impressions: ProductImpression[],
|
||
|
|
): void {
|
||
|
|
// Track as a batch event
|
||
|
|
client.trackEngagement({
|
||
|
|
type: 'ecommerce',
|
||
|
|
action: 'product_impressions',
|
||
|
|
metadata: {
|
||
|
|
impressionCount: impressions.length,
|
||
|
|
listName: impressions[0]?.listName,
|
||
|
|
products: impressions.map((p) => ({
|
||
|
|
productId: p.id,
|
||
|
|
productName: p.name,
|
||
|
|
price: p.price,
|
||
|
|
position: p.position,
|
||
|
|
category: p.category,
|
||
|
|
})),
|
||
|
|
},
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Track when a user clicks on a product from a list.
|
||
|
|
*/
|
||
|
|
export function trackProductClick(
|
||
|
|
client: AnalyticsClient,
|
||
|
|
product: Product,
|
||
|
|
listName: string,
|
||
|
|
position: number,
|
||
|
|
): void {
|
||
|
|
client.trackEngagement({
|
||
|
|
type: 'ecommerce',
|
||
|
|
action: 'product_click',
|
||
|
|
metadata: {
|
||
|
|
productId: product.id,
|
||
|
|
productName: product.name,
|
||
|
|
price: product.price,
|
||
|
|
listName,
|
||
|
|
position,
|
||
|
|
category: product.category,
|
||
|
|
},
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Track when a user adds a product to their wishlist.
|
||
|
|
*/
|
||
|
|
export function trackWishlistAdd(client: AnalyticsClient, product: Product): void {
|
||
|
|
client.trackEngagement({
|
||
|
|
type: 'ecommerce',
|
||
|
|
action: 'wishlist_add',
|
||
|
|
metadata: {
|
||
|
|
productId: product.id,
|
||
|
|
productName: product.name,
|
||
|
|
price: product.price,
|
||
|
|
category: product.category,
|
||
|
|
},
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Track when a user shares a product.
|
||
|
|
*/
|
||
|
|
export function trackProductShare(
|
||
|
|
client: AnalyticsClient,
|
||
|
|
product: Product,
|
||
|
|
method: 'email' | 'twitter' | 'facebook' | 'link' | string,
|
||
|
|
): void {
|
||
|
|
client.trackEngagement({
|
||
|
|
type: 'ecommerce',
|
||
|
|
action: 'product_share',
|
||
|
|
metadata: {
|
||
|
|
productId: product.id,
|
||
|
|
productName: product.name,
|
||
|
|
shareMethod: method,
|
||
|
|
},
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Track product review submission.
|
||
|
|
*/
|
||
|
|
export function trackReviewSubmit(
|
||
|
|
client: AnalyticsClient,
|
||
|
|
product: Product,
|
||
|
|
rating: number,
|
||
|
|
hasText: boolean,
|
||
|
|
): void {
|
||
|
|
client.trackEngagement({
|
||
|
|
type: 'ecommerce',
|
||
|
|
action: 'review_submit',
|
||
|
|
metadata: {
|
||
|
|
productId: product.id,
|
||
|
|
productName: product.name,
|
||
|
|
rating,
|
||
|
|
hasText,
|
||
|
|
},
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
||
|
|
// Search Tracking
|
||
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Track product search queries.
|
||
|
|
*/
|
||
|
|
export function trackSearch(
|
||
|
|
client: AnalyticsClient,
|
||
|
|
query: string,
|
||
|
|
resultCount: number,
|
||
|
|
filters?: Record<string, unknown>,
|
||
|
|
): void {
|
||
|
|
client.trackEngagement({
|
||
|
|
type: 'ecommerce',
|
||
|
|
action: 'search',
|
||
|
|
metadata: {
|
||
|
|
query,
|
||
|
|
resultCount,
|
||
|
|
filters,
|
||
|
|
hasResults: resultCount > 0,
|
||
|
|
},
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Track when user applies filters on a product list.
|
||
|
|
*/
|
||
|
|
export function trackFilterApply(
|
||
|
|
client: AnalyticsClient,
|
||
|
|
filterType: string,
|
||
|
|
filterValue: string | string[],
|
||
|
|
resultCount: number,
|
||
|
|
): void {
|
||
|
|
client.trackEngagement({
|
||
|
|
type: 'ecommerce',
|
||
|
|
action: 'filter_apply',
|
||
|
|
metadata: {
|
||
|
|
filterType,
|
||
|
|
filterValue,
|
||
|
|
resultCount,
|
||
|
|
},
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Track sort order changes.
|
||
|
|
*/
|
||
|
|
export function trackSortChange(
|
||
|
|
client: AnalyticsClient,
|
||
|
|
sortBy: string,
|
||
|
|
sortOrder: 'asc' | 'desc',
|
||
|
|
): void {
|
||
|
|
client.trackEngagement({
|
||
|
|
type: 'ecommerce',
|
||
|
|
action: 'sort_change',
|
||
|
|
metadata: {
|
||
|
|
sortBy,
|
||
|
|
sortOrder,
|
||
|
|
},
|
||
|
|
});
|
||
|
|
}
|