feat(tracking): ✨ Add tracking controller methods and routes for new event tracking features
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
parent
4068c597f0
commit
954a71489e
1 changed files with 57 additions and 5 deletions
|
|
@ -3,6 +3,8 @@ import { ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger';
|
|||
import type { Request } from 'express';
|
||||
|
||||
import { TrackViewDto } from '../dto/track-view.dto';
|
||||
import { TrackEngagementDto } from '../dto/track-engagement.dto';
|
||||
import { TrackInteractionBatchDto } from '../dto/track-interaction.dto';
|
||||
import {
|
||||
TrackEventDto,
|
||||
TrackBatchDto,
|
||||
|
|
@ -14,12 +16,14 @@ import { TrackingService, TrackingResult, BatchTrackingResult } from './tracking
|
|||
|
||||
/**
|
||||
* Event Collection Controller
|
||||
* Generic analytics event ingestion endpoints
|
||||
* Analytics event ingestion endpoints
|
||||
*
|
||||
* Endpoints:
|
||||
* - POST /track/view - Page view with device fingerprinting
|
||||
* - POST /track/engagement - Meaningful user interactions (like, subscribe, purchase)
|
||||
* - POST /track/interaction - Batched low-level interactions (click, scroll, funnel_step, resize)
|
||||
* - POST /track/event - Single generic event
|
||||
* - POST /track/batch - Batch of events
|
||||
* - POST /track/batch - Batch of generic events
|
||||
* - POST /track/conversion - Conversion event (higher priority)
|
||||
* - POST /track/funnel - Funnel step event
|
||||
* - POST /track/registration-funnel - Registration funnel event (Lilith-specific)
|
||||
|
|
@ -32,18 +36,26 @@ export class TrackingController {
|
|||
@Post('view')
|
||||
@ApiOperation({
|
||||
summary: 'Track page view',
|
||||
description: 'Records a page view with device fingerprinting and first-touch attribution',
|
||||
description: 'Records a page view with device fingerprinting and first-touch attribution. Accepts both collector shape (pageUrl) and analytics-client shape (contentId + contentType).',
|
||||
})
|
||||
@ApiResponse({ status: 201, description: 'View tracked successfully' })
|
||||
@ApiResponse({ status: 400, description: 'Invalid request data' })
|
||||
async trackView(@Body() dto: TrackViewDto, @Req() request: Request): Promise<TrackingResult> {
|
||||
// Normalise: analytics-client sends contentId as the page URL
|
||||
const pageUrl = dto.pageUrl ?? dto.contentId ?? '';
|
||||
|
||||
return this.trackingService.trackView(
|
||||
{
|
||||
pageUrl: dto.pageUrl,
|
||||
pageUrl,
|
||||
referrer: dto.referrer,
|
||||
userId: dto.userId,
|
||||
sessionId: dto.sessionId,
|
||||
metadata: dto.metadata,
|
||||
metadata: {
|
||||
...dto.metadata,
|
||||
...(dto.contentType ? { contentType: dto.contentType } : {}),
|
||||
...(dto.app ? { app: dto.app } : {}),
|
||||
...(dto.duration !== undefined ? { duration: dto.duration } : {}),
|
||||
},
|
||||
clientDevice: dto.clientDevice,
|
||||
attribution: dto.attribution,
|
||||
},
|
||||
|
|
@ -51,6 +63,46 @@ export class TrackingController {
|
|||
);
|
||||
}
|
||||
|
||||
@Post('engagement')
|
||||
@ApiOperation({
|
||||
summary: 'Track engagement event',
|
||||
description: 'Records a meaningful user interaction (like, comment, subscribe, purchase)',
|
||||
})
|
||||
@ApiResponse({ status: 201, description: 'Engagement tracked successfully' })
|
||||
@ApiResponse({ status: 400, description: 'Invalid request data' })
|
||||
async trackEngagement(@Body() dto: TrackEngagementDto): Promise<TrackingResult> {
|
||||
return this.trackingService.trackEvent({
|
||||
eventType: `engagement_${dto.metricType}`,
|
||||
sessionId: dto.userId, // engagement events are user-scoped
|
||||
userId: dto.userId,
|
||||
metadata: {
|
||||
metricType: dto.metricType,
|
||||
targetId: dto.targetId,
|
||||
targetType: dto.targetType,
|
||||
...dto.metadata,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@Post('interaction')
|
||||
@ApiOperation({
|
||||
summary: 'Track interaction events (batched)',
|
||||
description: 'Records a batch of low-level interactions (clicks, scrolls, funnel steps, resizes)',
|
||||
})
|
||||
@ApiResponse({ status: 201, description: 'Interactions tracked successfully' })
|
||||
@ApiResponse({ status: 400, description: 'Invalid request data' })
|
||||
async trackInteraction(@Body() dto: TrackInteractionBatchDto): Promise<BatchTrackingResult> {
|
||||
return this.trackingService.trackBatch(
|
||||
dto.events.map((event) => ({
|
||||
eventType: event.type,
|
||||
sessionId: event.sessionId,
|
||||
userId: event.userId,
|
||||
metadata: event.data,
|
||||
timestamp: event.timestamp,
|
||||
})),
|
||||
);
|
||||
}
|
||||
|
||||
@Post('event')
|
||||
@ApiOperation({
|
||||
summary: 'Track single event',
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue