Analytics Controller
Path: internal/api/v1/funnels/controllers/analytics.controller.js
Service: analyticsService
Module: Funnels
Overview
The Analytics controller tracks and reports conversion metrics for funnels. It records visitor actions, form submissions, payment events, and provides aggregated analytics data for funnel performance analysis.
Key Capabilities
- Funnel Analytics: Aggregate metrics for entire funnels
- Step Analytics: Granular metrics per funnel step
- Event Tracking: Record visitor actions, forms, payments
- Conversion Tracking: Monitor funnel conversion rates
- UTM Attribution: Track traffic sources and campaigns
- Payment Analytics: Stripe/Square payment tracking
Methods
getAnalytics()
Retrieves aggregated analytics data for a funnel with date filtering and pagination.
Route: GET /v1/funnels/analytics
Auth: Required (account-scoped)
Request Query Parameters
{
funnel_id: string; // Funnel ID to get analytics for
start_date?: string; // Filter from date (ISO 8601)
end_date?: string; // Filter to date (ISO 8601)
limit?: number; // Results per page (default: 10)
page?: number; // Page number (0-indexed)
}
Response
{
"success": true,
"message": "SUCCESS",
"data": {
"funnel_id": "60d5ec49f1b2c72e8c8e4b1a",
"date_range": {
"start": "2024-01-01T00:00:00Z",
"end": "2024-01-31T23:59:59Z"
},
"summary": {
"total_visitors": 1250,
"unique_visitors": 980,
"total_page_views": 3840,
"total_conversions": 142,
"conversion_rate": 14.49,
"total_revenue": 28450.5,
"average_order_value": 200.36
},
"steps": [
{
"step_id": "60d5ec49f1b2c72e8c8e4b1d",
"step_name": "Landing Page",
"visitors": 1250,
"unique_visitors": 980,
"page_views": 1420,
"bounce_rate": 23.5,
"avg_time_on_page": 125.8,
"exit_rate": 18.2
},
{
"step_id": "60d5ec49f1b2c72e8c8e4b1e",
"step_name": "Checkout",
"visitors": 340,
"unique_visitors": 310,
"page_views": 485,
"bounce_rate": 12.3,
"avg_time_on_page": 215.4,
"exit_rate": 45.8
}
],
"traffic_sources": [
{
"source": "google",
"medium": "cpc",
"visitors": 620,
"conversions": 89,
"conversion_rate": 14.35
},
{
"source": "facebook",
"medium": "social",
"visitors": 380,
"conversions": 42,
"conversion_rate": 11.05
}
],
"daily_metrics": [
{
"date": "2024-01-15",
"visitors": 42,
"unique_visitors": 38,
"conversions": 6,
"revenue": 1205.5
},
{
"date": "2024-01-16",
"visitors": 55,
"unique_visitors": 48,
"conversions": 8,
"revenue": 1680.0
}
],
"form_submissions": {
"total": 234,
"conversion_rate": 23.88
},
"payments": {
"total_transactions": 142,
"successful": 138,
"failed": 4,
"success_rate": 97.18
}
}
}
MongoDB Collections
| Collection | Operation | Purpose |
|---|---|---|
funnel_analytics | aggregate | Generate aggregated metrics |
funnel_visitors | distinct | Count unique visitors |
funnel_page_views | count | Count page views |
form_submissions | count | Count form submissions |
payment_transactions | aggregate | Calculate revenue metrics |
Query Parameters
- start_date: Defaults to 30 days ago if not provided
- end_date: Defaults to current date if not provided
- limit: Controls pagination for daily metrics
- page: 0-indexed page number for daily metrics
getAnalytic()
Retrieves detailed analytics for a specific funnel step.
Route: GET /v1/funnels/:funnel_id/analytics/:step_id
Auth: Required (account-scoped)
Request Parameters
{
funnel_id: string; // Funnel ID
step_id: string; // Step ID
}
Response
{
"success": true,
"message": "SUCCESS",
"data": {
"funnel_id": "60d5ec49f1b2c72e8c8e4b1a",
"step_id": "60d5ec49f1b2c72e8c8e4b1d",
"step_name": "Landing Page",
"metrics": {
"total_visitors": 1250,
"unique_visitors": 980,
"total_page_views": 1420,
"avg_page_views_per_visitor": 1.14,
"bounce_rate": 23.5,
"exit_rate": 18.2,
"avg_time_on_page": 125.8,
"conversions": 142,
"conversion_rate": 14.49
},
"visitor_flow": {
"entries": 1250,
"next_steps": [
{
"step_id": "60d5ec49f1b2c72e8c8e4b1e",
"step_name": "Checkout",
"visitors": 340,
"percentage": 27.2
}
],
"exits": 228,
"exit_percentage": 18.2
},
"devices": [
{
"type": "desktop",
"visitors": 675,
"percentage": 54.0
},
{
"type": "mobile",
"visitors": 525,
"percentage": 42.0
},
{
"type": "tablet",
"visitors": 50,
"percentage": 4.0
}
],
"browsers": [
{
"name": "Chrome",
"visitors": 825,
"percentage": 66.0
},
{
"name": "Safari",
"visitors": 250,
"percentage": 20.0
},
{
"name": "Firefox",
"visitors": 125,
"percentage": 10.0
}
],
"locations": [
{
"country": "United States",
"visitors": 875,
"percentage": 70.0
},
{
"country": "Canada",
"visitors": 188,
"percentage": 15.0
},
{
"country": "United Kingdom",
"visitors": 125,
"percentage": 10.0
}
],
"hourly_distribution": [
{
"hour": 9,
"visitors": 98,
"conversions": 14
},
{
"hour": 10,
"visitors": 125,
"conversions": 18
},
{
"hour": 14,
"visitors": 142,
"conversions": 22
}
],
"form_submissions": [
{
"form_id": "contact-form",
"submissions": 156,
"conversion_rate": 15.92
},
{
"form_id": "newsletter-signup",
"submissions": 78,
"conversion_rate": 7.96
}
]
}
}
MongoDB Collections
| Collection | Operation | Purpose |
|---|---|---|
funnel_analytics | aggregate | Step-specific metrics |
funnel_page_views | aggregate | Page view analysis |
funnel_visitors | aggregate | Visitor behavior patterns |
form_submissions | aggregate | Form performance |
visitor_sessions | aggregate | Device/browser/location data |
addAnalytics()
Records analytics events (page views, form submissions, payments).
Route: POST /v1/funnels/analytics
Auth: Optional (can be called from client-side)
Request Body
{
"items": [
{
"event_type": "page_view",
"step_id": "60d5ec49f1b2c72e8c8e4b1d",
"funnel_id": "60d5ec49f1b2c72e8c8e4b1a",
"timestamp": "2024-01-22T14:30:00Z"
},
{
"event_type": "form_submission",
"step_id": "60d5ec49f1b2c72e8c8e4b1d",
"funnel_id": "60d5ec49f1b2c72e8c8e4b1a",
"form_id": "contact-form",
"timestamp": "2024-01-22T14:32:00Z"
}
],
"form_id": "contact-form",
"response_id": "60d5ec49f1b2c72e8c8e4b2c",
"page_id": "60d5ec49f1b2c72e8c8e4b1d",
"site_id": "60d5ec49f1b2c72e8c8e4b1a",
"payment_details": {
"amount": 99.99,
"currency": "USD",
"payment_method": "stripe",
"transaction_id": "ch_abc123",
"status": "succeeded"
},
"visitor_id": "vis_abc123",
"contact_id": "60d5ec49f1b2c72e8c8e4b30",
"customer_id": "cus_abc123",
"unique_visit": true,
"timestamp": "2024-01-22T14:30:00Z",
"utms": {
"source": "google",
"medium": "cpc",
"campaign": "spring_sale_2024",
"term": "buy+shoes+online",
"content": "ad_variant_a"
}
}
Response
{
"success": true,
"message": "SUCCESS",
"data": {
"_id": "60d5ec49f1b2c72e8c8e4b31",
"events_recorded": 2,
"visitor_id": "vis_abc123",
"timestamp": "2024-01-22T14:30:00Z"
}
}
MongoDB Collections
| Collection | Operation | Purpose |
|---|---|---|
funnel_analytics | insertMany | Insert event records |
funnel_visitors | findOneAndUpdate (upsert) | Track visitor data |
funnel_page_views | insertMany | Record page views |
form_submissions | insertOne | Record form submission |
payment_transactions | insertOne | Record payment |
Event Types
| Event Type | Description | Required Fields |
|---|---|---|
page_view | Visitor loads a funnel step | step_id, funnel_id, visitor_id |
form_submission | Form submitted on step | step_id, funnel_id, form_id, response_id |
payment | Payment processed | step_id, funnel_id, payment_details |
conversion | Visitor completes funnel goal | step_id, funnel_id, visitor_id |
exit | Visitor leaves funnel | step_id, funnel_id, visitor_id |
Data Models
Funnel Analytics Document
{
_id: ObjectId;
funnel_id: ObjectId;
step_id?: ObjectId; // Optional: specific step
event_type: 'page_view' | 'form_submission' | 'payment' | 'conversion' | 'exit';
visitor_id: string;
contact_id?: ObjectId; // Optional: linked contact
customer_id?: string; // Optional: payment provider customer
session_id?: string; // Optional: session tracking
timestamp: Date;
// UTM parameters
utm_source?: string;
utm_medium?: string;
utm_campaign?: string;
utm_term?: string;
utm_content?: string;
// Device info
device_type?: 'desktop' | 'mobile' | 'tablet';
browser?: string;
os?: string;
// Location
country?: string;
region?: string;
city?: string;
ip_address?: string;
// Form-specific
form_id?: string;
response_id?: ObjectId;
// Payment-specific
payment_details?: {
amount: number;
currency: string;
payment_method: string;
transaction_id: string;
status: 'succeeded' | 'failed' | 'pending';
};
created_at: Date;
}
Funnel Visitor Document
{
_id: ObjectId;
visitor_id: string; // Unique visitor identifier (cookie/fingerprint)
funnel_id: ObjectId;
account_id: ObjectId;
// First visit info
first_visit_at: Date;
first_utm_source?: string;
first_utm_medium?: string;
first_utm_campaign?: string;
// Latest visit info
last_visit_at: Date;
last_utm_source?: string;
last_utm_medium?: string;
last_utm_campaign?: string;
// Aggregated metrics
total_visits: number;
total_page_views: number;
total_time_spent: number; // Seconds
conversion_count: number;
// Device/location (from latest visit)
device_type?: string;
browser?: string;
country?: string;
// Linked records
contact_id?: ObjectId; // If visitor becomes known contact
customer_id?: string; // If visitor makes purchase
created_at: Date;
updated_at: Date;
}
Funnel Page View Document
{
_id: ObjectId;
funnel_id: ObjectId;
step_id: ObjectId;
visitor_id: string;
session_id?: string;
// Timing
entered_at: Date;
exited_at?: Date;
time_on_page?: number; // Seconds
// Referrer
referrer_url?: string;
referrer_domain?: string;
// Exit tracking
exited_to_step?: ObjectId; // Next step visited
is_exit: boolean; // Last page in session
created_at: Date;
}
Payment Transaction Document
{
_id: ObjectId;
funnel_id: ObjectId;
step_id: ObjectId;
visitor_id: string;
contact_id?: ObjectId;
// Payment info
amount: number;
currency: string;
payment_method: 'stripe' | 'square' | 'paypal';
transaction_id: string;
status: 'succeeded' | 'failed' | 'pending' | 'refunded';
// Provider details
provider_customer_id?: string;
provider_payment_intent?: string;
// Attribution
utm_source?: string;
utm_medium?: string;
utm_campaign?: string;
// Timestamps
initiated_at: Date;
completed_at?: Date;
created_at: Date;
}
Business Logic & Workflows
Page View Tracking Flow
sequenceDiagram
participant Browser
participant Analytics
participant Database
participant Aggregation
Browser->>Analytics: POST /analytics (page_view event)
Analytics->>Database: Insert page view record
Analytics->>Database: Upsert visitor record
Database-->>Analytics: Records saved
alt Unique Visit
Analytics->>Database: Increment unique visitor count
end
Analytics->>Aggregation: Trigger async aggregation
Aggregation->>Database: Update funnel metrics
Analytics-->>Browser: 200 OK
Conversion Tracking Flow
sequenceDiagram
participant Browser
participant Analytics
participant Database
participant Notification
Browser->>Analytics: POST /analytics (conversion event)
Analytics->>Database: Insert conversion record
Analytics->>Database: Update visitor status
Analytics->>Database: Calculate conversion rate
Database-->>Analytics: Conversion saved
Analytics->>Notification: Trigger conversion notification
Analytics-->>Browser: 200 OK
Notification->>Database: Check notification rules
Notification-->>Admin: Email: New Conversion Alert
Revenue Attribution Flow
sequenceDiagram
participant Payment
participant Analytics
participant Database
participant Reports
Payment->>Analytics: POST /analytics (payment event)
Analytics->>Database: Insert payment transaction
Analytics->>Database: Link to visitor record
alt Has UTM Data
Analytics->>Database: Attribute to campaign
Analytics->>Database: Update campaign revenue
end
Analytics->>Reports: Update revenue metrics
Database-->>Analytics: Payment recorded
Analytics-->>Payment: 200 OK
Integration Points
Stripe Integration
- Purpose: Track payment conversions from Stripe checkouts
- Data: Transaction ID, amount, currency, status
- Attribution: Links payments to visitor UTM sources
Square Integration
- Purpose: Track payment conversions from Square checkouts
- Data: Order ID, amount, currency, status
- Attribution: Links payments to visitor UTM sources
Form Submissions
- Purpose: Track form conversion events
- Integration: Links to
form_submissionscollection - Metrics: Form-specific conversion rates
Contact/CRM Integration
- Purpose: Link anonymous visitors to known contacts
- Data: Contact ID association
- Benefit: Full customer journey tracking
Performance Considerations
Real-time vs Batch Processing
- Real-time: Page views, form submissions recorded immediately
- Batch: Aggregate metrics calculated hourly/daily
- Optimization: Uses MongoDB aggregation pipelines for efficiency
Data Retention
- Raw events: 90 days (configurable)
- Aggregated data: Indefinite retention
- Visitor records: 2 years of inactivity
Query Optimization
- Indexed fields:
funnel_id,step_id,visitor_id,timestamp,event_type - Compound indexes:
(funnel_id, timestamp),(visitor_id, event_type) - Aggregation caching: Pre-calculated daily/monthly summaries
Error Handling
Common Errors
// Invalid funnel ID
{
"success": false,
"message": "Funnel not found",
"statusCode": 404
}
// Invalid step ID
{
"success": false,
"message": "Step not found",
"statusCode": 404
}
// Missing required fields
{
"success": false,
"message": "Missing required field: visitor_id",
"statusCode": 400
}
// Invalid date range
{
"success": false,
"message": "start_date must be before end_date",
"statusCode": 400
}
Security
Multi-Tenant Isolation
- All analytics queries filtered by account (through funnel ownership)
- Visitor data scoped to account funnels
- No cross-account visitor tracking
Data Privacy
- Visitor IDs are anonymized hashes
- IP addresses optionally anonymized (last octet removed)
- GDPR compliance: Visitor data can be purged on request
Rate Limiting
- Analytics ingestion: 1000 events per minute per account
- Query endpoints: 100 requests per minute per account
Best Practices
When to Use This Controller
- ✅ Building funnel analytics dashboards
- ✅ Tracking conversion rates and revenue
- ✅ Analyzing traffic sources and campaigns
- ✅ Monitoring funnel performance
- ✅ A/B testing funnel variations
Common Patterns
- Batch event recording: Use
itemsarray to record multiple events in one call - UTM tracking: Always include UTM parameters for attribution
- Unique visitors: Use consistent
visitor_idacross sessions - Time-based queries: Use date ranges to limit result sets
Edge Cases
- Duplicate events: Implement client-side deduplication with event IDs
- Bot traffic: Filter by user agent patterns
- Cross-device tracking: Requires contact_id linking
- Timezone handling: All timestamps stored in UTC
Related Documentation
- Funnels Controller: Funnel CRUD and step management
- Forms Controller: Form submission handling
- Stripe/Square Webhooks: Payment event integration
- Reports Module: Advanced analytics and reporting
Last Updated: January 2025
API Version: v1
Maintained By: DashClicks Engineering