Magenta Tracking Pixel Specification
Overview
Magenta is a privacy-focused, first-party analytics system designed to provide comprehensive user tracking while respecting user privacy. It consists of a lightweight JavaScript library and a Django backend that work together to track user interactions, page views, and custom events.
System Architecture
graph TB
subgraph "Client Side"
A[Magenta.js] --> B[Event Queue]
B --> C[Batch Processor]
C --> D[HTTP POST]
end
subgraph "Server Side"
D --> E[Django Analytics API]
E --> F[Event Processing]
F --> G[Database Storage]
G --> H[Analytics Models]
end
subgraph "Data Models"
H --> I[AnonymousProfile]
H --> J[Session]
H --> K[Event]
H --> L[PageView]
end
Key Features
Privacy-First Design
- Respects Do Not Track (DNT) headers
- Optional cookieless mode
- No third-party dependencies
- First-party data only
- GDPR compliant by design
Tracking Capabilities
Automatic Tracking
- Page views (including SPA navigation)
- Click events
- Form submissions
- Session management
- Page exit events
Manual Tracking
- Custom events
- User identification
- E-commerce events
- Goal conversions
Performance
- Lightweight (~5KB minified)
- Asynchronous loading
- Event batching to reduce requests
- Local storage for offline resilience
- CDN fallback support
Implementation Components
1. JavaScript Library (magenta.js
)
Configuration
window.magenta = {
apiEndpoint: '/analytics/api',
siteId: 'comma-main',
debug: false,
trackPageViews: true,
trackClicks: true,
trackForms: true,
respectDoNotTrack: true,
cookieless: false
};
Core Methods
track(eventName, properties)
- Track custom eventsidentify(userId, traits)
- Identify authenticated userstrackPageView(properties)
- Manual page view trackingreset()
- Clear user session
Automatic Data Collection
- Page URL and title
- Referrer information
- Screen resolution
- Browser and OS details
- UTM parameters
- Session duration
- Engagement metrics
2. Django Backend
API Endpoint
- URL:
/api/v1/analytics/track/
- Method: POST
- Authentication: None required (public endpoint)
- CSRF: Exempt
Request Format
{
"ev": "pageload|click|form|custom",
"sid": "session-id",
"uid": "user-id",
"aid": "anonymous-id",
"site": "site-id",
"url": "https://comma.cm/article",
"ref": "https://google.com",
"title": "Page Title",
"props": {
"category": "news",
"author": "john-doe"
},
"meta": {
"screen": "1920x1080",
"viewport": "1200x800",
"browser": "Chrome 120",
"os": "Mac OS X"
}
}
Response Format
{
"success": true,
"session_id": "uuid",
"event_id": "uuid"
}
3. Data Models
AnonymousProfile
class AnonymousProfile(models.Model):
anonymous_id = models.CharField(max_length=64, unique=True, db_index=True)
user = models.ForeignKey(User, null=True, blank=True, on_delete=models.SET_NULL)
created_at = models.DateTimeField(auto_now_add=True)
last_seen = models.DateTimeField(auto_now=True)
total_sessions = models.IntegerField(default=0)
total_events = models.IntegerField(default=0)
total_pageviews = models.IntegerField(default=0)
browser = models.CharField(max_length=100, blank=True)
os = models.CharField(max_length=100, blank=True)
device_type = models.CharField(max_length=20, blank=True)
country = models.CharField(max_length=2, blank=True)
region = models.CharField(max_length=100, blank=True)
city = models.CharField(max_length=100, blank=True)
Session
class Session(models.Model):
session_id = models.CharField(max_length=64, unique=True, db_index=True)
profile = models.ForeignKey(AnonymousProfile, on_delete=models.CASCADE)
site_id = models.CharField(max_length=50, db_index=True)
started_at = models.DateTimeField(auto_now_add=True)
ended_at = models.DateTimeField(null=True, blank=True)
duration = models.IntegerField(default=0)
pageview_count = models.IntegerField(default=0)
event_count = models.IntegerField(default=0)
entry_page = models.URLField(max_length=2000, blank=True)
exit_page = models.URLField(max_length=2000, blank=True)
referrer = models.URLField(max_length=2000, blank=True)
utm_source = models.CharField(max_length=100, blank=True)
utm_medium = models.CharField(max_length=100, blank=True)
utm_campaign = models.CharField(max_length=100, blank=True)
Event
class Event(models.Model):
EVENT_TYPES = [
('pageload', 'Page Load'),
('click', 'Click'),
('form', 'Form Submit'),
('custom', 'Custom Event'),
('identify', 'Identify'),
]
profile = models.ForeignKey(AnonymousProfile, on_delete=models.CASCADE)
session = models.ForeignKey(Session, on_delete=models.CASCADE)
event_type = models.CharField(max_length=20, choices=EVENT_TYPES, db_index=True)
event_name = models.CharField(max_length=100, db_index=True)
timestamp = models.DateTimeField(auto_now_add=True, db_index=True)
properties = models.JSONField(default=dict)
url = models.URLField(max_length=2000, blank=True)
element_text = models.CharField(max_length=200, blank=True)
element_classes = models.CharField(max_length=500, blank=True)
PageView
class PageView(models.Model):
profile = models.ForeignKey(AnonymousProfile, on_delete=models.CASCADE)
session = models.ForeignKey(Session, on_delete=models.CASCADE)
event = models.OneToOneField(Event, on_delete=models.CASCADE)
url = models.URLField(max_length=2000, db_index=True)
title = models.CharField(max_length=500)
referrer = models.URLField(max_length=2000, blank=True)
timestamp = models.DateTimeField(auto_now_add=True, db_index=True)
time_on_page = models.IntegerField(default=0)
scroll_depth = models.IntegerField(default=0)
exit_intent = models.BooleanField(default=False)
Installation & Deployment
1. Include Magenta.js
<!-- Option 1: Local hosting -->
<script src="{% static 'js/magenta.min.js' %}" defer></script>
<!-- Option 2: CDN with fallback -->
<script>
(function() {
var script = document.createElement('script');
script.src = 'https://cdn.comma.cm/js/magenta.min.js';
script.async = true;
script.onerror = function() {
// Fallback to local version
var fallback = document.createElement('script');
fallback.src = '{% static "js/magenta.min.js" %}';
document.head.appendChild(fallback);
};
document.head.appendChild(script);
})();
</script>
2. Configure Tracking
<script>
window.magenta = {
apiEndpoint: '{{ MAGENTA_API_ENDPOINT|default:"/analytics/api" }}',
siteId: '{{ MAGENTA_SITE_ID|default:"comma-main" }}',
debug: {{ DEBUG|yesno:"true,false" }}
};
// Identify logged-in users
{% if user.is_authenticated %}
window.magenta.identify = {
userId: '{{ user.id }}',
email: '{{ user.email }}',
username: '{{ user.username }}'
};
{% endif %}
</script>
3. Enable Django URLs
# config/urls.py
urlpatterns = [
# ... other patterns
path('api/v1/analytics/', include('apps.analytics.urls')), # Currently commented out
]
Security Considerations
- CSRF Protection: The tracking endpoint is CSRF-exempt as it's a public API
- Rate Limiting: Implement rate limiting to prevent abuse
- Data Validation: All incoming data is validated and sanitized
- IP Anonymization: Store only partial IP addresses for privacy
- SSL/TLS: Always use HTTPS in production
- CORS: Configure appropriate CORS headers
Performance Optimization
- Event Batching: Queue events and send in batches every 5 seconds
- Local Storage: Cache events locally for offline support
- Compression: Use gzip compression for requests
- CDN Distribution: Serve magenta.js from CDN with long cache headers
- Database Indexes: Optimize queries with appropriate indexes
Analytics Dashboards
Real-time Metrics
- Active users
- Current page views
- Live event stream
- Geographic distribution
Historical Analysis
- User acquisition funnels
- Engagement metrics
- Content performance
- Campaign attribution
- User journey mapping
Migration Checklist
- [ ] Copy
packages/magenta-tracking/
directory - [ ] Copy
services/django/apps/analytics/
app - [ ] Add analytics app to INSTALLED_APPS
- [ ] Run migrations for analytics models
- [ ] Configure analytics settings
- [ ] Enable analytics URLs in
config/urls.py
- [ ] Update Django templates to include Magenta
- [ ] Configure CDN for magenta.js
- [ ] Set up monitoring and alerts
- [ ] Test tracking in staging environment
- [ ] Create analytics dashboards
- [ ] Document API endpoints
- [ ] Train team on analytics usage
Compliance & Privacy
GDPR Compliance
- User consent management
- Right to erasure (data deletion)
- Data portability exports
- Privacy by design
Cookie Policy
- First-party cookies only
- Session cookies expire after 30 minutes
- Persistent cookies expire after 2 years
- Cookieless mode available
Data Retention
- Raw events: 90 days
- Aggregated data: 2 years
- User profiles: Until deletion requested