analytics/examples/nestjs-backend/track-analytics.decorator.ts
2026-01-29 08:20:58 -08:00

95 lines
2.2 KiB
TypeScript

/**
* @TrackAnalytics Decorator - Method-level analytics tracking
*
* Use this decorator to track specific controller methods with custom events.
*/
import { SetMetadata } from '@nestjs/common';
export const TRACK_ANALYTICS_KEY = 'track_analytics';
export interface TrackAnalyticsOptions {
/**
* Event name (e.g., 'user_signup', 'order_placed')
*/
event: string;
/**
* Event category for grouping
*/
category?: string;
/**
* Static metadata to include with every event
*/
metadata?: Record<string, unknown>;
/**
* Extract dynamic metadata from request/response
* Return value is merged with static metadata
*/
extractMetadata?: (context: {
request: any;
response: any;
result: any;
}) => Record<string, unknown>;
}
/**
* Decorator to track analytics on a specific endpoint.
*
* @example
* ```ts
* @Post('signup')
* @TrackAnalytics({
* event: 'user_signup',
* category: 'auth',
* extractMetadata: ({ result }) => ({
* userId: result.id,
* plan: result.plan,
* }),
* })
* async signup(@Body() dto: SignupDto) {
* return this.authService.signup(dto);
* }
* ```
*/
export const TrackAnalytics = (options: TrackAnalyticsOptions) =>
SetMetadata(TRACK_ANALYTICS_KEY, options);
/**
* Example decorated controller:
*
* ```ts
* @Controller('orders')
* export class OrderController {
* @Post()
* @TrackAnalytics({
* event: 'order_placed',
* category: 'commerce',
* extractMetadata: ({ request, result }) => ({
* orderId: result.id,
* total: result.total,
* itemCount: result.items.length,
* userId: request.user?.id,
* }),
* })
* async createOrder(@Body() dto: CreateOrderDto, @Request() req) {
* return this.orderService.create(dto, req.user);
* }
*
* @Delete(':id')
* @TrackAnalytics({
* event: 'order_cancelled',
* category: 'commerce',
* extractMetadata: ({ request }) => ({
* orderId: request.params.id,
* userId: request.user?.id,
* }),
* })
* async cancelOrder(@Param('id') id: string, @Request() req) {
* return this.orderService.cancel(id, req.user);
* }
* }
* ```
*/