{
  "id": "9pmjBc7dqrEagOoX",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "AI Customer Churn Predictor",
  "tags": [],
  "nodes": [
    {
      "id": "1f854286-b67a-42f9-9711-0056c93f9a0d",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -32,
        -384
      ],
      "parameters": {
        "width": 900,
        "height": 1504,
        "content": "## AI Customer Churn Predictor\n\nAnalyzes user behavior data and predicts churn probability using machine learning algorithms.\n\n## How it works\n\n1. **Trigger** \u2014 Runs daily at 2 AM to analyze active customers\n2. **Collect** \u2014 Fetches customer profiles, activity logs, and transaction history from database\n3. **Engineer** \u2014 Extracts features: login frequency, spend patterns, support tickets, engagement metrics\n4. **Predict** \u2014 Uses ML model to calculate churn probability (0-100%)\n5. **Score** \u2014 Classifies as HIGH RISK / MEDIUM RISK / LOW RISK\n6. **Remediate** \u2014 Creates retention campaigns for at-risk customers\n7. **Store** \u2014 Saves predictions to analytics database\n8. **Notify** \u2014 Sends alerts and dashboards via Email & Slack\n\n## Setup steps\n\n1. **Database** \u2014 Connect your customer database (PostgreSQL/MySQL)\n2. **ML Model** \u2014 Configure ML API endpoint or use Python ML node\n3. **Analytics DB** \u2014 Set up table for churn predictions\n4. **Slack/Email** \u2014 Add webhook URLs and SMTP credentials\n5. **Retention API** \u2014 Configure CRM/marketing platform for campaigns\n6. **Test** \u2014 Run manually first, then schedule daily execution\n\n**AI Customer Churn Predictor**\n\nThis n8n workflow runs daily to analyze active customer behavior, engineers relevant features from usage and transaction data, applies a machine learning or AI-based model to predict churn probability, classifies risk levels, triggers retention actions for at-risk customers, stores predictions for tracking, and notifies relevant teams.\n\n### Key Insights\n- Prediction accuracy heavily depends on feature quality \u2014 ensure login frequency, spend trends, support interactions, and engagement metrics are consistently captured and up-to-date.\n- Start with simple rule-based scoring or AI prompting (e.g., OpenAI/Claude) before integrating full ML models for easier testing and faster value.\n- High-risk thresholds (e.g., &gt;70%) should be tuned based on your actual churn data to avoid alert fatigue or missed opportunities.\n\n### Usage Guide\n- Import the workflow into n8n and configure credentials for your customer database (PostgreSQL/MySQL), ML API (if external), analytics DB, Slack webhook, SMTP/email, and CRM/retention platform.\n- Define feature extraction queries and thresholds carefully in the relevant nodes \u2014 test with a small customer subset first.\n- If using AI/LLM for prediction, refine the prompt to include clear examples of churn signals.\n- Run manually via the **Execute workflow** button with sample data to validate data flow, scoring logic, and notifications.\n- Once confident, activate the daily schedule.\n\n### Prerequisites\n- Customer database with readable tables for users, activity logs, transactions, and support interactions\n- ML integration option: either an external ML API endpoint, Python code node with scikit-learn/simple model, or LLM node (OpenAI, Claude, etc.) for probabilistic scoring\n- Separate analytics database (or same DB) with a table ready for churn predictions (customer_id, date, churn_prob, risk_level, etc.)\n- SMTP credentials or email service for alerts\n- Slack webhook URL (optional but recommended for team notifications)\n- CRM or marketing automation API access (e.g., HubSpot, ActiveCampaign, Klaviyo) for creating retention campaigns/tasks\n\n### Customization Options\n- Adjust the daily trigger time or make it hourly for near real-time monitoring of high-value accounts.\n- Change risk classification thresholds or add more tiers in the scoring logic node.\n- Enhance the prediction step: switch from LLM-based to a trained ML model (via Hugging Face, custom endpoint, or Code node).\n- Personalize retention actions: use AI to generate custom email content/offers based on the customer's behavior profile.\n- Add filtering (e.g., only high-value customers &gt; certain MRR) to focus retention efforts.\n- Extend notifications: integrate with Microsoft Teams, Discord, or create tickets in Zendesk/Jira for follow-up.\n- Build feedback loop: after actual churn occurs, update a training dataset or adjust weights/rules in future runs.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "2ae5a72b-8d07-4274-8d1d-233863fb9a08",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        928,
        112
      ],
      "parameters": {
        "color": 3,
        "width": 500,
        "height": 768,
        "content": "## 1. Trigger & Collect Data\n\nDaily schedule to fetch customer profiles and behavioral data"
      },
      "typeVersion": 1
    },
    {
      "id": "43bb8c82-df36-49f3-89fe-70d908cd5e4a",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1472,
        256
      ],
      "parameters": {
        "color": 5,
        "width": 388,
        "height": 448,
        "content": "## 2. Feature Engineering\n\nExtract and calculate behavioral features for ML model"
      },
      "typeVersion": 1
    },
    {
      "id": "45eec6c4-bb3c-40ae-91fd-f3523ced9e7b",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1920,
        320
      ],
      "parameters": {
        "color": 4,
        "width": 596,
        "height": 408,
        "content": "## 3. ML Prediction\n\nRun churn probability predictions and score customers"
      },
      "typeVersion": 1
    },
    {
      "id": "a0bd3b99-1e56-4d62-9abb-b60829950996",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2592,
        192
      ],
      "parameters": {
        "color": 5,
        "width": 550,
        "height": 612,
        "content": "## 4. Classify & Remediate\n\nRoute customers by risk level and create retention campaigns"
      },
      "typeVersion": 1
    },
    {
      "id": "197eba11-4fc5-477a-9ec7-73b512f5351c",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3232,
        208
      ],
      "parameters": {
        "color": 3,
        "width": 550,
        "height": 580,
        "content": "## 5. Report & Notify\n\nStore results and deliver churn analytics to stakeholders"
      },
      "typeVersion": 1
    },
    {
      "id": "e6ec0958-1d51-45be-a2d3-e9e2edf6b9da",
      "name": "Daily churn analysis at 2 AM",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        1056,
        496
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 2 * * *"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "4c3ff3c6-e6a4-4a16-8a9d-ce732dbccdc3",
      "name": "Fetch active customer profiles",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1280,
        304
      ],
      "parameters": {
        "url": "https://api.example.com/customers/active",
        "options": {}
      },
      "typeVersion": 4.2
    },
    {
      "id": "ca121dcf-1812-463d-8388-10266013e886",
      "name": "Fetch customer activity logs (30 days)",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1280,
        496
      ],
      "parameters": {
        "url": "https://api.example.com/logs/activity?days=30",
        "options": {}
      },
      "typeVersion": 4.2
    },
    {
      "id": "ed96d0b9-b6e3-408d-b955-2c3cf2080712",
      "name": "Fetch transaction history (90 days)",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1280,
        688
      ],
      "parameters": {
        "url": "https://api.example.com/transactions?days=90",
        "options": {}
      },
      "typeVersion": 4.2
    },
    {
      "id": "5ac08f4f-5321-40ad-81a1-f027fd635970",
      "name": "Merge customer and activity data",
      "type": "n8n-nodes-base.merge",
      "position": [
        1504,
        496
      ],
      "parameters": {
        "mode": "combine",
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "39030266-1388-4a8f-8b10-4bb70898b93e",
      "name": "Engineer behavioral features",
      "type": "n8n-nodes-base.code",
      "position": [
        1728,
        496
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// Feature engineering for churn prediction\nconst customer = $input.item.json;\n\n// --- Login Frequency ---\nconst loginDays = customer.activity_logs?.filter(log => log.type === 'login').length || 0;\nconst daysActive = customer.days_since_signup || 1;\nconst loginFrequency = Math.round((loginDays / 30) * 100) / 100; // logins per month\nconst loginTrend = (customer.login_last_7_days || 0) - (customer.login_previous_7_days || 0);\n\n// --- Spend Patterns ---\nconst totalSpend = customer.transactions?.reduce((sum, t) => sum + (t.amount || 0), 0) || 0;\nconst avgTransactionValue = customer.transactions?.length > 0 ? totalSpend / customer.transactions.length : 0;\nconst spendTrend = ((customer.spend_last_30 || 0) - (customer.spend_previous_30 || 0)) / (customer.spend_previous_30 || 1);\nconst daysLastPurchase = customer.days_since_last_purchase || 999;\n\n// --- Engagement Metrics ---\nconst supportTickets = customer.support_tickets || 0;\nconst featureUsage = customer.features_used || 0;\nconst emailEngagement = customer.email_open_rate || 0; // percentage\nconst accountAge = customer.days_since_signup || 1;\n\n// --- Subscription Details ---\nconst planValue = customer.plan_value || 0;\nconst isFreeTier = customer.plan_type === 'free';\nconst daysUntilRenewal = customer.days_until_renewal || 365;\nconst hasCardOnFile = customer.has_payment_method || false;\n\n// --- Feature Adoption ---\nconst adoptionScore = (featureUsage / (customer.available_features || 1)) * 100;\nconst apiCalls = customer.api_usage || 0;\nconst storageUsage = customer.storage_used_percent || 0;\n\n// --- Anomaly Flags ---\nconst suspiciousLogin = loginTrend < -5; // drop in logins\nconst noPurchaseInDays = daysLastPurchase > 60;\nconst lowEngagement = loginFrequency < 2; // less than 2 logins/month\nconst highSupportVolume = supportTickets > 5;\nconst negativeSpendTrend = spendTrend < -0.3; // 30% drop in spend\n\n// --- Compile feature vector ---\nconst features = {\n  customer_id: customer.id,\n  email: customer.email,\n  signup_date: customer.signup_date,\n  plan_type: customer.plan_type,\n  \n  // Core features\n  login_frequency: loginFrequency,\n  login_trend: loginTrend,\n  days_last_purchase: daysLastPurchase,\n  total_spend: totalSpend,\n  avg_transaction_value: avgTransactionValue,\n  spend_trend: spendTrend,\n  account_age_days: accountAge,\n  \n  // Engagement\n  support_tickets: supportTickets,\n  feature_usage_count: featureUsage,\n  adoption_score: adoptionScore,\n  email_engagement: emailEngagement,\n  api_calls: apiCalls,\n  storage_usage_percent: storageUsage,\n  \n  // Subscription\n  plan_value: planValue,\n  is_free_tier: isFreeTier,\n  days_until_renewal: daysUntilRenewal,\n  has_card_on_file: hasCardOnFile,\n  \n  // Anomalies\n  flag_suspicious_login: suspiciousLogin,\n  flag_no_purchase_60days: noPurchaseInDays,\n  flag_low_engagement: lowEngagement,\n  flag_high_support_volume: highSupportVolume,\n  flag_negative_spend_trend: negativeSpendTrend,\n  \n  // Calculated risk indicators\n  anomaly_count: [suspiciousLogin, noPurchaseInDays, lowEngagement, highSupportVolume, negativeSpendTrend].filter(Boolean).length\n};\n\nreturn {\n  json: features\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "a6e2a4e3-05e5-426f-b6e6-8502ea446f3d",
      "name": "Call ML churn prediction model",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1952,
        496
      ],
      "parameters": {
        "url": "https://ml-api.example.com/predict/churn",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "features",
              "value": "={{ {login_frequency: $json.login_frequency, login_trend: $json.login_trend, days_last_purchase: $json.days_last_purchase, total_spend: $json.total_spend, spend_trend: $json.spend_trend, support_tickets: $json.support_tickets, adoption_score: $json.adoption_score, anomaly_count: $json.anomaly_count} }}"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "241db3b1-befb-4b8e-9758-f84ae5d600c8",
      "name": "Score and classify churn risk",
      "type": "n8n-nodes-base.code",
      "position": [
        2176,
        496
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// Score churn risk and classify into risk tiers\nconst data = $input.item.json;\nconst mlPrediction = data.churn_probability || 0; // 0-1 scale\n\n// Convert to 0-100 scale\nconst churnScore = Math.round(mlPrediction * 100);\n\n// Classification logic\nlet riskLevel = 'LOW_RISK';\nlet actionRequired = false;\nlet campaignType = 'none';\nlet priority = 'low';\n\nif (churnScore >= 70) {\n  riskLevel = 'HIGH_RISK';\n  actionRequired = true;\n  campaignType = 'aggressive_retention';\n  priority = 'critical';\n} else if (churnScore >= 50) {\n  riskLevel = 'MEDIUM_RISK';\n  actionRequired = true;\n  campaignType = 'engagement_boost';\n  priority = 'high';\n} else if (churnScore >= 30) {\n  riskLevel = 'EARLY_RISK';\n  actionRequired = false;\n  campaignType = 'preventive';\n  priority = 'medium';\n}\n\n// Risk factors summary\nconst riskFactors = [];\nif (data.flag_no_purchase_60days) riskFactors.push('No purchase in 60+ days');\nif (data.flag_low_engagement) riskFactors.push('Low login frequency');\nif (data.flag_negative_spend_trend) riskFactors.push('Declining spend');\nif (data.flag_high_support_volume) riskFactors.push('High support tickets');\nif (data.flag_suspicious_login) riskFactors.push('Unusual login activity');\n\n// Retention strategy\nlet recommendedAction = '';\nif (churnScore >= 70) {\n  recommendedAction = 'Immediate outreach: Offer discount, upgrade incentive, or VIP support';\n} else if (churnScore >= 50) {\n  recommendedAction = 'Engagement campaign: Personalized tutorials, feature highlights';\n} else if (churnScore >= 30) {\n  recommendedAction = 'Monitor closely: Nurture with educational content and updates';\n}\n\nconst timestamp = new Date().toISOString();\nconst predictionDate = new Date().toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' });\n\nreturn {\n  json: {\n    // Customer & Prediction Identity\n    customer_id: data.customer_id,\n    email: data.email,\n    plan_type: data.plan_type,\n    \n    // Churn Score & Classification\n    churn_probability_score: churnScore,\n    churn_probability_percentage: churnScore + '%',\n    risk_level: riskLevel,\n    risk_level_numeric: riskLevel === 'HIGH_RISK' ? 3 : riskLevel === 'MEDIUM_RISK' ? 2 : riskLevel === 'EARLY_RISK' ? 1 : 0,\n    \n    // Key Metrics\n    login_frequency: data.login_frequency,\n    days_since_last_purchase: data.days_last_purchase,\n    total_lifetime_value: data.total_spend,\n    spend_trend_percent: Math.round(data.spend_trend * 100),\n    support_tickets_90days: data.support_tickets,\n    feature_adoption_score: Math.round(data.adoption_score),\n    account_age_days: data.account_age_days,\n    \n    // Risk Indicators\n    risk_factors: riskFactors,\n    risk_factor_count: riskFactors.length,\n    anomaly_flags_count: data.anomaly_count,\n    \n    // Action & Campaign\n    action_required: actionRequired,\n    campaign_type: campaignType,\n    priority: priority,\n    recommended_action: recommendedAction,\n    \n    // Timestamp\n    prediction_date: predictionDate,\n    prediction_timestamp: timestamp,\n    \n    // Original features for reference\n    features: data\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "e37bc7ba-bd03-41d3-9be4-0744bbb5b2d7",
      "name": "Route by risk level",
      "type": "n8n-nodes-base.switch",
      "position": [
        2400,
        480
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "High Risk",
              "conditions": {
                "options": {
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.risk_level }}",
                    "rightValue": "HIGH_RISK"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Medium Risk",
              "conditions": {
                "options": {
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.risk_level }}",
                    "rightValue": "MEDIUM_RISK"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Low Risk",
              "conditions": {
                "options": {
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.risk_level }}",
                    "rightValue": "EARLY_RISK"
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "c276d68c-d114-4894-a2c1-7b7a2f620762",
      "name": "Create retention campaign task",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2624,
        400
      ],
      "parameters": {
        "url": "https://api.example.com/campaigns/create",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "customer_id",
              "value": "={{ $json.customer_id }}"
            },
            {
              "name": "campaign_type",
              "value": "={{ $json.campaign_type }}"
            },
            {
              "name": "churn_score",
              "value": "={{ $json.churn_probability_score }}"
            },
            {
              "name": "risk_level",
              "value": "={{ $json.risk_level }}"
            },
            {
              "name": "recommended_action",
              "value": "={{ $json.recommended_action }}"
            },
            {
              "name": "priority",
              "value": "={{ $json.priority }}"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "ca4e1fe7-be3f-4551-88f2-321fee4b8318",
      "name": "Store churn predictions in database",
      "type": "n8n-nodes-base.postgres",
      "position": [
        2624,
        592
      ],
      "parameters": {
        "table": "churn_predictions",
        "schema": {
          "__rl": true,
          "mode": "list",
          "value": "public"
        },
        "columns": {
          "value": {},
          "schema": [],
          "mappingMode": "autoMapInputData",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.5
    },
    {
      "id": "77b5a3e0-50ac-4a7a-90fd-5df6a4245a73",
      "name": "Generate churn analytics report",
      "type": "n8n-nodes-base.code",
      "position": [
        2848,
        496
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// Generate HTML report for churn predictions\nconst data = $input.item.json;\n\nconst statusColor = data.risk_level === 'HIGH_RISK' ? '#ef4444' \n  : data.risk_level === 'MEDIUM_RISK' ? '#f59e0b' \n  : '#22c55e';\n\nconst statusIcon = data.risk_level === 'HIGH_RISK' ? '\ud83d\udea8' \n  : data.risk_level === 'MEDIUM_RISK' ? '\u26a0\ufe0f' \n  : '\u2705';\n\nconst reportHtml = `\n<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"UTF-8\">\n  <title>Churn Prediction Report - ${data.customer_id}</title>\n  <style>\n    body { font-family: Arial, sans-serif; color: #1e293b; margin: 0; padding: 24px; background: #f8fafc; }\n    .header { background: #0f172a; color: white; padding: 24px; border-radius: 8px; margin-bottom: 24px; }\n    .header h1 { margin: 0 0 8px 0; font-size: 22px; }\n    .header p { margin: 0; opacity: 0.7; font-size: 13px; }\n    .status-badge { display: inline-block; padding: 8px 16px; border-radius: 20px; font-weight: bold; font-size: 14px; background: ${statusColor}; color: white; margin-top: 12px; }\n    .cards { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; margin-bottom: 24px; }\n    .card { background: white; border-radius: 8px; padding: 16px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); }\n    .card .value { font-size: 28px; font-weight: bold; color: ${statusColor}; }\n    .card .label { font-size: 12px; color: #64748b; margin-top: 4px; }\n    .section { background: white; border-radius: 8px; padding: 20px; margin-bottom: 20px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); }\n    .section h2 { margin: 0 0 16px 0; font-size: 16px; border-bottom: 2px solid #e2e8f0; padding-bottom: 8px; }\n    table { width: 100%; border-collapse: collapse; font-size: 13px; }\n    th { background: #f1f5f9; text-align: left; padding: 8px 12px; }\n    td { padding: 8px 12px; border-bottom: 1px solid #e2e8f0; }\n    .action-box { background: ${statusColor}15; border-left: 4px solid ${statusColor}; padding: 12px; margin-top: 12px; border-radius: 4px; }\n    .footer { text-align: center; font-size: 11px; color: #94a3b8; margin-top: 24px; }\n  </style>\n</head>\n<body>\n  <div class=\"header\">\n    <h1>${statusIcon} Customer Churn Risk Assessment</h1>\n    <p>Customer: ${data.email} | Plan: ${data.plan_type} | Generated: ${data.prediction_date}</p>\n    <div class=\"status-badge\">${data.risk_level.replace(/_/g, ' ')}</div>\n  </div>\n\n  <div class=\"cards\">\n    <div class=\"card\"><div class=\"value\">${data.churn_probability_score}%</div><div class=\"label\">Churn Risk Score</div></div>\n    <div class=\"card\"><div class=\"value\">\\$${Math.round(data.total_lifetime_value)}</div><div class=\"label\">Lifetime Value</div></div>\n    <div class=\"card\"><div class=\"value\">${data.login_frequency.toFixed(1)}</div><div class=\"label\">Logins/Month</div></div>\n    <div class=\"card\"><div class=\"value\">${data.adoption_score}%</div><div class=\"label\">Feature Adoption</div></div>\n  </div>\n\n  <div class=\"section\">\n    <h2>\ud83d\udcca Key Metrics</h2>\n    <table><tbody>\n      <tr><td><strong>Days Since Last Purchase</strong></td><td>${data.days_since_last_purchase}</td></tr>\n      <tr><td><strong>Spend Trend (90 days)</strong></td><td>${data.spend_trend_percent > 0 ? '+' : ''}${data.spend_trend_percent}%</td></tr>\n      <tr><td><strong>Support Tickets (90 days)</strong></td><td>${data.support_tickets_90days}</td></tr>\n      <tr><td><strong>Account Age</strong></td><td>${data.account_age_days} days</td></tr>\n    </tbody></table>\n  </div>\n\n  <div class=\"section\">\n    <h2>\u26a0\ufe0f Risk Factors (${data.risk_factor_count})</h2>\n    <ul>${data.risk_factors.map(f => '<li>' + f + '</li>').join('')}</ul>\n  </div>\n\n  <div class=\"section\">\n    <h2>\ud83c\udfaf Recommended Action</h2>\n    <div class=\"action-box\">\n      <strong>${data.recommended_action}</strong>\n      <br><br>\n      <em>Campaign Type: ${data.campaign_type.replace(/_/g, ' ').toUpperCase()}</em>\n    </div>\n  </div>\n\n  <div class=\"footer\">AI Customer Churn Predictor | ${data.prediction_timestamp}</div>\n</body>\n</html>`;\n\nconst notificationMessage = `${statusIcon} *CHURN RISK ALERT \u2014 ${data.email}*\\n\\n` +\n  `*Risk Level:* ${data.risk_level.replace(/_/g, ' ')}\\n` +\n  `*Churn Score:* ${data.churn_probability_score}%\\n` +\n  `*Lifetime Value:* \\$${Math.round(data.total_lifetime_value)}\\n\\n` +\n  `*Key Metrics:*\\n` +\n  `\u2022 Logins/Month: ${data.login_frequency.toFixed(1)}\\n` +\n  `\u2022 Days Since Purchase: ${data.days_since_last_purchase}\\n` +\n  `\u2022 Spend Trend: ${data.spend_trend_percent > 0 ? '+' : ''}${data.spend_trend_percent}%\\n` +\n  `\u2022 Feature Adoption: ${data.adoption_score}%\\n\\n` +\n  `*Risk Factors:* ${data.risk_factors.join(', ')}\\n` +\n  `*Action:* ${data.recommended_action}`;\n\nreturn {\n  json: {\n    ...data,\n    reportHtml,\n    notificationMessage,\n    notificationTitle: `${statusIcon} [${data.customer_id}] ${data.risk_level.replace(/_/g, ' ')} - Churn Score: ${data.churn_probability_score}%`,\n    shouldNotify: data.action_required,\n    shouldNotifyAll: true\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "749cee1c-71ed-4c46-acf5-2bffb16fd094",
      "name": "Filter at-risk customers",
      "type": "n8n-nodes-base.filter",
      "position": [
        3072,
        496
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": false,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "notify-condition",
              "operator": {
                "type": "boolean",
                "operation": "true"
              },
              "leftValue": "={{ $json.action_required }}"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "859e2c70-dded-45ee-a8a0-118a16762657",
      "name": "Post churn alert to Slack",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        3296,
        400
      ],
      "parameters": {
        "url": "YOUR_SLACK_WEBHOOK_URL",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"text\": \"{{ $json.notificationTitle }}\",\n  \"blocks\": [\n    {\n      \"type\": \"section\",\n      \"text\": {\n        \"type\": \"mrkdwn\",\n        \"text\": \"{{ $json.notificationMessage }}\"\n      }\n    }\n  ]\n}",
        "sendBody": true,
        "specifyBody": "json"
      },
      "typeVersion": 4.2
    },
    {
      "id": "c871536b-fb9f-4b73-ba8e-9666959da6ab",
      "name": "Email report to customer success team",
      "type": "n8n-nodes-base.emailSend",
      "position": [
        3296,
        592
      ],
      "parameters": {
        "html": "={{ $json.reportHtml }}",
        "options": {},
        "subject": "={{ $json.notificationTitle }}",
        "toEmail": "user@example.com",
        "fromEmail": "noreply@example.com"
      },
      "credentials": {
        "smtp": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "f6b94a2d-c388-4596-9438-f8b593307b22",
      "name": "Log analysis completion",
      "type": "n8n-nodes-base.code",
      "position": [
        3520,
        496
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// Log churn analysis completion\nconst timestamp = new Date().toISOString();\nconst data = $input.item.json;\n\nconsole.log(`\u2705 CHURN ANALYSIS: Customer ${data.customer_id} | Risk: ${data.risk_level} | Score: ${data.churn_probability_score}% | Action: ${data.campaign_type} | Time: ${timestamp}`);\n\n// Aggregate statistics\nconst stats = $getWorkflowStaticData('global').stats || {\n  totalAnalyzed: 0,\n  highRiskCount: 0,\n  mediumRiskCount: 0,\n  lowRiskCount: 0,\n  avgChurnScore: 0,\n  lastUpdated: null\n};\n\nif (data.risk_level === 'HIGH_RISK') stats.highRiskCount++;\nelse if (data.risk_level === 'MEDIUM_RISK') stats.mediumRiskCount++;\nelse stats.lowRiskCount++;\n\nstats.totalAnalyzed++;\nstats.lastUpdated = timestamp;\n\n$getWorkflowStaticData('global').stats = stats;\n\nreturn {\n  json: {\n    success: true,\n    customer_id: data.customer_id,\n    risk_level: data.risk_level,\n    churn_score: data.churn_probability_score,\n    timestamp,\n    cumulativeStats: stats\n  }\n};"
      },
      "typeVersion": 2
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "d4a74901-f1bc-46d0-ae0a-88864d51c3df",
  "connections": {
    "Route by risk level": {
      "main": [
        [
          {
            "node": "Create retention campaign task",
            "type": "main",
            "index": 0
          },
          {
            "node": "Store churn predictions in database",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Create retention campaign task",
            "type": "main",
            "index": 0
          },
          {
            "node": "Store churn predictions in database",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Store churn predictions in database",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter at-risk customers": {
      "main": [
        [
          {
            "node": "Post churn alert to Slack",
            "type": "main",
            "index": 0
          },
          {
            "node": "Email report to customer success team",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Post churn alert to Slack": {
      "main": [
        [
          {
            "node": "Log analysis completion",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Daily churn analysis at 2 AM": {
      "main": [
        [
          {
            "node": "Fetch active customer profiles",
            "type": "main",
            "index": 0
          },
          {
            "node": "Fetch customer activity logs (30 days)",
            "type": "main",
            "index": 0
          },
          {
            "node": "Fetch transaction history (90 days)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Engineer behavioral features": {
      "main": [
        [
          {
            "node": "Call ML churn prediction model",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Score and classify churn risk": {
      "main": [
        [
          {
            "node": "Route by risk level",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Call ML churn prediction model": {
      "main": [
        [
          {
            "node": "Score and classify churn risk",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create retention campaign task": {
      "main": [
        [
          {
            "node": "Generate churn analytics report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch active customer profiles": {
      "main": [
        [
          {
            "node": "Merge customer and activity data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate churn analytics report": {
      "main": [
        [
          {
            "node": "Filter at-risk customers",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge customer and activity data": {
      "main": [
        [
          {
            "node": "Engineer behavioral features",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch transaction history (90 days)": {
      "main": [
        [
          {
            "node": "Merge customer and activity data",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Store churn predictions in database": {
      "main": [
        [
          {
            "node": "Generate churn analytics report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Email report to customer success team": {
      "main": [
        [
          {
            "node": "Log analysis completion",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch customer activity logs (30 days)": {
      "main": [
        [
          {
            "node": "Merge customer and activity data",
            "type": "main",
            "index": 1
          }
        ]
      ]
    }
  }
}