
Customer Analytics
- 84 installs
- 41 repo stars
- Updated March 13, 2026
- finsilabs/awesome-ecommerce-skills
Analyze customer behavior with RFM scoring, purchase-frequency tracking, churn prediction, and cohort analysis to improve retention strategy.
About
A skill for turning order data into customer insights via RFM scoring, cohort retention, purchase frequency, and churn prediction. A developer uses it to identify loyal, at-risk, and high-value customers for retention.
- RFM scoring and cohort retention analysis
- Purchase-frequency tracking and churn prediction
Customer Analytics by the numbers
- 84 all-time installs (skills.sh)
- Ranked #860 of 2,064 Data Science & ML skills by installs in the Skillselion catalog
- Data as of Aug 3, 2026 (Skillselion catalog sync)
npx skills add https://github.com/finsilabs/awesome-ecommerce-skills --skill customer-analyticsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 84 |
|---|---|
| repo stars | ★ 41 |
| Last updated | March 13, 2026 |
| Repository | finsilabs/awesome-ecommerce-skills ↗ |
What it does
Analyze customer behavior with RFM scoring, purchase-frequency tracking, churn prediction, and cohort analysis to improve retention strategy.
Files
Customer Analytics
Overview
Customer analytics transforms raw order data into actionable insights about purchase patterns, lifecycle stages, and churn risk. The core analyses — RFM scoring, cohort retention, purchase frequency, and churn prediction — reveal which customers are loyal, which are at risk, and which channels produce the best long-term customers.
This skill guides you through running these analyses using your platform's built-in tools and dedicated analytics apps, with data warehouse approaches for stores that need deeper segmentation.
When to Use This Skill
- When the marketing team needs data-driven segments beyond simple demographic filters
- When calculating at-risk customer counts for quarterly business reviews
- When measuring the impact of loyalty programs on purchase frequency
- When identifying the acquisition channels that produce the highest-LTV customers
- When preparing customer health dashboards for account management or VIP programs
- When building cohort retention analysis to understand customer lifetime value trends
Core Instructions
Step 1: Choose the right tool for your platform
| Platform | Recommended Tool | What It Provides |
|---|---|---|
| Shopify | Klaviyo + Shopify's built-in customer segments | RFM-style segments, purchase frequency, CLV prediction, cohort reports |
| Shopify (advanced) | Lifetimely or Triple Whale | True cohort LTV, CLV by acquisition channel, retention curves |
| WooCommerce | Metorik | Customer segmentation, RFM analysis, cohort retention, churn identification |
| WooCommerce (email) | Klaviyo for WooCommerce | Behavioral segments + automated flows based on customer lifecycle stage |
| BigCommerce | Klaviyo for BigCommerce + Glew.io | Glew provides cohort analysis and CLV tracking natively for BigCommerce |
| All platforms (data-first) | Export to Google Looker Studio + BigQuery via Fivetran | Full SQL-based analysis; required for advanced RFM and cohort modeling |
Step 2: Set up customer segmentation on your platform
---
Shopify
Using Shopify's built-in customer segments (all plans):
1. Go to Customers → Segments 2. Shopify provides pre-built segments including:
- Abandoned checkout in the last 30 days
- Customers who have purchased more than X times
- Customers who haven't purchased in 90 days (at-risk segment)
- High-spend customers (based on total spend threshold)
3. Create custom segments using the query editor with filters like:
number_of_orders >= 3(loyal customers)days_since_last_order > 90(churn risk)total_spent > 500(high-value)
4. Export segments to CSV or sync directly to Klaviyo for email campaigns
Using Klaviyo for RFM segmentation on Shopify:
1. Install Klaviyo from the Shopify App Store 2. Klaviyo automatically syncs all historical and new Shopify order data 3. Go to Segments → Create Segment and build RFM-style segments using:
- Recency: "Has placed an order in the last X days"
- Frequency: "Number of orders is greater than X"
- Monetary: "Total amount spent is greater than $X"
4. Pre-built segment examples:
- Champions: Ordered in last 30 days + 3+ orders + $200+ lifetime spend
- At Risk: No order in 90–180 days + previously placed 2+ orders
- Lost: No order in 180+ days
5. Use these segments to trigger flows in Klaviyo: win-back campaigns for at-risk, VIP rewards for champions
Using Lifetimely for cohort LTV on Shopify:
1. Install Lifetimely from the Shopify App Store 2. Go to Lifetimely → Cohorts to see a month-by-month retention matrix: what percentage of customers from each acquisition cohort are still buying at months 1, 3, 6, 12 3. Go to Lifetimely → Channels to compare 12-month LTV by acquisition source (Google, Meta, organic, email) 4. Go to Lifetimely → Customer Segments to see RFM distribution and predicted CLV per customer
---
WooCommerce
Using Metorik:
1. Connect Metorik to your WooCommerce store via API 2. Go to Metorik → Customers to browse all customers with filters:
- Last order date (identify churned/at-risk)
- Total spent (identify high-value)
- Order count (identify one-time vs. repeat buyers)
3. Go to Metorik → Reports → Customer Cohorts to see retention by monthly acquisition cohort 4. Go to Metorik → Segments to create saved customer segments (equivalent to RFM groups); export segments as CSVs for Klaviyo or Mailchimp
Using Klaviyo for WooCommerce:
1. Install the Klaviyo for WooCommerce plugin 2. Klaviyo syncs WooCommerce customers and orders, enabling the same RFM segments described for Shopify above 3. Go to Klaviyo → Analytics → Cohort Analysis to see retention curves and predicted CLV by acquisition date
---
BigCommerce
1. BigCommerce Customer Groups: Go to Customers → Customer Groups — create groups based on purchase history, spend thresholds, and geographic criteria 2. Install Glew.io from the BigCommerce App Marketplace — provides cohort retention analysis, RFM scoring, and CLV by acquisition channel 3. Install Klaviyo for BigCommerce for behavioral email segmentation and lifecycle automation
---
Step 3: Analyze purchase frequency and retention
Purchase frequency distribution (using any platform's export):
Export your customer order data to a CSV or Google Sheet and calculate:
- What % of customers have placed exactly 1 order?
- What % have placed 2–3 orders?
- What % have placed 4+ orders?
Industry benchmarks:
- Typical DTC brand: 60–70% of customers are one-time buyers
- Healthy subscription or consumable brand: 40–50% of customers reorder within 90 days
- Your second-purchase rate (% of first-time buyers who place a second order within 90 days) is the single most important leading indicator of long-term CLV
Cohort retention analysis:
A cohort retention grid shows what percentage of customers acquired in month X are still buying at months 1, 3, 6, 12:
- Shopify + Lifetimely: Available natively in the Cohorts view
- Klaviyo: Available under Analytics → Cohort Analysis
- Metorik: Available under Reports → Cohorts
- Manual (any platform): Export all orders to Google Sheets; create a pivot table with acquisition month as rows and "months since first order" as columns
What good retention looks like:
| Months After First Order | Minimum Viable | Healthy | Excellent |
|---|---|---|---|
| Month 1 (second purchase rate) | 15% | 25% | 40%+ |
| Month 3 retention | 10% | 20% | 35%+ |
| Month 12 retention | 5% | 15% | 30%+ |
Step 4: Identify at-risk customers and act
At-risk customer identification:
The simplest at-risk definition: customers who previously ordered multiple times but have not ordered in longer than their typical interval.
- Shopify Segments:
number_of_orders > 1 AND days_since_last_order > 90 - Klaviyo: Create a "Winback" segment: "Has placed more than 1 order" AND "Has not placed an order in the last 90 days"
- Metorik: Use the "Customers at risk of churning" pre-built filter
Action by segment:
| Segment | Recommended Action |
|---|---|
| Champions (recent, frequent, high-spend) | Invite to VIP program; early access to new products |
| Loyal but cooling (frequent but not recent) | Targeted win-back email with personalized product recommendations |
| At risk (inactive > 90 days, multiple prior orders) | Win-back sequence: reminder → small incentive → final offer |
| One-time buyers | Second purchase campaign; show complementary products |
| Lost (inactive > 180 days) | Low-cost re-engagement attempt; if no response, suppress to reduce email costs |
Best Practices
- Run RFM scoring monthly — customer order history changes continuously; stale segments lead to wrong targeting
- Track second-purchase rate as a leading indicator — the conversion from one-time to repeat buyer is the highest-leverage retention metric; it predicts CLV far in advance of any LTV model
- Segment CLV by acquisition channel — customers from organic search, paid social, and email/SMS referrals often have dramatically different LTVs; measure them separately to inform budget allocation
- Build alerts for segment migration — when the "at risk" segment grows week over week, it signals a retention problem needing immediate action; set up alerts in Klaviyo or Lifetimely
- Flag seasonal buyers separately — customers who only buy in Q4 should not be marked as churned in Q2; apply a seasonal buyer tag before running churn analysis
Common Pitfalls
| Problem | Solution |
|---|---|
| RFM segments shift dramatically after a sale event | Use a rolling 90-day window for scoring; recent sales spikes should not permanently elevate scores for customers who only responded to a discount |
| Acquisition channel CLV analysis not accounting for multi-touch | Use first-touch attribution for CLV by channel — the channel that introduced the customer, not the channel that converted the last order |
| Cohort retention shows 0% after month 6 | Check whether the query or export is filtering out cohorts that do not have 6 months of data yet; exclude cohorts acquired in the last 6 months from long-term retention views |
| Customer count in segments does not match email list size | Some customers in your store may not be subscribed to email; segment by customer (order-based) separately from email list (consent-based) |
| Win-back campaigns going to customers who bought recently | Ensure segment filters are current — sync order data before running segment exports; stale data causes emails to go to wrong contacts |
Related Skills
- @customer-segmentation
- @attribution-modeling
- @sales-reporting-dashboard
- @ab-testing-ecommerce
- @unit-economics-tracking
{
"context": "Tests whether the agent uses correct SQL patterns for acquisition channel quality analysis (COALESCE for direct fallback, LATERAL join for 12-month CLV, 18-month customer filter, first-touch attribution join) and cohort retention (DATE_TRUNC month grouping, HAVING filter for mature cohorts), plus correct documentation of attribution model and second-purchase rate as a leading indicator.",
"type": "weighted_checklist",
"checklist": [
{
"name": "COALESCE for direct",
"max_score": 8,
"description": "channel_quality.sql uses COALESCE(oa.source, 'direct') or equivalent to label customers with no attribution record as 'direct'"
},
{
"name": "LATERAL join for CLV",
"max_score": 9,
"description": "channel_quality.sql uses a LATERAL join (or equivalent correlated subquery) to compute per-customer 12-month revenue"
},
{
"name": "18-month customer filter",
"max_score": 9,
"description": "channel_quality.sql restricts the analysis to customers acquired in the last 18 months (NOT all-time customers)"
},
{
"name": "12-month CLV window",
"max_score": 8,
"description": "The 12-month CLV computation counts only orders within 12 months of the customer's acquisition date (not all orders ever)"
},
{
"name": "Repeat purchase rate",
"max_score": 7,
"description": "channel_quality.sql includes a metric for the percentage of customers who ordered more than once (repeat purchase rate)"
},
{
"name": "First-touch attribution join",
"max_score": 8,
"description": "channel_quality.sql attributes each customer to the channel of their FIRST order (not last or any order)"
},
{
"name": "Attribution model labeled",
"max_score": 7,
"description": "analysis_notes.md explicitly states which attribution model (first-touch or last-touch) is used"
},
{
"name": "Excludes cancelled/refunded",
"max_score": 10,
"description": "Both SQL files exclude orders with status 'cancelled' and 'refunded'"
},
{
"name": "DATE_TRUNC cohort month",
"max_score": 7,
"description": "cohort_retention.sql uses DATE_TRUNC('month', ...) to group customers into monthly cohorts"
},
{
"name": "HAVING mature cohorts only",
"max_score": 9,
"description": "cohort_retention.sql uses a HAVING clause or WHERE filter to exclude cohorts that haven't had enough months to measure retention at the period being reported (e.g. HAVING cohort_month <= NOW() - INTERVAL 'N months')"
},
{
"name": "Second-purchase rate as leading indicator",
"max_score": 9,
"description": "analysis_notes.md identifies second-purchase rate (or repeat purchase rate / one-time-to-repeat conversion) as a key leading indicator of customer lifetime value"
},
{
"name": "Cohort analysis by cohort month",
"max_score": 9,
"description": "analysis_notes.md or channel_quality.sql notes that channel performance should be compared by cohort month (not across all-time customers) to avoid comparing different time periods"
}
]
}
Marketing Channel ROI and Cohort Retention Report
Problem Description
Trove Market, an online home goods retailer, is heading into its annual marketing budget review. The CMO wants hard data to decide where to invest next year: which acquisition channels are actually bringing in customers who stick around and spend, not just one-time bargain hunters? The analytics team is being asked to produce two analyses: (1) a channel quality comparison showing revenue contribution per acquired customer, and (2) a cohort retention matrix showing what percentage of each month's new customers returned to buy in subsequent months.
The database is PostgreSQL and has four tables: customers (id, email, first_name, created_at), orders (id, customer_id, created_at, subtotal_cents, status), order_attribution (order_id, source), and customer_rfm_scores (for materialized scores). Not all orders are valid — cancelled and refunded orders should be excluded. Some customers came in via paid channels, others organically, and some with no tracking data at all.
The team has been burned before by analysis that mixed together channels from very different time periods — a channel that looked great three years ago may now be bringing in low-quality customers. They also want to understand which specific months are showing weak long-term retention so they can investigate what was happening with those cohorts.
Output Specification
Produce two SQL files:
`channel_quality.sql` — Queries CLV by acquisition channel for recently acquired customers, including:
- Acquisition source (with a fallback label for untracked customers)
- Number of customers acquired per channel
- Average and median 12-month revenue per customer
- Average order count per customer
- Repeat purchase rate (percentage who ordered more than once)
`cohort_retention.sql` — A monthly cohort retention matrix showing:
- The cohort month (month of first purchase)
- Cohort size
- How many months after first purchase each data point represents
- Count of retained customers and retention percentage at each period
- Only includes cohorts that have had sufficient time to accumulate data (exclude cohorts too recent to have meaningful retention at the period being measured)
Also produce `analysis_notes.md` documenting:
- What time window was used for the channel analysis and why
- Whether first-touch or last-touch attribution is used, labeled clearly
- What metric the team should track as the leading indicator of customer lifetime value
{
"context": "Tests whether the agent implements churn scoring using the specified TypeScript interface shape, the correct formulas for single-purchase vs multi-purchase customers (linear growth vs z-score sigmoid), seasonal purchase pattern handling, monthly validation recommendations, and the correct high-value action thresholds.",
"type": "weighted_checklist",
"checklist": [
{
"name": "CustomerChurnRisk interface",
"max_score": 10,
"description": "Defines a TypeScript type/interface for churn risk that includes: churnScore (number 0-1), churnCategory ('low'|'medium'|'high'|'churned'), daysSinceLastOrder, avgPurchaseIntervalDays, and predictedNextOrderDate (Date|null)"
},
{
"name": "Single-purchase linear formula",
"max_score": 10,
"description": "For customers with exactly one order, computes churnScore using a formula based on days since purchase (increasing linearly), capped at a maximum value (e.g. 0.95)"
},
{
"name": "Multi-purchase z-score sigmoid",
"max_score": 10,
"description": "For repeat customers, computes churnScore using a sigmoid function applied to a z-score (standard deviations past due relative to average purchase interval)"
},
{
"name": "Std dev floor",
"max_score": 8,
"description": "Uses Math.max(1, stdDev) or equivalent to prevent division by zero when computing the z-score for multi-purchase customers"
},
{
"name": "churnScore clamped",
"max_score": 6,
"description": "churnScore is clamped to a [0.01, 0.99] or similar range (does NOT allow exactly 0 or 1 for multi-purchase customers)"
},
{
"name": "Category thresholds",
"max_score": 7,
"description": "Uses 0.75 (or similar) as the high/medium boundary and 0.45 (or similar) as the medium/low boundary for multi-purchase customers"
},
{
"name": "Excludes cancelled/refunded",
"max_score": 7,
"description": "Filters out cancelled and refunded orders before computing purchase history metrics"
},
{
"name": "Seasonal pattern flag",
"max_score": 8,
"description": "churn-design.md or code includes a mention of a seasonal purchase pattern flag or logic to avoid marking seasonal buyers as churned during their off-season"
},
{
"name": "Monthly validation plan",
"max_score": 8,
"description": "churn-design.md recommends a monthly validation process comparing predicted scores from a past period to actual churn outcomes"
},
{
"name": "Personal outreach threshold",
"max_score": 8,
"description": "getHighValueAtRiskCustomers returns a recommendedAction of 'personal_outreach' for customers above a lifetime spend threshold and 'win_back_email' for others"
},
{
"name": "Ordered by lifetime value",
"max_score": 8,
"description": "getHighValueAtRiskCustomers orders results by lifetime spend/value descending (highest value customers first)"
},
{
"name": "Predicted next order date",
"max_score": 10,
"description": "For multi-purchase customers, computes a predictedNextOrderDate as lastOrderDate + avgInterval"
}
]
}
Customer Churn Risk Scoring Service
Problem Description
Pulse Commerce, a subscription-to-repurchase health supplements brand, has been losing high-value customers without warning. The customer success team only finds out a customer has churned after they've already gone 3 months without a purchase, at which point win-back campaigns have a very low success rate. The VP of Customer Success wants a proactive system that flags customers before they churn so the CS team can intervene with targeted offers.
The engineering team uses TypeScript and has a database abstraction layer (db) already set up. Order records have a createdAt timestamp and a status field (orders can be 'cancelled', 'refunded', or valid). The team's data scientists have noted that churn behavior is fundamentally different for first-time buyers (who may simply never return) versus repeat customers (whose churn can be detected by looking at whether they've gone unusually long past their normal repurchase interval).
The CS team also maintains a customerChurnScores table in the database where scores can be persisted for lookup, and they want to surface the top at-risk high-value customers to the CS team daily. The business has a mix of customers who only buy seasonally (e.g., gift buyers) and regular repeat purchasers, and the system should account for this to avoid false alarms.
Output Specification
Produce a TypeScript file churn-scoring.ts that implements: 1. A function scoreCustomerChurnRisk(customerId: string) that computes a churn risk score and category for a single customer 2. A function getHighValueAtRiskCustomers(limit?: number) that retrieves the top at-risk customers ordered by lifetime value
Also produce churn-design.md that explains:
- The scoring formula used for first-time buyers vs repeat buyers
- How the system avoids false positives for seasonal purchasers
- The recommended validation process to ensure the model stays accurate over time
- What action the system recommends based on lifetime value tier
{
"context": "Tests whether the agent builds an RFM scoring pipeline using the correct SQL patterns: NTILE(5) window functions with correct ordering, the specified segment label set, proper exclusion of cancelled/refunded orders, cents-to-dollars conversion, and appropriate architecture recommendations for production scheduling.",
"type": "weighted_checklist",
"checklist": [
{
"name": "NTILE for R score",
"max_score": 8,
"description": "Uses NTILE(5) OVER (ORDER BY recency_days DESC) or equivalent to compute the recency score (most recent = highest score)"
},
{
"name": "NTILE for F score",
"max_score": 8,
"description": "Uses NTILE(5) OVER (ORDER BY frequency ASC) or equivalent to compute the frequency score"
},
{
"name": "NTILE for M score",
"max_score": 8,
"description": "Uses NTILE(5) OVER (ORDER BY monetary ASC) or equivalent to compute the monetary score"
},
{
"name": "Excludes cancelled/refunded",
"max_score": 8,
"description": "Filters out orders with status 'cancelled' and 'refunded' before computing any metrics"
},
{
"name": "Cents conversion",
"max_score": 6,
"description": "Divides subtotal_cents by 100.0 (not 100) to convert order amounts to currency units"
},
{
"name": "champions segment",
"max_score": 7,
"description": "Assigns the label 'champions' for customers with high scores on all three dimensions (r>=4, f>=4, m>=4 or equivalent)"
},
{
"name": "cannot_lose_them segment",
"max_score": 7,
"description": "Assigns the label 'cannot_lose_them' (or cannot_lose_them) for high-value customers with low recency"
},
{
"name": "at_risk segment",
"max_score": 7,
"description": "Assigns the label 'at_risk' for customers with low recency but moderate frequency"
},
{
"name": "lost segment",
"max_score": 7,
"description": "Assigns the label 'lost' for customers with the lowest recency and low frequency"
},
{
"name": "All 8 segment labels",
"max_score": 8,
"description": "The query uses all 8 named segments: champions, loyal_customers, recent_customers, potential_loyalists, cannot_lose_them, at_risk, lost, other"
},
{
"name": "Nightly batch recommendation",
"max_score": 8,
"description": "notes.md recommends running the query on a nightly/daily schedule (not weekly or on-demand)"
},
{
"name": "Customer join",
"max_score": 8,
"description": "Joins to the customers table to include email and first_name in the output"
},
{
"name": "Recency in days",
"max_score": 10,
"description": "Computes recency as elapsed days (difference between now and last order date), not as a raw timestamp"
}
]
}
Customer Segmentation for Loyalty Program Targeting
Problem Description
Finova, a mid-size direct-to-consumer fashion retailer, is launching a revamped loyalty program next quarter. The marketing team currently treats all customers the same — everyone gets the same newsletter, the same discounts, and the same reactivation emails. The head of retention has seen competitors use data-driven segmentation to dramatically improve campaign ROI and wants Finova to do the same.
The data team has a PostgreSQL database with two relevant tables: orders (columns: id, customer_id, created_at, subtotal_cents, status) and customers (columns: id, email, first_name). Not all orders should count toward analytics — some were cancelled or refunded. The team wants a SQL-based scoring pipeline that keeps segments up to date so marketing always has fresh data to target.
The analytics lead wants a self-contained SQL file that can be scheduled as a cron job. It should score every customer on how recently they purchased, how often they purchase, and how much they spend — then classify each into a named segment that marketing can act on directly. The results should reference each customer's email and first name for easy export to the marketing automation tool.
Output Specification
Produce a file rfm_pipeline.sql containing the complete SQL query that:
- Computes recency, frequency, and monetary scores for each customer
- Assigns each customer a percentile-based score from 1–5 on each dimension
- Classifies each customer into a named segment based on their scores
- Returns customer contact info alongside analytics fields
Also produce a short notes.md explaining:
- How the query handles problematic order statuses
- What the segment names represent and when they are assigned
- A recommendation for the appropriate scheduling cadence for this query and why it matters
{
"name": "finsi/customer-analytics",
"version": "0.1.0",
"summary": "RFM scoring, purchase frequency, churn prediction, and segment analysis",
"skills": {
"customer-analytics": {
"path": "SKILL.md"
}
}
}