Churn Risk Scorer

Read-only: scores customers by churn probability based on purchase recency, frequency decay, and expected repurchase intervals.

shopify-admin-churn-risk-scorer


Purpose

Predicts which customers are at risk of churning by analyzing their purchase patterns against their historical buying frequency. Calculates an expected next-purchase date for each repeat customer, then scores churn risk based on how overdue they are. Read-only — no mutations.


Prerequisites

  • Authenticated Shopify CLI session: shopify store auth --store --scopes read_orders,read_customers
  • API scopes: read_orders, read_customers

  • Parameters


    ParameterTypeRequiredDefaultDescription
    storestringyesStore domain
    days_backintegerno365Historical window for purchase pattern analysis
    min_ordersintegerno2Minimum orders to calculate purchase interval (need 2+ for frequency)
    risk_thresholdfloatno1.5Multiplier of avg purchase interval before flagging as at-risk
    formatstringnohumanOutput format: human or json

    Safety


    > ℹ️ Read-only skill — no mutations are executed. Safe to run at any time.


    Churn Risk Scoring Model


    For each customer with min_orders or more purchases:


  • Average Purchase Interval (API) = total days between first and last order / (order_count - 1)
  • Days Since Last Order (DSLO) = today - last_order_date
  • Overdue Ratio = DSLO / API
  • Churn Risk Score (0-100):
  • Overdue ratio ≤ 1.0 → Score 0-20 (Active)
  • Overdue ratio 1.0–1.5 → Score 20-50 (Cooling)
  • Overdue ratio 1.5–2.5 → Score 50-80 (At Risk)
  • Overdue ratio > 2.5 → Score 80-100 (Likely Churned)
  • Customer Lifetime Value (CLV) = total spend / customer age in years × expected remaining years

  • Workflow Steps


  • OPERATION: orders — query
  • Inputs: query: "created_at:>=''", first: 250, select createdAt, totalPriceSet, customer { id, email, firstName, lastName }, pagination cursor

    Expected output: All orders with customer association


  • Group orders by customer, calculate per customer:
  • Order dates (sorted chronologically)
  • Average purchase interval
  • Days since last order
  • Total spend
  • Order count

  • OPERATION: customers — query (enrichment)
  • Inputs: Customer IDs for at-risk and likely-churned segments

    Expected output: Contact details, tags, total spend


  • Calculate churn risk score and classify into segments

  • Estimate revenue at risk = sum of (annual_spend × churn_probability) for at-risk customers

  • GraphQL Operations


    # orders:query — validated against api_version 2025-01
    query OrdersForChurnAnalysis($query: String!, $after: String) {
      orders(first: 250, after: $after, query: $query) {
        edges {
          node {
            createdAt
            totalPriceSet { shopMoney { amount currencyCode } }
            customer {
              id
              email
              firstName
              lastName
              numberOfOrders
            }
          }
        }
        pageInfo { hasNextPage endCursor }
      }
    }
    

    # customers:query — validated against api_version 2025-01
    query AtRiskCustomers($ids: [ID!]!) {
      nodes(ids: $ids) {
        ... on Customer {
          id
          email
          firstName
          lastName
          totalSpentV2 { amount currencyCode }
          numberOfOrders
          tags
          createdAt
        }
      }
    }
    

    Session Tracking


    Claude MUST emit the following output at each stage. This is mandatory.


    On start, emit:

    ╔══════════════════════════════════════════════╗
    ║  SKILL: Churn Risk Scorer                    ║
    ║  Store: <store domain>                       ║
    ║  Started: <YYYY-MM-DD HH:MM UTC>             ║
    ╚══════════════════════════════════════════════╝
    

    After each step, emit:

    [N/TOTAL] <QUERY|MUTATION>  <OperationName>
              → Params: <brief summary of key inputs>
              → Result: <count or outcome>
    

    On completion, emit:


    For format: human (default):

    ══════════════════════════════════════════════
    CHURN RISK REPORT  (<days_back> days analyzed)
      Repeat customers scored:  <n>
      ─────────────────────────────
      Active (score 0-20):      <n> (<pct>%)
      Cooling (score 20-50):    <n> (<pct>%)
      At Risk (score 50-80):    <n> (<pct>%)   ⚠️
      Likely Churned (80-100):  <n> (<pct>%)   🔴
    
      Revenue at risk:         $<amount>/year
    
      Top at-risk by value:
        <name> (<email>)  Score: <n>  Last order: <date>  Lifetime: $<n>
    
      Output: churn_risk_<date>.csv
    ══════════════════════════════════════════════
    

    Output Format

    CSV file churn_risk_.csv with columns:

    customer_id, email, first_name, last_name, order_count, total_spent, avg_purchase_interval_days, days_since_last_order, overdue_ratio, churn_risk_score, risk_segment, expected_annual_value


    Error Handling

    ErrorCauseRecovery
    THROTTLEDAPI rate limit exceededWait 2 seconds, retry up to 3 times
    Single-purchase customersCan't calculate intervalExclude from scoring (need 2+ orders)
    Guest ordersNo customer linkageSkip — cannot build customer profile

    Best Practices

  • Pair with customer-win-back skill to take action on At-Risk and Likely Churned segments.
  • Use with rfm-customer-segmentation for a more holistic view of customer health.
  • High-value churning customers (top 20% by spend) should get personalized outreach.
  • Export At-Risk segment to email marketing platform for automated win-back sequences.
  • Adjust risk_threshold based on your product type: consumables (1.3), fashion (1.5), furniture (2.0).