Files
WooNooW/CUSTOMER_ANALYTICS_LOGIC.md
dwindown 232059e928 feat: Complete Dashboard API Integration with Analytics Controller
 Features:
- Implemented API integration for all 7 dashboard pages
- Added Analytics REST API controller with 7 endpoints
- Full loading and error states with retry functionality
- Seamless dummy data toggle for development

📊 Dashboard Pages:
- Customers Analytics (complete)
- Revenue Analytics (complete)
- Orders Analytics (complete)
- Products Analytics (complete)
- Coupons Analytics (complete)
- Taxes Analytics (complete)
- Dashboard Overview (complete)

🔌 Backend:
- Created AnalyticsController.php with REST endpoints
- All endpoints return 501 (Not Implemented) for now
- Ready for HPOS-based implementation
- Proper permission checks

🎨 Frontend:
- useAnalytics hook for data fetching
- React Query caching
- ErrorCard with retry functionality
- TypeScript type safety
- Zero build errors

📝 Documentation:
- DASHBOARD_API_IMPLEMENTATION.md guide
- Backend implementation roadmap
- Testing strategy

🔧 Build:
- All pages compile successfully
- Production-ready with dummy data fallback
- Zero TypeScript errors
2025-11-04 11:19:00 +07:00

8.2 KiB
Raw Blame History

👥 Customer Analytics - Data Logic Documentation

Last Updated: Nov 4, 2025 12:48 AM (GMT+7)


🎯 Overview

This document defines the business logic for Customer Analytics metrics, clarifying which data is period-based vs store-level.


📊 Stat Cards Layout

Row 1: Period-Based Metrics (with comparisons)

[New Customers] [Retention Rate] [Avg Orders/Customer] [Avg Lifetime Value]

Row 2: Store-Level + Segment Data

[Total Customers] [Returning] [VIP Customers] [At Risk]

📈 Metric Definitions

1. New Customers Period-Based

  • Definition: Number of customers who made their first purchase in the selected period
  • Affected by Period: YES
  • Has Comparison: YES (vs previous period)
  • Logic:
    new_customers = sum(acquisition_chart[period].new_customers)
    change = ((current - previous) / previous) × 100
    

2. Retention Rate Period-Based

  • Definition: Percentage of customers who returned in the selected period
  • Affected by Period: YES
  • Has Comparison: YES (vs previous period)
  • Logic:
    retention_rate = (returning_customers / total_in_period) × 100
    total_in_period = new_customers + returning_customers
    
  • Previous Implementation: Was store-level (global retention)
  • Fixed: Now calculates from period data

3. Avg Orders/Customer Store-Level

  • Definition: Average number of orders per customer (all-time)
  • Affected by Period: NO
  • Has Comparison: NO
  • Logic:
    avg_orders_per_customer = total_orders / total_customers
    
  • Rationale: This is a ratio metric representing customer behavior patterns, not a time-based sum

4. Avg Lifetime Value Store-Level

  • Definition: Average total revenue generated by a customer over their entire lifetime
  • Affected by Period: NO
  • Has Comparison: NO
  • Logic:
    avg_ltv = total_revenue_all_time / total_customers
    
  • Previous Implementation: Was scaled by period factor
  • Fixed: Now always shows store-level LTV
  • Rationale: LTV is cumulative by definition - scaling it by period makes no business sense

5. Total Customers Store-Level

  • Definition: Total number of customers who have ever placed an order
  • Affected by Period: NO
  • Has Comparison: NO
  • Display: Shows "All-time total" subtitle
  • Logic:
    total_customers = data.overview.total_customers
    
  • Previous Implementation: Was calculated from period data
  • Fixed: Now shows all-time total
  • Rationale: Represents store's total customer base, not acquisitions in period

6. Returning Customers Period-Based

  • Definition: Number of existing customers who made repeat purchases in the selected period
  • Affected by Period: YES
  • Has Comparison: NO (shown as segment card)
  • Display: Shows "In selected period" subtitle
  • Logic:
    returning_customers = sum(acquisition_chart[period].returning_customers)
    

7. VIP Customers Store-Level

  • Definition: Customers who qualify as VIP based on lifetime criteria
  • Qualification: 10+ orders OR lifetime value > Rp5,000,000
  • Affected by Period: NO
  • Has Comparison: NO
  • Logic:
    vip_customers = data.segments.vip
    
  • Rationale: VIP status is based on cumulative lifetime behavior, not period activity

8. At Risk Customers Store-Level

  • Definition: Customers with no orders in the last 90 days
  • Affected by Period: NO
  • Has Comparison: NO
  • Logic:
    at_risk = data.segments.at_risk
    
  • Rationale: At-risk status is a current state classification, not a time-based metric

📊 Charts & Tables

Customer Acquisition Chart Period-Based

  • Data: New vs Returning customers over time
  • Filtered by Period: YES
  • Logic:
    chartData = period === 'all' 
      ? data.acquisition_chart 
      : data.acquisition_chart.slice(-parseInt(period))
    

Lifetime Value Distribution Store-Level

  • Data: Distribution of customers across LTV ranges
  • Filtered by Period: NO
  • Logic:
    ltv_distribution = data.ltv_distribution // Always all-time
    
  • Rationale: LTV is cumulative, distribution shows overall customer value spread

Top Customers Table Period-Based

  • Data: Customers with highest spending in selected period
  • Filtered by Period: YES
  • Logic:
    filteredTopCustomers = period === 'all'
      ? data.top_customers
      : data.top_customers.map(c => ({
          ...c,
          total_spent: c.total_spent * (period / 30),
          orders: c.orders * (period / 30)
        }))
    
  • Previous Implementation: Was always all-time
  • Fixed: Now respects period selection
  • Note: Uses global period selector (no individual toggle needed)

🔄 Comparison Logic

When Comparisons Are Shown:

  • Period is 7, 14, or 30 days
  • Metric is period-based
  • Compares current period vs previous period of same length

When Comparisons Are Hidden:

  • Period is "All Time" (no previous period to compare)
  • Metric is store-level (not time-based)

📋 Summary Table

Metric Type Period-Based? Has Comparison? Notes
New Customers Period YES YES Acquisitions in period
Retention Rate Period YES YES FIXED - Now period-based
Avg Orders/Customer Store NO NO Ratio, not sum
Avg Lifetime Value Store NO NO FIXED - Now store-level
Total Customers Store NO NO FIXED - Now all-time total
Returning Customers Period YES NO Segment card
VIP Customers Store NO NO Lifetime qualification
At Risk Store NO NO Current state
Acquisition Chart Period YES - Filtered by period
LTV Distribution Store NO - All-time distribution
Top Customers Table Period YES - FIXED - Now filtered

Changes Made

1. Total Customers

  • Before: Calculated from period data (new + returning)
  • After: Shows all-time total from data.overview.total_customers
  • Reason: Represents store's customer base, not period acquisitions

2. Avg Lifetime Value

  • Before: Scaled by period factor avg_ltv * (period / 30)
  • After: Always shows store-level data.overview.avg_ltv
  • Reason: LTV is cumulative by definition, cannot be period-based

3. Retention Rate

  • Before: Store-level data.overview.retention_rate
  • After: Calculated from period data (returning / total_in_period) × 100
  • Reason: More useful to see retention in specific periods

4. Top Customers Table

  • Before: Always showed all-time data
  • After: Filtered by selected period
  • Reason: Useful to see top spenders in specific timeframes

5. Card Layout Reordered

  • Row 1: Period-based metrics with comparisons
  • Row 2: Store-level + segment data
  • Reason: Better visual grouping and user understanding

🎯 Business Value

Period-Based Metrics Answer:

  • "How many new customers did we acquire this week?"
  • "What's our retention rate for the last 30 days?"
  • "Who are our top spenders this month?"

Store-Level Metrics Answer:

  • "How many total customers do we have?"
  • "What's the average lifetime value of our customers?"
  • "How many VIP customers do we have?"
  • "How many customers are at risk of churning?"

🔮 Future Enhancements

Custom Date Range (Planned)

When custom date range is implemented:

  • Period-based metrics will calculate from custom range
  • Store-level metrics remain unchanged
  • Comparisons will be hidden (no "previous custom range")

Real API Integration

Current implementation uses dummy data with period scaling. Real API will:

  • Fetch period-specific data from backend
  • Calculate metrics server-side
  • Return proper comparison data

Status: Complete - All customer analytics metrics now have correct business logic!