159 lines
4.4 KiB
TypeScript
159 lines
4.4 KiB
TypeScript
/**
|
|
* UserController - Example with analytics tracking
|
|
*
|
|
* Demonstrates various tracking patterns in a NestJS controller.
|
|
*/
|
|
|
|
import {
|
|
Controller,
|
|
Post,
|
|
Get,
|
|
Body,
|
|
Param,
|
|
Request,
|
|
Inject,
|
|
UseInterceptors,
|
|
} from '@nestjs/common';
|
|
|
|
import { BackendAnalyticsClient } from '@analytics/client';
|
|
import { ANALYTICS_CLIENT } from './analytics.module';
|
|
import { AnalyticsInterceptor } from './analytics.interceptor';
|
|
import { TrackAnalytics } from './track-analytics.decorator';
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
// DTOs
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
interface SignupDto {
|
|
email: string;
|
|
name: string;
|
|
plan?: string;
|
|
}
|
|
|
|
interface User {
|
|
id: string;
|
|
email: string;
|
|
name: string;
|
|
plan: string;
|
|
}
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
// Controller
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
@Controller('users')
|
|
@UseInterceptors(AnalyticsInterceptor) // Track all requests
|
|
export class UserController {
|
|
constructor(
|
|
@Inject(ANALYTICS_CLIENT)
|
|
private readonly analytics: BackendAnalyticsClient,
|
|
) {}
|
|
|
|
/**
|
|
* Signup endpoint with automatic tracking via decorator.
|
|
*/
|
|
@Post('signup')
|
|
@TrackAnalytics({
|
|
event: 'user_signup',
|
|
category: 'auth',
|
|
extractMetadata: ({ result }) => ({
|
|
userId: result.id,
|
|
plan: result.plan,
|
|
emailDomain: result.email.split('@')[1],
|
|
}),
|
|
})
|
|
async signup(@Body() dto: SignupDto): Promise<User> {
|
|
// Your signup logic here
|
|
const user: User = {
|
|
id: `usr_${Date.now()}`,
|
|
email: dto.email,
|
|
name: dto.name,
|
|
plan: dto.plan || 'free',
|
|
};
|
|
|
|
return user;
|
|
}
|
|
|
|
/**
|
|
* Profile view with manual tracking.
|
|
*
|
|
* Use manual tracking when you need more control.
|
|
*/
|
|
@Get(':id')
|
|
async getProfile(@Param('id') id: string, @Request() req: any): Promise<User | null> {
|
|
// Your fetch logic here
|
|
const user: User = {
|
|
id,
|
|
email: 'user@example.com',
|
|
name: 'Example User',
|
|
plan: 'pro',
|
|
};
|
|
|
|
// Manual tracking with full context
|
|
this.analytics.trackEngagement({
|
|
sessionId: req.headers['x-session-id'] || 'unknown',
|
|
userId: req.user?.id, // Viewer's ID
|
|
type: 'profile_view',
|
|
action: 'view',
|
|
metadata: {
|
|
viewedProfileId: id,
|
|
viewedUserPlan: user.plan,
|
|
viewerIsAuthenticated: Boolean(req.user),
|
|
},
|
|
});
|
|
|
|
return user;
|
|
}
|
|
|
|
/**
|
|
* Upgrade plan with funnel tracking.
|
|
*/
|
|
@Post(':id/upgrade')
|
|
async upgradePlan(
|
|
@Param('id') id: string,
|
|
@Body() body: { plan: string },
|
|
@Request() req: any,
|
|
): Promise<{ success: boolean }> {
|
|
const sessionId = req.headers['x-session-id'] || 'unknown';
|
|
|
|
// Track upgrade funnel step
|
|
this.analytics.trackEngagement({
|
|
sessionId,
|
|
userId: id,
|
|
type: 'funnel_step',
|
|
action: 'plan_upgrade',
|
|
metadata: {
|
|
funnelId: 'upgrade',
|
|
step: 'upgrade_completed',
|
|
fromPlan: 'free', // You'd fetch this from DB
|
|
toPlan: body.plan,
|
|
},
|
|
});
|
|
|
|
return { success: true };
|
|
}
|
|
|
|
/**
|
|
* Account deletion with GDPR tracking.
|
|
*/
|
|
@Post(':id/delete')
|
|
async deleteAccount(@Param('id') id: string, @Request() req: any): Promise<{ deleted: boolean }> {
|
|
const sessionId = req.headers['x-session-id'] || 'unknown';
|
|
|
|
// Track before deletion (important for compliance)
|
|
this.analytics.trackEngagement({
|
|
sessionId,
|
|
userId: id,
|
|
type: 'account_action',
|
|
action: 'deletion_requested',
|
|
metadata: {
|
|
requestedBy: req.user?.id === id ? 'self' : 'admin',
|
|
gdprRequest: true,
|
|
},
|
|
});
|
|
|
|
// Your deletion logic here
|
|
|
|
return { deleted: true };
|
|
}
|
|
}
|