Customer Analytics
Understand customer behavior, value, and patterns with transaction data
Customer analytics help you identify high-value customers, understand purchasing behavior, and create targeted retention strategies. These examples demonstrate how to calculate customer lifetime value, segment customers by behavior, and track cohort performance. Use these patterns to build a data-driven understanding of your customer base.
Customer analytics aggregate transaction data by customer to reveal patterns and value. Always consider time windows when analyzing customer behavior - a customer's lifetime value changes over time, and recent activity may indicate changing behavior patterns.
Prerequisites
Before building customer analytics, understand:
Customer Lifetime Value
Calculate comprehensive customer value metrics.
What this query does
This query calculates customer lifetime value by grouping all processed payment transactions by customer and computing total spend, average order value, and purchase frequency for each customer, ordered by total value.
Query components:
| Component | Description |
|---|---|
| Select | Customer ID, sum, average, and count aggregates |
| Filter | Processed payment transactions |
| Group | Results by customer |
| Order | By total spend (highest first) |
| Limit | Top customers (e.g., 50 or 100) |
Query breakdown
results = (
pl.Transaction.select(
pl.attr.sender.account_id, # Grouping dimension
pl.attr.amount.sum(), # Total lifetime spend
pl.attr.amount.avg(), # Average order value
pl.attr.id.count(), # Purchase frequency
)
.filter_by(pl.attr.type == "payment", pl.attr.status.value == "processed")
.group_by(pl.attr.sender.account_id)
.order_by(pl.attr.sender.account_id)
.limit(50)
.all()
) # 50 aggregated customer rowsResult structure:
[
{
"customer_id": "cust_abc123",
"sum(amount)": 15750.0,
"avg(amount)": 525.0,
"count(id)": 30
},
{
"customer_id": "cust_def456",
"sum(amount)": 12300.0,
"avg(amount)": 410.0,
"count(id)": 30
}
]Analysis insights:
- High total, high average: Premium customers making large purchases
- High total, low average: Frequent buyers with smaller orders
- Low total, high average: Infrequent but valuable purchases
- High count, low average: Loyal customers with small transactions
Extended analysis
Calculate customer tiers:
# Define tier thresholds
PLATINUM_THRESHOLD = 10000
GOLD_THRESHOLD = 5000
SILVER_THRESHOLD = 1000
for customer in results:
total_spend = customer["sum(amount)"]
if total_spend >= PLATINUM_THRESHOLD:
tier = "Platinum"
elif total_spend >= GOLD_THRESHOLD:
tier = "Gold"
elif total_spend >= SILVER_THRESHOLD:
tier = "Silver"
else:
tier = "Bronze"
print(f"{customer['sender.account_id']}: {tier} - ${total_spend:,.2f}")Identify at-risk customers:
Calculate purchase frequency distribution:
from collections import Counter
# Group customers by purchase frequency
frequency_dist = Counter()
for customer in results:
count = customer["count(id)"]
frequency_dist[count] += 1
print("Purchase Frequency Distribution:")
for frequency, num_customers in sorted(frequency_dist.items()):
print(f"{frequency} purchases: {num_customers} customers")Customer Segmentation Patterns
Common patterns for segmenting customers by behavior.
Recency, Frequency, Monetary analysis for customer segmentation:
Track customers by signup month and analyze retention:
Analyze new customer acquisition vs returning customer revenue:
Customer Behavior Analysis
Understand purchasing patterns and preferences.
Calculate average days between purchases for each customer:
Analyze when customers make purchases:
Identify preferred payment methods by customer:
Customer Retention Metrics
Track and measure customer retention.
Calculate cohort retention rates:
Identify customers at risk of churning:
Best Practices
Tips for effective customer analytics.
Customer behavior changes over time:
Count provides context for total spend:
# Good: Includes context
complete = (
pl.Transaction.select(
pl.attr.sender.account_id,
pl.attr.amount.sum(), # Total spend
pl.attr.id.count(), # Number of transactions
pl.attr.amount.avg(), # Average order value
)
.group_by(pl.attr.sender.account_id)
.all()
)
# Incomplete: Missing context
incomplete = (
pl.Transaction.select(
pl.attr.sender.account_id,
pl.attr.amount.sum(), # Just total - need frequency too
)
.group_by(pl.attr.sender.account_id)
.all()
)Recent behavior predicts future behavior:
# Always include last transaction date
ltv_with_recency = (
pl.Transaction.select(
pl.attr.sender.account_id,
pl.attr.amount.sum(),
pl.attr.id.count(),
pl.attr.created_at.max(), # Last transaction date
pl.attr.created_at.min(), # First transaction date
)
.filter_by(pl.attr.type == "payment", pl.attr.status.value == "processed")
.group_by(pl.attr.sender.account_id)
.all()
)Different customer segments need different strategies:
Next Steps
Explore related reporting topics
Revenue Reports
Analyze revenue trends and financial performance with Revenue Reports documentation, track monthly revenue trends, and build multi-dimensional revenue analysis across payment methods and time periods.
Query Mechanics
Deep dive into query building techniques with Building Report Queries guide, master aggregate functions and grouping operations, and optimize complex analytics queries for performance.