Analytics & Business Intelligence Guide
Last Updated: 2026-01-10 Status: Implemented Plan References:
- 037-analytics-business-intelligence.md
- 052-analytics-enhancement.md
Overview
The Analytics & Business Intelligence system provides data-driven insights into portal usage, business performance, and trends. It includes interactive dashboards, KPI tracking, trend analysis, predictive insights, drill-down exploration, period comparisons, and comprehensive export capabilities to help administrators make informed decisions.
Table of Contents
- Accessing Analytics
- Dashboard Overview
- Key Metrics
- Charts & Visualizations
- Period Comparisons
- Trend Analysis
- Drill-Down Exploration
- Export Options
- Custom Dashboards
- Technical Architecture
- Related Features
Accessing Analytics
Navigation
| Access Point | Location | URL | Role |
|---|---|---|---|
| Analytics Dashboard | Admin sidebar | /admin/analytics | Admin |
| Financial Analytics | Analytics menu | /admin/analytics/financial | Admin |
| Client Analytics | Analytics menu | /admin/analytics/clients | Admin |
| Project Analytics | Analytics menu | /admin/analytics/projects | Admin |
| Comparisons | Analytics menu | /admin/analytics/comparisons | Admin |
| Trends | Analytics menu | /admin/analytics/trends | Admin |
| Drill-Down | Analytics menu | /admin/analytics/drill-down | Admin |
| Exports | Analytics menu | /admin/analytics/exports | Admin |
Permissions
| Action | Admin | Client User |
|---|---|---|
| View analytics dashboard | Yes | No |
| Create custom dashboards | Yes | No |
| Export analytics data | Yes | No |
| Configure KPIs | Yes | No |
| Use drill-down | Yes | No |
| Create comparisons | Yes | No |
| View trend analysis | Yes | No |
Dashboard Overview
Main Dashboard
The analytics dashboard provides at-a-glance insights:
| Section | Content |
|---|---|
| KPI Cards | Key performance indicators |
| Revenue Chart | Revenue over time |
| Client Growth | New clients trend |
| Project Status | Projects by status |
| Recent Activity | Latest portal activity |
Time Period Selection
| Period | Description |
|---|---|
| Today | Current day |
| This Week | Current week |
| This Month | Current month |
| This Quarter | Current quarter |
| This Year | Current year |
| Custom | Select date range |
Key Metrics
Revenue Metrics
| Metric | Description | Calculation |
|---|---|---|
| Total Revenue | All-time revenue | Sum of paid invoices |
| Monthly Revenue | This month | Paid invoices this month |
| MRR | Monthly recurring | Subscription-based revenue |
| Revenue Growth | Month-over-month | (Current - Previous) / Previous |
| Average Invoice | Mean invoice value | Total / Invoice count |
Client Metrics
| Metric | Description | Calculation |
|---|---|---|
| Total Clients | All clients | Client count |
| Active Clients | With active projects | Clients with status=active projects |
| New Clients | Added this period | Created in date range |
| Churn Rate | Lost clients | Inactive / Total |
| Client Lifetime Value | Average revenue per client | Total revenue / Client count |
| Client Retention Rate | Returning clients | Retained / Previous period clients |
Project Metrics
| Metric | Description | Calculation |
|---|---|---|
| Total Projects | All projects | Project count |
| Active Projects | Currently active | Status = active |
| Completion Rate | Completed projects | Completed / Total |
| Average Duration | Days to complete | Avg(completion - start) |
| Projects per Client | Average projects | Projects / Clients |
Engagement Metrics
| Metric | Description | Calculation |
|---|---|---|
| Daily Active Users | Unique logins today | Distinct users logged in |
| Monthly Active Users | Unique logins this month | Distinct monthly logins |
| Average Session | Time spent | Avg session duration |
| Portal Adoption | Clients using portal | Active clients / Total |
| File Downloads | Downloads per period | Download count |
Charts & Visualizations
Chart Types
The system supports 18 chart types via the ChartBuilder service:
| Type | Use Case | Example |
|---|---|---|
| Line Chart | Trends over time | Revenue by month |
| Bar Chart | Comparisons | Revenue by client |
| Horizontal Bar | Ranked comparisons | Top clients by revenue |
| Pie Chart | Proportions | Projects by status |
| Donut Chart | Composition | Invoice status breakdown |
| Area Chart | Cumulative trends | Cumulative revenue |
| Stacked Area | Multiple series areas | Revenue by category |
| Stacked Bar | Grouped comparisons | Monthly revenue by type |
| Grouped Bar | Side-by-side comparison | This year vs last year |
| Radar Chart | Multi-dimensional | Client health score |
| Polar Area | Radial proportions | Category distribution |
| Scatter Chart | Correlation analysis | Price vs quantity |
| Sankey | Flow visualization | Revenue flow by source |
| Funnel | Conversion stages | Sales pipeline |
| Waterfall | Incremental changes | Cash flow analysis |
| Bubble | 3D data points | Client size/revenue/age |
| Sparkline | Inline trends | Dashboard KPI trends |
| Multi-Axis | Dual Y-axis | Revenue + Count |
Advanced Chart Types (Plan 052)
Sankey Chart
- Visualizes flow of values between categories
- Shows source → target relationships with proportional widths
- Use for: Revenue flows, customer journey, resource allocation
Funnel Chart
- Shows conversion through stages
- Each stage shows value and percentage of previous
- Use for: Sales pipeline, lead conversion, process completion
Waterfall Chart
- Displays incremental changes to a starting value
- Shows positive (green) and negative (red) changes
- Supports subtotals at specific indices
- Use for: Cash flow, budget variance, cumulative impact
Bubble Chart
- 3-dimensional scatter plot (x, y, radius)
- Can group by category with different colors
- Use for: Client analysis, portfolio visualization
Sparkline Chart
- Compact inline chart for dashboards
- Shows trend direction and change percentage
- Minimal chrome, maximum data density
- Use for: KPI cards, tables with trends
Period Comparisons
Overview
Compare metrics across multiple time periods to identify trends and performance changes.
Location: /admin/analytics/comparisons
Comparison Types
| Type | Description | Example |
|---|---|---|
| Year-over-Year (YoY) | Compare same periods across years | 2024 vs 2023 revenue |
| Quarter-over-Quarter (QoQ) | Compare sequential quarters | Q1 vs Q2 performance |
| Month-over-Month (MoM) | Compare sequential months | Monthly trend analysis |
| Custom Periods | Define custom date ranges | Campaign periods |
| Period-over-Period | Compare any defined periods | Pre/post launch |
Available Metrics
| Metric | Description |
|---|---|
| Revenue | Total paid invoice revenue |
| Invoices | Invoice count |
| Projects | Project count |
| Clients | New client count |
| Collection Rate | % of invoices collected |
| Project Completion | % of projects completed |
| Client Retention | % of clients retained |
Comparison Output
Each comparison returns:
[
'metric' => 'revenue',
'metric_label' => 'Revenue',
'comparison_type' => 'year_over_year',
'periods' => [
[
'label' => '2023',
'start' => '2023-01-01',
'end' => '2023-12-31',
'value' => 150000,
'change' => null,
'change_percent' => null,
'trend' => 'neutral',
],
[
'label' => '2024',
'start' => '2024-01-01',
'end' => '2024-12-31',
'value' => 185000,
'change' => 35000,
'change_percent' => 23.33,
'trend' => 'up',
],
],
'summary' => [
'overall_change' => 35000,
'overall_change_percent' => 23.33,
'overall_trend' => 'up',
'best_period' => '2024',
'worst_period' => '2023',
'average' => 167500,
'max' => 185000,
'min' => 150000,
],
];
Saving Comparisons
Save frequently-used comparisons for quick access:
- Configure comparison parameters
- Click "Save Comparison"
- Name the comparison
- Optionally pin to dashboard
- Access from saved comparisons list
Trend Analysis
Overview
Analyze data trends using statistical methods for insights and forecasting.
Location: /admin/analytics/trends
Analysis Components
| Component | Description |
|---|---|
| Trend Direction | Up, down, or stable |
| Slope | Rate of change |
| R-squared | Trend reliability (0-1) |
| Statistics | Mean, median, std dev |
| Moving Averages | SMA and EMA |
| Forecast | Predicted future values |
| Anomalies | Unusual data points |
| Seasonality | Recurring patterns |
| Growth Analysis | Period-over-period growth |
Trend Calculation
// Example trend result
[
'direction' => 'up', // up, down, stable, insufficient_data
'slope' => 2.5, // Rate of change per period
'r_squared' => 0.95, // Correlation coefficient
'intercept' => 100, // Y-intercept
'strength' => 'strong', // Trend strength
]
Moving Averages
| Type | Description |
|---|---|
| SMA (Simple) | Equal-weighted average over window |
| EMA (Exponential) | Recent values weighted more heavily |
Forecasting
Uses linear regression with confidence intervals:
[
'periods' => [
[
'period' => '2024-07',
'value' => 182500,
'confidence_lower' => 165000,
'confidence_upper' => 200000,
],
// ... more forecast periods
],
'method' => 'linear_regression',
'confidence_level' => 0.95,
]
Anomaly Detection
Identifies unusual values using Z-score analysis:
[
[
'period' => '2024-04',
'value' => 500000,
'expected' => 150000,
'z_score' => 4.5,
'type' => 'high', // high or low
],
]
Growth Analysis
[
'total_growth_percent' => 33.1,
'average_period_growth' => 10.0,
'cagr' => 8.5, // Compound annual growth rate
'growth_consistency' => 0.85,
]
Drill-Down Exploration
Overview
Explore data hierarchically, drilling from summary to detail levels.
Location: /admin/analytics/drill-down
Available Hierarchies
| Hierarchy | Levels | Description |
|---|---|---|
| Revenue | Year → Quarter → Month → Week → Day | Time-based revenue drill-down |
| Time | Year → Quarter → Month → Week → Day → Hour | General time hierarchy |
| Clients | Industry → Size → Region → Client | Client segmentation |
| Projects | Status → Type → Client → Project | Project organization |
| Geography | Country → State → City | Location-based analysis |
Using Drill-Down
- Select Hierarchy: Choose the dimension to explore
- View Summary: See top-level aggregation
- Click to Drill: Select a value to drill deeper
- View Breadcrumb: Track your drill path
- Navigate: Use breadcrumb to jump to any level
- Save Path: Bookmark useful drill paths
Drill-Down Response
[
'hierarchy' => 'revenue',
'hierarchy_name' => 'Revenue',
'metric' => 'revenue',
'current_level' => 1,
'current_level_name' => 'year',
'next_level' => 'quarter',
'can_drill_deeper' => true,
'path' => ['2024'],
'breadcrumb' => [
['level' => 'year', 'value' => '2024'],
],
'data' => [
['dimension' => '1', 'label' => 'Q1 2024', 'value' => 45000, 'drillable' => true],
['dimension' => '2', 'label' => 'Q2 2024', 'value' => 52000, 'drillable' => true],
['dimension' => '3', 'label' => 'Q3 2024', 'value' => 48000, 'drillable' => true],
['dimension' => '4', 'label' => 'Q4 2024', 'value' => 55000, 'drillable' => true],
],
'total' => 200000,
]
Saved Drill Paths
Save and bookmark frequently-used drill paths:
| Field | Description |
|---|---|
| Name | Descriptive name |
| Hierarchy | Which hierarchy |
| Path | Array of drill values |
| Filters | Optional filters applied |
| Is Bookmarked | Quick access flag |
Export Options
Overview
Export analytics data in multiple formats for reporting and external analysis.
Location: /admin/analytics/exports
Supported Formats
| Format | Extension | Use Case |
|---|---|---|
| Formatted reports | ||
| Excel | .xlsx | Data analysis |
| CSV | .csv | Data import/export |
| JSON | .json | API integration |
| PNG | .png | Chart images |
| SVG | .svg | Scalable graphics |
| PowerPoint | .pptx | Presentations |
Export Types
| Type | Description | Formats |
|---|---|---|
| Dashboard | Full dashboard export | PDF, PPTX |
| Chart | Single chart export | PNG, SVG, PDF |
| Data | Raw data export | CSV, Excel, JSON |
| Report | Formatted report | PDF, PPTX |
| Comparison | Comparison results | PDF, Excel, CSV |
| Trend Analysis | Trend report | PDF, Excel |
Creating an Export
- Navigate to analytics section
- Click "Export" button
- Select format
- Configure options:
- Include charts
- Include data tables
- Date range
- Filters
- Click "Generate Export"
- Download when ready (background processing for large exports)
Export Status
| Status | Description |
|---|---|
| Pending | Queued for processing |
| Processing | Currently generating |
| Completed | Ready for download |
| Failed | Error during generation |
| Expired | Download link expired |
Automatic Cleanup
Exports are automatically cleaned up after configured retention period (default: 7 days).
Custom Dashboards
Creating a Dashboard
- Navigate to Admin → Analytics → Dashboards
- Click "Create Dashboard"
- Enter dashboard name
- Add widgets:
- Click "Add Widget"
- Select widget type (Chart, KPI, Table)
- Configure data source
- Set dimensions and metrics
- Arrange widgets by dragging
- Click "Save Dashboard"
Widget Types
| Type | Description |
|---|---|
| KPI Card | Single metric with trend (uses sparkline) |
| Line Chart | Time series data |
| Bar Chart | Categorical comparison |
| Pie Chart | Proportional breakdown |
| Funnel | Conversion stages |
| Waterfall | Incremental changes |
| Bubble | Multi-dimensional analysis |
| Data Table | Tabular data view |
| Metric Comparison | Period comparison |
| Goal Tracker | Progress toward target |
Sharing Dashboards
- Open dashboard
- Click "Share"
- Options:
- Copy link (view-only)
- Schedule email delivery
- Export as PDF/PPTX
Technical Architecture
Models
SavedComparison Model: app/Models/SavedComparison.php
class SavedComparison extends Model
{
protected $fillable = [
'name',
'description',
'metric',
'comparison_type',
'periods',
'filters',
'visualization',
'is_pinned',
'created_by',
];
protected $casts = [
'periods' => 'array',
'filters' => 'array',
'visualization' => 'array',
'is_pinned' => 'boolean',
];
const METRICS = [
'revenue' => 'Revenue',
'invoices' => 'Invoice Count',
'projects' => 'Project Count',
'clients' => 'Client Count',
'collection_rate' => 'Collection Rate',
'project_completion' => 'Project Completion Rate',
'client_retention' => 'Client Retention Rate',
];
}
AnalyticsExport Model: app/Models/AnalyticsExport.php
class AnalyticsExport extends Model
{
protected $fillable = [
'name',
'type',
'format',
'status',
'parameters',
'file_path',
'file_size',
'error_message',
'started_at',
'completed_at',
'expires_at',
'created_by',
];
protected $casts = [
'parameters' => 'array',
'started_at' => 'datetime',
'completed_at' => 'datetime',
'expires_at' => 'datetime',
];
}
AnalyticsDrillPath Model: app/Models/AnalyticsDrillPath.php
class AnalyticsDrillPath extends Model
{
protected $fillable = [
'name',
'metric',
'hierarchy',
'path',
'filters',
'is_bookmarked',
'user_id',
];
protected $casts = [
'path' => 'array',
'filters' => 'array',
'is_bookmarked' => 'boolean',
];
const HIERARCHIES = [
'revenue' => [
'name' => 'Revenue',
'levels' => ['year', 'quarter', 'month', 'week', 'day'],
],
'time' => [
'name' => 'Time',
'levels' => ['year', 'quarter', 'month', 'week', 'day', 'hour'],
],
'clients' => [
'name' => 'Clients',
'levels' => ['industry', 'size', 'region', 'client'],
],
'projects' => [
'name' => 'Projects',
'levels' => ['status', 'type', 'client', 'project'],
],
'geography' => [
'name' => 'Geography',
'levels' => ['country', 'state', 'city'],
],
];
}
Services
ComparisonService: app/Services/Analytics/ComparisonService.php
| Method | Description |
|---|---|
compare() | Compare metrics across periods |
yearOverYear() | Year-over-year comparison |
quarterOverQuarter() | Quarter-over-quarter comparison |
monthOverMonth() | Month-over-month comparison |
customPeriods() | Custom period comparison |
saveComparison() | Save comparison configuration |
getSavedComparisons() | Get user's saved comparisons |
runSavedComparison() | Execute a saved comparison |
TrendAnalyzer: app/Services/Analytics/TrendAnalyzer.php
| Method | Description |
|---|---|
analyze() | Full trend analysis |
calculateTrend() | Determine trend direction/slope |
calculateStatistics() | Basic statistics |
calculateMovingAverages() | SMA and EMA |
forecast() | Generate predictions |
detectAnomalies() | Find unusual values |
detectSeasonality() | Identify patterns |
comparePeriods() | Period-by-period changes |
analyzeGrowth() | Growth metrics |
DrillDownService: app/Services/Analytics/DrillDownService.php
| Method | Description |
|---|---|
getHierarchies() | Get available hierarchies |
drillDown() | Drill into hierarchy level |
saveDrillPath() | Save drill path |
getSavedDrillPaths() | Get user's saved paths |
AnalyticsExportService: app/Services/Analytics/AnalyticsExportService.php
| Method | Description |
|---|---|
createExport() | Create export record |
processExport() | Process pending export |
exportToPdf() | Generate PDF export |
exportToExcel() | Generate Excel export |
exportToCsv() | Generate CSV export |
exportToJson() | Generate JSON export |
exportToImage() | Generate PNG/SVG export |
cleanupOldExports() | Remove expired exports |
ChartBuilder: app/Services/Reports/ChartBuilder.php
| Method | Description |
|---|---|
build() | Build any chart type |
buildSankeyChart() | Flow visualization |
buildFunnelChart() | Conversion funnel |
buildWaterfallChart() | Incremental changes |
buildBubbleChart() | 3D scatter plot |
buildSparklineChart() | Inline trend |
getChartTypes() | List all chart types |
Controllers
| Controller | Route Prefix | Description |
|---|---|---|
ComparisonController | /admin/analytics/comparisons | Period comparisons |
TrendController | /admin/analytics/trends | Trend analysis |
DrillDownController | /admin/analytics/drill-down | Drill-down exploration |
AnalyticsExportController | /admin/analytics/exports | Export management |
Routes
// Analytics routes (in web.php)
Route::prefix('admin/analytics')->middleware(['auth', 'admin'])->group(function () {
// Existing routes...
// Comparisons
Route::get('comparisons', [ComparisonController::class, 'index']);
Route::post('comparisons/compare', [ComparisonController::class, 'compare']);
Route::get('comparisons/year-over-year', [ComparisonController::class, 'yearOverYear']);
Route::get('comparisons/quarter-over-quarter', [ComparisonController::class, 'quarterOverQuarter']);
Route::get('comparisons/month-over-month', [ComparisonController::class, 'monthOverMonth']);
Route::resource('comparisons', ComparisonController::class)->only(['store', 'destroy']);
Route::post('comparisons/{comparison}/run', [ComparisonController::class, 'run']);
Route::patch('comparisons/{comparison}/toggle-pin', [ComparisonController::class, 'togglePin']);
// Exports
Route::get('exports', [AnalyticsExportController::class, 'index']);
Route::post('exports', [AnalyticsExportController::class, 'store']);
Route::get('exports/{export}', [AnalyticsExportController::class, 'show']);
Route::get('exports/{export}/download', [AnalyticsExportController::class, 'download']);
Route::delete('exports/{export}', [AnalyticsExportController::class, 'destroy']);
Route::get('exports/meta/formats', [AnalyticsExportController::class, 'formats']);
Route::get('exports/meta/types', [AnalyticsExportController::class, 'types']);
Route::post('exports/cleanup', [AnalyticsExportController::class, 'cleanup']);
// Drill-down
Route::get('drill-down', [DrillDownController::class, 'index']);
Route::get('drill-down/hierarchies', [DrillDownController::class, 'hierarchies']);
Route::post('drill-down/explore', [DrillDownController::class, 'drillDown']);
Route::post('drill-down/drill-into', [DrillDownController::class, 'drillInto']);
Route::post('drill-down/drill-up', [DrillDownController::class, 'drillUp']);
Route::post('drill-down/jump', [DrillDownController::class, 'jumpToLevel']);
Route::resource('drill-down/paths', DrillDownController::class)->only(['store', 'destroy']);
Route::get('drill-down/paths/{path}/load', [DrillDownController::class, 'load']);
Route::patch('drill-down/paths/{path}/toggle-bookmark', [DrillDownController::class, 'toggleBookmark']);
// Trends
Route::post('trends/analyze', [TrendController::class, 'analyze']);
Route::post('trends/trend', [TrendController::class, 'trend']);
Route::post('trends/statistics', [TrendController::class, 'statistics']);
Route::post('trends/moving-averages', [TrendController::class, 'movingAverages']);
Route::post('trends/forecast', [TrendController::class, 'forecast']);
Route::post('trends/anomalies', [TrendController::class, 'anomalies']);
Route::post('trends/seasonality', [TrendController::class, 'seasonality']);
Route::post('trends/growth', [TrendController::class, 'growth']);
Route::post('trends/periods', [TrendController::class, 'periods']);
});
Data Caching
Analytics queries are cached for performance:
// Cache revenue metrics for 1 hour
Cache::remember('analytics:revenue:' . $period, 3600, function () use ($start, $end) {
return $this->analyticsService->getRevenueMetrics($start, $end);
});
Cache Invalidation
Cache is cleared when relevant data changes:
// In Invoice observer
public function updated(Invoice $invoice): void
{
if ($invoice->wasChanged('status') && $invoice->status === 'paid') {
Cache::tags(['analytics', 'revenue'])->flush();
}
}
Related Features
Dependencies
| Feature | Relationship |
|---|---|
| Authorization | Admin access required |
| Invoicing | Revenue data source |
| Client Management | Client metrics |
| Project Management | Project metrics |
Complementary Features
| Feature | Description |
|---|---|
| Reports | Detailed data exports |
| Admin Dashboard | Overview dashboard |
| Activity Logging | Activity metrics |
Best Practices
For Data Accuracy
- Use consistent date ranges for comparisons
- Understand metric definitions
- Verify data sources before decisions
- Consider seasonality in trends
- Check anomaly context before acting
For Performance
- Cache expensive queries appropriately
- Use date range limits on large datasets
- Aggregate data for historical views
- Index analytical columns
- Use background jobs for exports
For Comparisons
- Compare like periods (same duration)
- Account for business changes between periods
- Use multiple metrics for context
- Consider external factors in analysis
For Drill-Down
- Save useful paths for repeated analysis
- Use breadcrumbs to navigate
- Apply filters at appropriate levels
- Export detail data for deep analysis
Troubleshooting
| Issue | Solution |
|---|---|
| Charts not loading | Check JavaScript console |
| Wrong numbers | Verify date range and filters |
| Slow dashboard | Reduce widgets, check cache |
| Missing data | Verify data exists in source |
| Export fails | Check storage permissions |
| Drill-down empty | Verify hierarchy has data |
| Trend insufficient | Need more data points |
See Also
- Reports - Detailed reporting
- Admin Dashboard - Overview
- Activity Logging - Activity tracking