Engagement Stats System
The Engagement Stats system provides comprehensive analytics and reporting on alumni engagement activities across multiple dimensions and time periods. It’s accessible at /engagement_stats and consists of multiple tabs with different views and calculations.
Overview
The engagement stats system analyzes engagement activities using a sophisticated scoring system that combines:
- Level-based point scoring for activity quality
- Activity count tracking for engagement breadth
- Time period filtering for temporal analysis
- Demographic breakdowns for population insights
- Matrix analysis for quadrant-based segmentation
Core Components
1. Scoring System
Level-Based Points
Based on EngagementType::LEVEL_POINTS:
- Level 0: 0 points (inactive/administrative)
- Level 1: 1 point (basic engagement like email clicks)
- Level 2: 3 points (meaningful engagement like event attendance)
- Level 3: 7 points (significant engagement like panel participation)
- Level 4: 10 points (highest engagement like major giving)
Activity Caps (Anti-Gaming Protection)
To prevent manipulation through repetitive low-level activities:
- Email Clicks: Maximum 5 count toward score and activity count
- Event RSVPs: Maximum 2 count toward score and activity count
- All Other Activities: No caps applied
Rankings use a “distance” calculation balancing quality and breadth:
Distance = √((score × 1.5)² + (capped_activity_count × 1.0)²)
2. Time Period Filtering
Fiscal Year Support
- Fiscal Year: July 1 - June 30 (using
FiscalYearHelpers)
- Current Fiscal Year: Automatically calculated based on current date
- Historical Analysis: Support for previous fiscal years
Time Period Options
- 30 Days: Last 30 days from current date
- 6 Months: Last 6 months from current date
- 1 Year: Last 12 months from current date
- All Time: No date restrictions
- Custom Fiscal Year: Specific fiscal year selection
Caching Strategy
- Fast Mode: Used for active tab viewing with 1-hour cache
- Comprehensive Mode: Used for background calculations
- Cache Keys: Include date range and filter parameters
Database Optimization
- Batch Processing: Alumni processed in batches of 50-100
- Optimized Joins: Careful association loading
- Query Limits: Emergency limits for large datasets (max 10,000 engaged alumni)
- SQL-based Aggregations: Database-level calculations where possible
Tab Breakdown
Overview Tab
Purpose: High-level engagement statistics and trends
Key Metrics:
- Total engaged alumni count
- Average engagement score
- Score distribution brackets
- Engagement statistics (total activities, average per alumnus)
Calculations:
- Uses
EngagementScoreCalculator for precise scoring
- Processes in batches to handle large datasets
- Includes score bracket distribution (1-2, 3, 4-6, 7-9, 10-14, 15+ points)
Analytics Tab
Purpose: Detailed charts and advanced metrics
Features:
- Score distribution charts
- Engagement trends over time
- Single vs. multiple engagement analysis
- Level 3+ activity participation rates
Performance: Intensive mode with detailed processing
Breakdown Tab
Purpose: Activity breakdown by champion role and level
Display:
- Activities grouped by champion role (Connection Advisor, Digital Ambassador, etc.)
- Level headers show point values: “Level 1 (1 pt)”, “Level 2 (3 pts)”, etc.
- Champion role icons (SVG files in
/public/)
- Expandable activity descriptions
Data Structure:
@activity_data = {
"Champion Role Name" => {
types: [
{
name: "Activity Name",
code: "activity_code",
level: 2,
unique_buids: 150,
descriptions: [
{ description: "Specific activity", count: 50, unique_buids: 45 }
]
}
]
}
}
Demographics Tab
Purpose: Engagement analysis by demographic segments
Segments:
- Graduation year ranges
- Degree programs
- Geographic regions
- Other demographic filters
Matrix Tab
Purpose: Quadrant analysis based on score vs. activity count
Quadrants:
- Committed: High score (≥10) + High activity count (≥3)
- Purposeful: High score (≥10) + Low activity count (<3)
- Frequent: Low score (<10) + High activity count (≥3)
- Untapped: Low score (<10) + Low activity count (<3)
Visualization: Scatter plot with quadrant boundaries
Top Alumni Tab
Purpose: Ranked list of most engaged alumni
Ranking: Based on distance formula combining score and activity count
Features: Detailed activity breakdowns per alumnus
Activity Pairs Tab
Purpose: Analysis of alumni with specific activity combinations
Use Case: Understanding which activities occur together
Export: CSV export functionality available
Technical Implementation
Service Architecture (CRITICAL)
⚠️ All statistics logic MUST be in services, NOT duplicated in the controller.
The EngagementStats:: namespace provides services for each tab. The controller should only:
- Instantiate the service with filter parameters
- Call the service
- Set instance variables from the result
# ✅ Correct pattern - controller delegates to service
def load_demographics_data
service = EngagementStats::DemographicsService.new(
start_date: @start_date,
end_date: @end_date,
college: @college,
year: @year
)
service.call.each { |key, value| instance_variable_set("@#{key}", value) }
@last_updated = Rails.cache.read("engagement_stats_last_updated") || Time.current
end
| Service |
Purpose |
Cache Duration |
OverviewService |
Goal metrics, engagement counts |
4 hours |
AnalyticsService |
Charts, score distributions |
4 hours |
BreakdownService |
Activity breakdown by role/level |
1 hour |
DemographicsService |
Year/college/major breakdowns |
1 hour |
MatrixService |
Quadrant analysis scatter plot |
1 hour |
ActivityPairsService |
Activity combination analysis |
1 hour |
Key Design Decisions:
-
Alumni Counting (not Degrees): All services count unique alumni by BUID, not degree records. An alum with multiple degrees appears once per graduation year.
-
Built-in Caching: Services use BaseService#with_caching - no need for separate fast/comprehensive modes.
-
Tested Logic: Services have tests in test/services/engagement_stats/. Controller duplicates are NOT tested.
-
Degree Classification:
- Bachelor’s includes Associate’s (
A% + B% codes)
- Doctorate includes
D%, J%, P% codes
Controller Structure
EngagementStatsController handles all tab logic with methods:
load_overview_data / load_analytics_data / etc.
- Fast vs. comprehensive loading strategies
- Optimized SQL queries with proper caching
Key Services
EngagementScoreCalculator: Core scoring logic with caps
TopEngagedAlumniService: Ranking and distance calculations
AlumniFilterService: Filtering by demographics
FiscalYearHelpers: Date range calculations
Database Dependencies
alumni table with buid primary key
engagement_activities table with buid, activity_code, engagement_date
engagement_types table with code, level, champion_role
- Proper indexes on date ranges and foreign keys
Filters and Parameters
URL Parameters
tab: Active tab (overview, analytics, breakdown, etc.)
start_date / end_date: Custom date ranges
year: Fiscal year selection
- Demographic filters (passed to
AlumniFilterService)
Alumni Filtering
Integration with AlumniFilterService supports:
- Graduation year ranges
- Degree programs
- Geographic regions
- Champion status
- Other demographic criteria
Large Dataset Handling
- Batch Processing: Process alumni in chunks
- Query Optimization: Use database aggregations where possible
- Emergency Limits: Cap processing at 10,000 engaged alumni
- Timeout Protection: Prevent long-running queries
Caching Strategy
- Cache Duration: 1-4 hours for different data types (overview: 4 hours, detailed views: 1 hour)
- Cache Invalidation: Manual clearing via “Update Now” link or
Rails.cache.clear
- Cache Keys: Include all relevant filter parameters
- Real-time Updates: Cache clearing forces immediate data recalculation
- Last Updated Tracking: Timestamps stored for user feedback on data freshness
Cache Update Interface
- Last Updated Display: Shows when cached data was last calculated in Central Time
- Manual Refresh: “Update Now” link available at bottom left of all tabs
- Confirmation Dialog: Prevents accidental cache clearing
- Route:
POST /engagement_stats/clear_cache clears all engagement stats caches
SQL Optimization
- Capped Scoring: SQL implementation of Level 1 activity caps
- Optimized Joins: Careful use of
includes and joins
- Index Usage: Ensure proper database indexes
UI Features
Visual Elements
- Color Coding: Consistent level colors across all views
- Champion Icons: SVG files for each champion role
- Progress Indicators: For long-running calculations
- Responsive Design: Tailwind CSS implementation
- Cache Status Display: Bottom-left timestamp showing last data update in Central Time
Export Capabilities
- CSV Export: Available for activity pairs and other datasets
- Formatted Output: Proper headers and data formatting
User Interface Controls
- Tab Navigation: Seven main tabs with consistent URL parameters
- Filter Controls: Date ranges, college selection, and graduation year filtering
- Data Refresh: “Update Now” link for manual cache clearing (bottom-left of page)
- Time Display: All timestamps shown in Central Time (US & Canada)
Troubleshooting
Common Issues
- Missing Icons: Check SVG files in
/public/ directory
- Slow Performance: Check for missing database indexes
- Cache Issues: Use “Update Now” link or clear Rails cache in production
- Data Inconsistencies: Verify engagement_types.champion_role values
- Stale Data: Click “Update Now” to force cache refresh after importing new engagement data
- Monitor Rails logs for query performance
- Check cache hit/miss rates via “Last Updated” timestamp
- Verify batch processing is working correctly
- Use “Update Now” link to test cache clearing functionality