
Customer Retention Engine
- 71 installs
- 41 repo stars
- Updated March 13, 2026
- finsilabs/awesome-ecommerce-skills
Build automated retention campaigns that detect at-risk customers by repurchase cadence and intervene with tiered offers before they lapse.
About
Sets up proactive churn-prevention flows in Klaviyo or AutomateWoo using predicted next-order dates and per-tier incentives. A developer uses it when repeat purchase rate declines or too many customers only buy once.
- Churn-threshold table by product category (consumables, apparel, home goods)
- Klaviyo/AutomateWoo flows plus custom Klaviyo API order-event tracking
Customer Retention Engine by the numbers
- 71 all-time installs (skills.sh)
- Ranked #512 of 853 Sales & Marketing 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-retention-engineAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 71 |
|---|---|
| repo stars | ★ 41 |
| Last updated | March 13, 2026 |
| Repository | finsilabs/awesome-ecommerce-skills ↗ |
What it does
Build automated retention campaigns that detect at-risk customers by repurchase cadence and intervene with tiered offers before they lapse.
Files
Customer Retention Engine
Overview
Acquiring a new customer costs 5–7x more than retaining an existing one. A retention engine identifies customers who show declining engagement — reduced purchase frequency, decreasing order values, browsing without buying — and intervenes with personalized campaigns before they lapse. Klaviyo and AutomateWoo can build these workflows with no custom code using predictive analytics built into the platform.
Note: For reactivating already-lapsed customers, see @win-back-reactivation. This skill focuses on proactive churn prevention before customers lapse.
When to Use This Skill
- When repeat purchase rate is declining month-over-month
- When a significant percentage of customers only ever purchase once
- When you want to proactively contact customers before they go fully dormant
- When building a post-purchase nurture program beyond the first 30 days
- When needing to identify which customers are worth offering a discount vs. which will repurchase anyway
Core Instructions
Step 1: Choose the right tool for your platform
| Platform | Recommended Tool | Why |
|---|---|---|
| Shopify | Klaviyo | Klaviyo's predictive analytics automatically calculates expected next purchase date and churn risk for every customer; no manual scoring needed |
| WooCommerce | AutomateWoo ($99/yr) | Deep WooCommerce integration, "Customer win-back" workflow type, RFM segmentation built in |
| BigCommerce | Klaviyo or Omnisend | Both integrate natively with BigCommerce order events and offer predictive churn scoring |
| Custom / Headless | Klaviyo (via API) | Send order events to Klaviyo; use their predictive analytics to identify at-risk customers |
Step 2: Define your churn threshold
Churn timing depends on your product's natural repurchase cycle:
| Product Category | Expected Repurchase Cycle | At-Risk Threshold | Churned Threshold |
|---|---|---|---|
| Consumables (skincare, supplements) | 30–60 days | 60+ days since last order | 120+ days |
| Apparel/fashion | 60–90 days | 90+ days | 180+ days |
| Home goods | 90–180 days | 180+ days | 365+ days |
| Electronics accessories | 120–365 days | 180+ days | 365+ days |
In Klaviyo, go to Analytics → Predictive Analytics to see Klaviyo's automatically calculated churn risk for your customer base. Klaviyo uses your actual order history to set these thresholds — no manual calculation needed.
Step 3: Build retention flows
---
Shopify with Klaviyo
Flow 1: Early warning — customers approaching their expected repurchase date
1. Go to Klaviyo → Flows → Create Flow → Start from Scratch 2. Set trigger: Metric → Expected Date of Next Order is in 7 days
- Klaviyo calculates this automatically using predictive analytics
3. Add an email action with subject line: "Your favorites are waiting for you"
- Include: personalized product recommendations based on past purchases
- Use the
{{ person.predicted_next_purchase_date }}variable to acknowledge timing
4. Wait 3 days → Add a conditional: "Has placed an order since flow start?" → If No: send a follow-up email
Flow 2: High-value at-risk customers — personalized offer
1. Create a new flow triggered by: Segment → "High-Value At-Risk" segment (configure segment below) 2. Email: personalized exclusive offer (free shipping or 15% off for top-tier; no discount for mid-tier) 3. Wait 5 days → If no purchase: SMS follow-up (for SMS-consented customers)
Create the "High-Value At-Risk" segment in Klaviyo: 1. Go to Klaviyo → Segments → Create Segment 2. Conditions:
Predicted Churn RiskequalsHighORMid- AND
Total Customer Value(Historic CLV) greater than $150 - AND
Has not placed order in last 60 days
3. Save as "High-Value At-Risk"
Flow 3: One-time buyer reminder
1. Create a flow triggered by: Metric → Placed Order 2. Wait 45 days 3. Check: "Total number of orders equals 1" → If yes: 4. Email: "Based on your [product name] purchase, you might love these..." with 3–4 complementary product recommendations 5. Wait 14 days → If still only 1 order: send final email with 10% welcome-back discount
---
WooCommerce with AutomateWoo
1. Go to AutomateWoo → Workflows → Add Workflow 2. Set trigger: Customer → Win Back
- AutomateWoo has a built-in "Customer Win Back" trigger that fires at configurable intervals after last purchase
3. Set timing rules:
- Workflow A: 45 days since last purchase — send personalized recommendations email
- Workflow B: 75 days since last purchase — send exclusive offer email with discount
4. Add a rule to each workflow: "Customer has not purchased since workflow was created" — auto-cancels on conversion 5. For VIP customers: add a rule "Customer total spend > $500" to route to a separate workflow with better offers
AutomateWoo also includes built-in RFM segmentation — go to AutomateWoo → Reports → RFM Analysis to see your customer segments visually.
---
BigCommerce
1. Install Klaviyo from the BigCommerce App Marketplace 2. Klaviyo automatically syncs all BigCommerce order history 3. Follow the same Klaviyo flow setup described in the Shopify section above 4. BigCommerce order events trigger Klaviyo flows in real-time after the integration is connected
---
Custom / Headless
Send order events to Klaviyo's API to trigger retention flows:
// Send order event to Klaviyo when an order is completed
async function trackKlaviyoOrder(order: Order) {
await fetch('https://a.klaviyo.com/api/events/', {
method: 'POST',
headers: {
'Authorization': `Klaviyo-API-Key ${process.env.KLAVIYO_PRIVATE_KEY}`,
'Content-Type': 'application/json',
'revision': '2024-10-15',
},
body: JSON.stringify({
data: {
type: 'event',
attributes: {
metric: { data: { type: 'metric', attributes: { name: 'Placed Order' } } },
profile: { data: { type: 'profile', attributes: { email: order.customerEmail } } },
properties: {
$value: order.subtotal,
OrderId: order.id,
Items: order.lineItems.map(i => ({ ProductName: i.name, ItemPrice: i.price })),
},
},
},
}),
});
}Klaviyo's predictive analytics then automatically calculates churn risk and expected next purchase date based on these events.
Step 4: Configure intervention timing and incentives
Match interventions to customer value tier:
| Customer Tier | Intervention | Incentive |
|---|---|---|
| VIP (6+ orders, $500+ LTV) | Personalized email from "founder" | No discount — just recognition and early access |
| High-value (3–5 orders) | Email + SMS follow-up | Free shipping (protects margin) |
| Standard (1–2 orders) | Email sequence | 10% discount at final step only |
| One-time buyer | Email at 45 days | 10% off second order |
Step 5: Measure retention lift
Track these in Klaviyo or AutomateWoo dashboards:
| Metric | Target | Where to Find |
|---|---|---|
| Flow revenue | Growing month-over-month | Klaviyo → Flows → Analytics |
| Repeat purchase rate | > 25% of customers | Shopify: Analytics → Customer cohorts. Klaviyo: Segment analytics |
| At-risk segment shrinking | Decrease vs. prior month | Klaviyo → Segments → Size history |
| Churn rate | Declining | Compare lapsed customer count month-over-month |
Best Practices
- Never discount VIP customers reflexively — high-LTV customers who are slightly overdue may just be busy; a soft nudge without discount often works and protects margin
- Personalize based on actual purchase history — Klaviyo's dynamic product blocks automatically show recommendations based on what the customer has bought
- Set a contact frequency cap — in Klaviyo, use Smart Sending and set a daily message limit; at-risk customers should not receive more than one touchpoint per week
- Use Klaviyo's predictive analytics — do not manually calculate churn scores; Klaviyo computes expected next purchase date and churn risk automatically from your order data
- Close the loop with CS for high-value customers — for accounts over $1,000 LTV showing high churn risk, route to a customer success rep via Gorgias or Zendesk for personal outreach
Common Pitfalls
| Problem | Solution |
|---|---|
| Sending retention emails to customers who just bought | Add a flow filter in Klaviyo: "Has placed an order in last 7 days → skip"; AutomateWoo's "Customer has not purchased since workflow was created" rule handles this |
| Discounts eroding margin on customers who would have repurchased anyway | Use Klaviyo's predictive analytics: only offer discounts when predicted churn risk is "High"; skip for "Mid" and "Low" |
| Single-purchase customers receiving win-back messaging too early | Set a minimum 45-day window before treating a one-time buyer as at-risk |
| Flows sending to unsubscribed contacts | Klaviyo respects unsubscribes automatically; ensure your Shopify/WooCommerce unsubscribe events sync to Klaviyo in real-time |
Related Skills
- @lifecycle-marketing-automation
- @win-back-reactivation
- @loyalty-program-optimization
- @email-marketing-automation
- @email-list-segmentation
{
"context": "Tests whether the agent implements behavioral triggers at the correct thresholds, uses the correct lookback and product counts, withholds the right fraction of customers as a control group, calculates lift correctly, avoids aggressive discounting for VIP customers, and tracks unsubscribes separately.",
"type": "weighted_checklist",
"checklist": [
{
"name": "Inactivity trigger at 21 days",
"max_score": 10,
"description": "The inactive-customer trigger fires at exactly 21 days of inactivity (not 14, not 30) and fires only once at that specific mark"
},
{
"name": "Browse-reactivation vs whats-new branching",
"max_score": 8,
"description": "When triggered by inactivity: if the customer has recently viewed products, send a browse-reactivation email with those products; otherwise send a whats-new email"
},
{
"name": "6 new arrivals in whats-new",
"max_score": 7,
"description": "The whats-new fallback email includes 6 new arrivals (not 3, not 10)"
},
{
"name": "Order value drop threshold",
"max_score": 10,
"description": "The order-value-drop trigger fires when the latest order value is less than 50% of the customer's average order value"
},
{
"name": "Average order value lookback",
"max_score": 8,
"description": "Average order value for the drop trigger is calculated over the last 5 orders specifically"
},
{
"name": "Value-recovery email content",
"max_score": 8,
"description": "The value-recovery email includes the customer's top 3 most-purchased products (not generic recommendations)"
},
{
"name": "10% control group",
"max_score": 12,
"description": "The measurement module withholds 10% of at-risk customers as a control group (documented in ANALYTICS_NOTES.md or implemented in code)"
},
{
"name": "Lift calculation",
"max_score": 10,
"description": "Retention lift is calculated as ((campaignRepurchaseRate - controlRepurchaseRate) / controlRepurchaseRate) * 100, or equivalent percentage formula"
},
{
"name": "Revenue recovered metric",
"max_score": 8,
"description": "The measurement function also computes and returns revenue recovered from retained campaign customers (not just repurchase rate)"
},
{
"name": "No reflexive VIP discounting",
"max_score": 10,
"description": "ANALYTICS_NOTES.md documents that high-LTV customers who are only slightly overdue should receive a soft nudge rather than an automatic discount offer"
},
{
"name": "Separate unsubscribe tracking",
"max_score": 9,
"description": "ANALYTICS_NOTES.md describes tracking unsubscribes per campaign separately to detect messaging/timing problems before scaling"
}
]
}
Behavioral Triggers and Retention Campaign Analytics
Problem/Feature Description
Orchard Home is an online home goods retailer that has started sending retention emails but isn't sure whether they actually work. The head of growth wants two things: (1) a set of real-time behavioral triggers so that emails fire when customers show specific disengagement signals rather than on a fixed schedule, and (2) a measurement framework that produces reliable evidence that the campaigns are generating incremental repurchases — not just capturing customers who would have come back anyway.
The team also wants to make sure they're not burning goodwill by emailing enthusiastic VIP customers with aggressive discount offers every time they take a brief pause, and they want to understand whether certain campaigns are causing customers to unsubscribe at elevated rates.
Output Specification
Produce a TypeScript file behavioral-triggers.ts implementing two event-driven trigger functions that fire based on customer activity signals.
Produce a second TypeScript file campaign-analytics.ts implementing a lift measurement function that compares campaign recipients against a control group and returns repurchase rates, percentage lift, and revenue recovered.
Also produce an ANALYTICS_NOTES.md that covers: 1. What signals trigger each behavioral email and under what conditions 2. How the control group is selected and what fraction of at-risk customers it represents 3. How the measurement handles the comparison to calculate lift 4. How to avoid over-discounting VIP customers 5. What unsubscribe tracking should look like
{
"context": "Tests whether the agent correctly implements churn risk thresholds relative to individual purchase frequency, uses the correct RetentionScore interface fields, applies a sensible default for single-purchase customers, segments customers into the four expected groups with correct filter criteria, and excludes subscription customers from the scoring logic.",
"type": "weighted_checklist",
"checklist": [
{
"name": "RetentionScore interface fields",
"max_score": 10,
"description": "The RetentionScore type/interface includes all of: customerId, churnRisk, daysSincePurchase, purchaseFrequency, expectedNextOrder, daysOverdue"
},
{
"name": "churnRisk enum values",
"max_score": 8,
"description": "The churnRisk field is typed as 'low' | 'medium' | 'high' | 'churned' (exactly these four values)"
},
{
"name": "Frequency-relative thresholds",
"max_score": 14,
"description": "Churn risk levels are determined by multiples of purchase frequency: 'churned' when daysOverdue > frequency*2, 'high' when > frequency*1, 'medium' when > frequency*0.5, 'low' otherwise"
},
{
"name": "Single-purchase default frequency",
"max_score": 8,
"description": "Customers with only one order are assigned a default purchase frequency of 60 days"
},
{
"name": "Subscription customer exclusion",
"max_score": 10,
"description": "Subscription customers are explicitly excluded from churn scoring (e.g. filtered out before scoring or documented as excluded in DESIGN_NOTES.md)"
},
{
"name": "highValueAtRisk segment",
"max_score": 8,
"description": "The highValueAtRisk segment filters for churnRisk==='high' AND customer LTV > 200"
},
{
"name": "earlyWarning segment",
"max_score": 7,
"description": "The earlyWarning segment contains customers with churnRisk==='medium'"
},
{
"name": "recentlyChurned segment",
"max_score": 8,
"description": "The recentlyChurned segment filters for churnRisk==='churned' AND daysSincePurchase < 90"
},
{
"name": "oneTimeBuyers segment",
"max_score": 9,
"description": "The oneTimeBuyers segment filters for churnRisk==='medium' AND order count === 1 (not all one-time buyers, only medium-risk ones)"
},
{
"name": "45-day one-time buyer minimum",
"max_score": 8,
"description": "DESIGN_NOTES.md or code comments mention or implement the 45-day minimum window before treating a single-purchase customer as at-risk"
},
{
"name": "Nightly scoring job and DB indexes",
"max_score": 10,
"description": "DESIGN_NOTES.md or code comments mention running the scoring job nightly and recommend database indexes on last_order_date and customer_id"
}
]
}
Customer Churn Scoring System
Problem/Feature Description
Bloom & Co is a mid-sized online florist with a growing repeat customer base. Their marketing team has noticed that many customers who bought once or twice simply disappear, and the company has no way of knowing who is truly "gone" versus who is just between purchase cycles. The data team has access to the full order history per customer but currently has no scoring system to classify who is at risk of churning.
Your task is to design and implement a TypeScript churn scoring module that the team can run daily as part of their data pipeline. The module should assign risk levels to customers based on how overdue they are relative to their own individual purchase patterns. Customers with only a single order should receive a sensible fallback estimate. The team also has a mix of subscription-box customers and one-off purchasers in the same database, and they want to make sure the scoring logic applies correctly only to the right population.
Output Specification
Produce a single TypeScript file named churn-scoring.ts that implements the scoring logic as described. The file should export:
- A
RetentionScoretype or interface - A
calculateRetentionScoresfunction (can use stub/mock data access for database calls) - A
getAtRiskSegmentsfunction that groups scored customers into named segments
Also produce a short DESIGN_NOTES.md explaining: 1. How risk thresholds are determined 2. How single-purchase customers are handled 3. Which customers are excluded and why 4. What segments are produced and their definitions
The functions should be complete enough that a reviewer can understand the full scoring and segmentation approach by reading the code and notes.
{
"context": "Tests whether the agent implements correct deduplication guards for each workflow type, uses the correct discount parameters, recommends sending complementary products to one-time buyers, enforces a contact frequency cap, cancels pending jobs on purchase, and schedules the runner at the right time.",
"type": "weighted_checklist",
"checklist": [
{
"name": "Daily 9am schedule",
"max_score": 6,
"description": "The workflow runner is described or configured to run daily at 9am local timezone (in code comment, cron expression, or WORKFLOW_NOTES.md)"
},
{
"name": "Early-warning active-job dedup",
"max_score": 10,
"description": "For early-warning workflow, code or notes show checking for an existing active retentionJob record for the customer before sending and skipping if one exists"
},
{
"name": "Early-warning product count",
"max_score": 7,
"description": "Early-warning email is sent with 3 recommended products (not 1, 2, or 5)"
},
{
"name": "High-value 14-day dedup window",
"max_score": 9,
"description": "For high-value at-risk workflow, the deduplication check covers the last 14 days specifically (not 7, not 30)"
},
{
"name": "15% discount with 7-day expiry",
"max_score": 9,
"description": "The discount created for high-value customers is 15% off with an expiry of 7 days"
},
{
"name": "CS task creation",
"max_score": 8,
"description": "A follow-up task (e.g. 'follow-up-call') is queued for the CS team for high-value at-risk customers in addition to the automated email"
},
{
"name": "One-time buyer complementary products",
"max_score": 9,
"description": "The one-time buyer repurchase-reminder email uses complementary products derived from the previous order's line items (not generic recommendations)"
},
{
"name": "Contact frequency cap",
"max_score": 10,
"description": "A maximum of one retention touchpoint per week per customer (across all workflows) is documented or enforced"
},
{
"name": "Cancel on order.paid",
"max_score": 10,
"description": "WORKFLOW_NOTES.md or code documents that pending retention jobs should be cancelled when a customer places a new order (order.paid event or equivalent)"
},
{
"name": "Last purchase date pre-check",
"max_score": 10,
"description": "WORKFLOW_NOTES.md or code shows checking the customer's last purchase date before enqueueing any retention email to avoid sending to customers who just bought"
},
{
"name": "Discount only at high churn probability",
"max_score": 12,
"description": "WORKFLOW_NOTES.md or code notes that discount codes should only be offered when churn probability is sufficiently high (mentions 70% threshold or equivalent propensity scoring approach)"
}
]
}
Automated Retention Intervention Workflows
Problem/Feature Description
UrbanKit is an online streetwear retailer whose marketing team runs several email campaigns manually today. Each week a team member exports a list of lapsed customers and sends them a bulk discount code. The problem: customers who just bought yesterday sometimes receive the email anyway, high-value customers are getting the same 20%-off code as occasional buyers (which has started to erode gross margin), and some customers are getting retention emails on top of a newsletter plus a flash sale notification in the same day.
The engineering team has been asked to replace this manual process with an automated workflow system. The new system should automatically classify customers into risk tiers and dispatch the appropriate intervention — with guardrails to prevent over-contacting customers or sending unnecessary discounts to people who are likely to repurchase on their own.
The team wants the system to run once per day at a specific time and handle at least three distinct intervention types: early-warning customers who are just beginning to slip, high-value customers who are truly at risk, and first-time buyers approaching their expected repurchase window.
Output Specification
Produce a TypeScript file retention-workflows.ts that implements the automated workflow runner described above. Use stub/mock implementations for database calls and email sending — the logic and guard conditions are what matter.
Also produce a WORKFLOW_NOTES.md that documents: 1. When each workflow fires and for whom 2. What each intervention sends (content/parameters) 3. How duplicate sends are prevented for each workflow type 4. How frequently a customer can be contacted (across all workflows) 5. When a pending retention job should be cancelled
{
"name": "finsi/customer-retention-engine",
"version": "0.1.0",
"summary": "Build automated retention campaigns targeting at-risk customers with behavioral triggers, personalized offers, and churn prevention workflows",
"skills": {
"customer-retention-engine": {
"path": "SKILL.md"
}
}
}