Comma DocsComma Docs
Home
  • REST API
  • GraphQL API
Components
Infrastructure
  • Django
  • Vue.js
  • PrimeVue
  • Tailwind CSS
  • Prompts
  • Architecture
  • Labs
  • Dev
  • Deployment
  • Operations
  • Future Work
GitHub
Home
  • REST API
  • GraphQL API
Components
Infrastructure
  • Django
  • Vue.js
  • PrimeVue
  • Tailwind CSS
  • Prompts
  • Architecture
  • Labs
  • Dev
  • Deployment
  • Operations
  • Future Work
GitHub
  • Overview

    • Comma Project Documentation
    • Documentation Guidelines (CLAUDE.md)
    • Analytics Cleanup Summary
    • CI/CD Pipeline Fixes
    • Magenta Domain Change Summary
    • Magenta Analytics Installation Guide
    • Magenta Tracking Pixel Specification
    • Metabase Setup Guide

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 events
  • identify(userId, traits) - Identify authenticated users
  • trackPageView(properties) - Manual page view tracking
  • reset() - 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

  1. CSRF Protection: The tracking endpoint is CSRF-exempt as it's a public API
  2. Rate Limiting: Implement rate limiting to prevent abuse
  3. Data Validation: All incoming data is validated and sanitized
  4. IP Anonymization: Store only partial IP addresses for privacy
  5. SSL/TLS: Always use HTTPS in production
  6. CORS: Configure appropriate CORS headers

Performance Optimization

  1. Event Batching: Queue events and send in batches every 5 seconds
  2. Local Storage: Cache events locally for offline support
  3. Compression: Use gzip compression for requests
  4. CDN Distribution: Serve magenta.js from CDN with long cache headers
  5. 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
Edit this page on GitHub
Last Updated: 6/20/25, 9:58 AM
Contributors: Scott de Rozic
Prev
Magenta Analytics Installation Guide
Next
Metabase Setup Guide