MixPanel Analytics Skill
When to Use This Skill
Use this Skill in the Django4Lyfe backend when working with MixPanel analytics
tracking in the optimo_analytics module:
/mixpanel-analytics:implement– to implement new MixPanel tracking events or update existing ones following established patterns (7-step checklist)./mixpanel-analytics:review– to review MixPanel implementations for correctness, PII protection, and adherence to Django4Lyfe standards.
Example Prompts
Implement Mode
- "Use
/mixpanel-analytics:implementto add a new event for tracking when a user completes their profile setup." - "Run
/mixpanel-analytics:implement svc.surveys.reminder_sentto add tracking for survey reminder notifications." - "Implement MixPanel tracking for the new HRIS CSV validation feature using
/mixpanel-analytics:implement."
Review Mode
- "Run
/mixpanel-analytics:review stagedto check my staged MixPanel changes for PII violations and pattern compliance." - "Use
/mixpanel-analytics:review branchto audit all analytics changes on this feature branch." - "Review the entire optimo_analytics module with
/mixpanel-analytics:review all."
Modes
This Skill behaves differently based on how it is invoked:
implementmode – invoked via/mixpanel-analytics:implement:- Guides implementation of new MixPanel events through 7 steps.
- Creates constants, schemas, registry entries, service methods, and tests.
- Enforces PII protection and code patterns.
reviewmode – invoked via/mixpanel-analytics:review:- Audits existing implementations for compliance.
- Checks PII protection, schema design, service patterns, and test coverage.
- Generates structured review reports with severity tags.
Environment & Context Gathering
When this Skill runs, gather context first:
# Git context
git branch --show-current
git status --porcelain
git diff --cached --name-only | grep -E "optimo_analytics|mixpanel"
# Analytics module stats
grep -c "^ [A-Z_]* = " optimo_analytics/constants.py 2>/dev/null || echo "0"
grep -c "^class Mxp" optimo_analytics/schemas.py 2>/dev/null || echo "0"
grep -c "MixPanelEvent\." optimo_analytics/registry.py 2>/dev/null || echo "0"
ls -1 optimo_analytics/service/*.py 2>/dev/null | xargs -I{} basename {} .py
Read key reference files:
optimo_analytics/AGENTS.md– module-level rules and PII guidelinesoptimo_analytics/schemas.py– existing schema patternsoptimo_analytics/service/AGENTS.md– service layer patternsoptimo_analytics/tests/AGENTS.md– test patterns
Implementation Mode
7-Step Implementation Checklist
For each new event, complete these steps in order:
Step 1: Add Event Constant (optimo_analytics/constants.py)
# Event naming convention: {prefix}.{object}.{action}[.error]
# Examples:
# - svc.surveys.survey_delivered
# - svc.map.action_plan_created
# - svc.hris_csv.upload.analysis_completed
#
# NOTE: Do NOT include "cron" in event names - use is_cron_job property instead
class MixPanelEvent:
# Add under appropriate section with comment
NEW_EVENT_NAME = "svc.domain.action_name"
Step 2: Create Schema (optimo_analytics/schemas.py)
# Schema naming: Mxp{Domain}{Action}EventSchema
# CRITICAL RULES:
# - All UUIDs MUST be strings (str, not UUID)
# - NO PII: no names, emails, phone numbers
# - organization_name IS allowed (business approved)
# - Use STRICT_MODEL_CONFIG (no aliases) or ALIASED_MODEL_CONFIG ($ aliases)
class MxpNewEventSchema(MixpanelSuperEventPropertiesSchema):
"""Properties for svc.domain.action_name event.
Tracked when [describe when this event fires].
"""
# Required fields (no defaults)
employee_id: str = Field(description="Employee UUID as string")
organization_id: str = Field(description="Organization UUID as string")
organization_name: str = Field(description="Organization name for analytics")
role: SystemRole | None = Field(description="User role")
impersonation: bool = Field(description="Is impersonated session")
# Event-specific fields
custom_field: str = Field(description="What this field represents")
# Use STRICT_MODEL_CONFIG for internal-only schemas
# Use ALIASED_MODEL_CONFIG when field names need $ prefix for MixPanel (e.g., $device_id)
model_config = STRICT_MODEL_CONFIG
Step 3: Register in Registry (optimo_analytics/registry.py)
# Add import at top
from optimo_analytics.schemas import MxpNewEventSchema
# Add to _EVENT_SCHEMA_REGISTRY dict
_EVENT_SCHEMA_REGISTRY: dict[str, type[MixpanelSuperEventPropertiesSchema]] = {
# ... existing entries ...
MixPanelEvent.NEW_EVENT_NAME: MxpNewEventSchema,
}
Step 4: Add Tracking Helper (optimo_analytics/service/{domain}.py)
Choose appropriate service file or create new one:
auth.py- Authentication eventssurvey.py- Survey lifecycle eventsrisk.py- Risk calculation eventsmap.py- Manager Action Pipeline eventscore.py- Core/HRIS events
class OptimoMixpanel{Domain}TrackHelper:
"""Helper class for {Domain} event tracking."""
@classmethod
def track_new_event(
cls,
*, # CRITICAL: Force keyword-only arguments
employee_id: str,
# ... other params ...
) -> None:
"""
Track new event (svc.domain.action_name).
Tracked when [describe trigger condition].
Args:
employee_id: Employee UUID as string
"""
try:
cls._track_new_event(
employee_id=employee_id,
# ... pass all args ...
)
except Exception:
# Fire-and-forget: log but don't propagate
logger.exception(
"mixpanel_new_event_tracking_failed",
employee_id=employee_id,
)
@staticmethod
def _track_new_event(
*,
employee_id: str,
# ... other params ...
) -> None:
"""Track new event implementation."""
emp_info = OptimoMixpanelService._fetch_required_emp_info(
employee_id=employee_id
)
properties = MxpNewEventSchema(
employee_id=employee_id,
organization_id=str(emp_info.organization.uuid),
organization_name=emp_info.organization.name,
role=emp_info.role,
impersonation=False,
# ... event-specific fields ...
)
# distinct_id fallback hierarchy:
# 1. User's UUID (primary)
# 2. org_<organization_uuid> (fallback when no user)
# 3. Context-specific: slack_<id>, apikey_<id>, webhook_<id>
distinct_id = employee_id # or f"org_{org_uuid}" if no user
OptimoMixpanelService.track_event(
distinct_id=distinct_id,
event_name=MixPanelEvent.NEW_EVENT_NAME,
properties=properties,
)
Step 5: Export from __init__.py (optimo_analytics/service/__init__.py)
# Add to imports
from optimo_analytics.service.{domain} import OptimoMixpanel{Domain}TrackHelper
# Add to __all__
__all__ = [
# ... existing ...
"OptimoMixpanel{Domain}TrackHelper",
]
Step 6: Add Tests (optimo_analytics/tests/test_{event}_event.py)
"""Tests for {Event} MixPanel tracking."""
from unittest.mock import patch
from uuid import uuid4
import pytest
from optimo_analytics.constants import MixPanelEvent
from optimo_analytics.registry import EVENT_SCHEMA_REGISTRY, is_event_registered
from optimo_analytics.schemas import MxpNewEventSchema
from optimo_analytics.service import OptimoMixpanel{Domain}TrackHelper
pytestmark = [pytest.mark.django_db]
@pytest.fixture(autouse=True)
def eager_jobs(settings):
"""Force synchronous job execution."""
settings.OPTIMO_JOBS_EAGER_MODE = True
yield
settings.OPTIMO_JOBS_EAGER_MODE = False
@pytest.fixtu