Features

Features

How every feature in Customer Dashboard works. Classification, alerts, revenue tracking, B2B detection, and data export.

Customer Classification

The Two-Threshold Model

Customer Dashboard uses two configurable thresholds to classify every B2B customer into one of three statuses.

The thresholds

  • Active days (default 30): the boundary between Active and At Risk
  • At-risk days (default 90): the boundary between At Risk and Dormant

The classification logic

For each B2B customer, Customer Dashboard calculates days since the most recent order matching the configured revenue statuses. Then:

  • If days since last order ≤ active days → Active
  • If days since last order > active days but ≤ at-risk days → At Risk
  • If days since last order > at-risk days → Dormant

Customers who have never placed an order matching the configured statuses are classified as Dormant.

With default settings (30/90): ordered within 30 days → Active, 31–90 days ago → At Risk, more than 90 days ago → Dormant.

Why Two Thresholds, Not Three

Customer Dashboard intentionally uses two thresholds, not three. With three statuses (Active, At Risk, Dormant), only two boundary lines are needed. A common mistake in customer health dashboards is using three thresholds for three statuses, which creates an undefined gap. Two thresholds is mathematically exhaustive — every customer falls into exactly one status with no gaps and no overlaps.

How Range Filtering Affects the Dashboard

The range pills at the top of the dashboard (30 Days, 90 Days, This Year, All Time) filter what revenue and order data is shown, but they do not change customer classification. This is a deliberate design choice.

What the range pills DO filter

  • Revenue totals
  • Order counts
  • Average order value
  • The revenue trend chart

What the range pills do NOT filter

  • Customer classification (Active, At Risk, Dormant)
  • Days since last order
  • The customer health doughnut chart breakdown

Adjusting Thresholds for Your Store

The default thresholds (30 days Active, 90 days At Risk) suit B2B stores with monthly ordering patterns. Here are recommended values for different ordering cycles:

  • Monthly ordering patterns: Active 30, At-risk 90 (default)
  • Quarterly ordering patterns: Active 90, At-risk 180
  • Long-cycle B2B (equipment, durable goods): Active 180, At-risk 365

You can adjust thresholds anytime in the Configuration settings. The dashboard recalculates all classifications immediately.

When Customers Move Between Statuses

Customer Dashboard recalculates classification on every page load (within cache limits). The days_since_last value is recomputed from the cached last-order timestamp on every read, so a customer can cross a threshold boundary even within the cache TTL.

  • Dormant becomes Active: The customer places a new order and the cache refreshes.
  • Active becomes At Risk: More than active_days pass since the customer’s last order.
  • At Risk becomes Dormant: More than atrisk_days pass since the customer’s last order.

You can also adjust thresholds in settings to reclassify all customers immediately.

What Classification Doesn’t Account For

Classification is based purely on time since last order. It doesn’t account for:

  • Order value: A customer who placed one $50 order yesterday is Active. A customer who placed twenty $5,000 orders 45 days ago is At Risk.
  • Order frequency variation: A customer who orders every 14 days is treated the same as one who orders every 25 days, as long as both ordered within the last 30 days.
  • Customer lifetime: A brand-new customer with one order yesterday is Active. A 10-year customer with thousands of orders but no order in 100 days is Dormant.

Classification answers “when did this customer last engage with my store?” not “is this customer valuable?” or “is this customer’s behavior normal?”

To understand value or behavioral patterns, use the revenue column (sortable), AOV column, reorder cycle column, and the Alerts feature.

Alerts

Three Alert Types

Customer Dashboard surfaces three alert categories on the dashboard:

  • Dormant Accounts: Customers who haven’t ordered in over atrisk_days days
  • Slipping Accounts: Customers whose ordering pattern is decelerating
  • Growth Opportunities: Customers whose revenue is significantly increasing

Each alert appears as a card on the dashboard with up to 5 customers shown. The customer name, company, and relevant metric (days silent, gap drift, revenue change) display in each entry.

Dormant Accounts

Lists customers with at least one order who haven’t placed an order in more than atrisk_days days. These customers have crossed from At Risk into Dormant status and may need re-engagement.

Sorted by revenue descending — the highest-value Dormant customers appear first.

Common reasons customers become Dormant

  • Switched to a competitor
  • Internal change at their business (procurement contact left, budget cut, contract ended)
  • Forgot about your store
  • Business closed or paused operations
  • Seasonal customer (only orders during certain months)

How to act on Dormant alerts

The card shows customer name, company, and days since last order. Click their entry to view full order history in WooCommerce.

Slipping Accounts

Surfaces customers whose ordering pattern is decelerating. Unlike Dormant alerts (time silence alone), Slipping alerts detect behavioral changes from a customer’s own historical pattern. Slipping is independent of classification status — a customer can be Active, At Risk, or Dormant and also Slipping.

How Slipping is calculated

For each customer with at least 2 orders matching the configured revenue statuses:

  • Average gap: mean number of days between this customer’s consecutive orders
  • Latest gap: number of days since their last order to now (a synthetic “silence-to-now” gap)
  • If the latest gap exceeds the average gap by more than the slipping percentage setting (default 50%), the Slipping alert fires.

Sorted by drift percentage descending — the most dramatically slowing customers appear first.

Example

A customer historically orders every 21 days on average. Last order was 35 days ago. Latest gap (35 days) is 67% longer than average (21 days), exceeding 50% threshold. They appear in the Slipping alert.

Growth Opportunities

Highlights customers whose recent revenue significantly exceeds their prior 90-day revenue. Accounts trending upward and might be candidates for relationship investment.

How Growth is calculated

Compare recent revenue (last 90 days) vs prior revenue (90 days before that). Both windows must have revenue greater than zero. If recent exceeds prior by at least 1.2× (20% increase), the Growth alert fires.

Sorted by lift percentage descending — the fastest-growing customers appear first.

Example

Customer spent $5,000 in prior 90 days and $7,500 in recent 90 days. Growth ratio is 1.5× (50% increase), exceeding the 1.2× threshold.

Why this matters: Growing customers are often early signals of expanding business relationships.

Accounts Needing Attention

In addition to the three alert cards, Customer Dashboard displays an “Accounts Needing Attention” summary table that combines At Risk and Dormant customers in a single list.

Sorted by revenue exposure — highest revenue at risk first. Helps prioritize retention efforts.

Shows up to 10 combined At Risk + Dormant customers. Separate from the Dormant alert card (which shows top 5 Dormant specifically).

Why a Customer Might Not Appear in Any Alert

  • They haven’t crossed any threshold yet. Slipping requires latest gap to exceed average by the configured percentage (default 50%). Growth requires recent revenue to exceed prior by 20%. Dormant requires more than atrisk_days since last order.
  • They have only one order. Slipping requires at least 2 orders. Growth requires revenue in both the recent and prior 90-day windows. Single-order customers can only appear in Dormant alerts.
  • The cache hasn’t refreshed. Based on the cache refresh interval setting (default 1 hour). Click the “Last updated” link in the dashboard header to manually refresh.

Revenue Tracking

Which Orders Count Toward Revenue

Revenue calculations are controlled by the Revenue statuses setting. Only orders whose WooCommerce status matches one of the selected statuses are counted.

  • New installs default to: Completed and Processing
  • Stores upgrading from a version before this setting existed have Completed, Processing, and On Hold selected automatically to preserve prior behavior

You can change which statuses count by opening the plugin settings (gear icon) and selecting or deselecting statuses under Revenue statuses. The change takes effect after saving and affects all dashboard calculations.

Guest Order Exclusion

Orders placed by guest checkout (no registered account) are excluded from all dashboard figures. When guest orders exist in the selected date range, the dashboard displays a notice showing the number of excluded guest orders.

For accurate B2B analytics, ensure wholesale customers create accounts at checkout. Most B2B plugins enforce account creation.

Revenue at Risk

The Revenue at Risk banner at the top of the dashboard shows total revenue that may be at stake from At Risk or Dormant customers.

How it’s calculated: Combines At Risk customers’ annualized revenue based on recent order history + Dormant customers’ lifetime revenue (annualized from first to last order timeframe).

The number gives you a single dollar figure to prioritize retention efforts. Small number = strong retention. Large number = concentrated risk.

Largest Exposure

To the right of Revenue at Risk, shows the single customer with highest revenue exposure. Displays: customer company name, revenue amount, status pill (At Risk or Dormant).

Hidden if no At Risk or Dormant customers exist.

Most actionable single piece of information — answers “where should I focus first?”

Revenue Trend Chart

Shows monthly B2B revenue. The number of months adapts to the selected range: 6 months for 30 Days and 90 Days, 12 months for This Year, and 24 months for All Time. Leading months with zero revenue are trimmed. X-axis: months in “Mon ’YY” format (English month abbreviations). Y-axis: revenue in store’s currency, starting at zero.

  • Includes: Revenue from orders matching the configured revenue statuses
  • Excludes: Refunded orders (wc-refunded status), cancelled, failed, pending orders, and any status not selected in settings

How Partial Refunds Are Handled

Customer Dashboard deducts partial refunds from revenue calculations at the query level. If you refunded $200 from a $1,000 order, the order contributes $800, not $1,000. Revenue is floored at zero per order — a refund larger than the original total does not produce negative revenue.

Affects: headline Total Revenue metric, AOV, Revenue at Risk, Largest Exposure figure, monthly Revenue Trend chart.

Why this matters: B2B stores routinely process partial refunds for returns, billing adjustments, and dispute settlements. Without refund deduction, the dashboard would overstate revenue.

Fully refunded orders (status changed to wc-refunded) are excluded entirely.

Time Range Filtering

Range pills: 30 Days, 90 Days, This Year (default), All Time.

Default is “This Year” because it aligns with how most B2B operators think about revenue periods.

When the order history window is set to a value other than All Time, the “All Time” range pill shows data within the configured window, not truly all historical data. The dashboard displays a notice indicating the effective date range. To see truly all revenue, set the order history window to All Time in settings and select the All Time range pill.

Revenue Reconciliation with WooCommerce

Differences with WooCommerce built-in reports are expected and usually correct.

Common reasons:

  • Dashboard shows only B2B revenue (WooCommerce shows all)
  • Dashboard deducts partial refunds
  • Dashboard only counts orders matching the configured revenue statuses (default: completed and processing)
  • Time ranges may differ
  • Guest orders are excluded from the dashboard

If the difference is significant, see the Troubleshooting guide.

B2B Customer Detection

Why B2B Detection Matters

WooCommerce treats every customer the same. For B2B-focused analytics, this isn’t useful.

Customer Dashboard separates B2B from retail automatically. The dashboard only shows B2B customers — retail excluded from all metrics, classifications, and alerts.

Detection Sources

Four detection layers, evaluated in order. A customer is B2B if ANY layer matches.

Layer 1: Built-in B2B roles

wholesale_customer (Wholesale Suite), b2bking_customer (B2BKing), wcwp_wholesale (Barn2). No configuration needed.

Layer 2: Built-in B2B user meta

b2bking_customergroup meta, b2bking_b2buser meta (B2BKing), __wholesalex_role meta (WholesaleX, note: double underscore). Work in addition to role-based detection.

Layer 3: Custom B2B roles

Configure additional roles in settings. Steps:

  1. Navigate to dashboard
  2. Click gear icon
  3. Scroll to B2B Customer Detection
  4. Check boxes for additional roles
  5. Click Save Changes

Custom roles detected in addition to built-in, not instead of.

Layer 4: Order-count fallback (gated)

If layers 1–3 find zero combined matches, falls back to customers with at least N completed orders (default 2, configurable). This fallback only activates when role and meta detection find zero matches. This prevents retail repeat-buyers from being accidentally classified as B2B on stores with legitimate B2B detection.

Supported B2B Plugins

  • Wholesale Suite by Rymera Web Co. — Detection: wholesale_customer role. No config required.
  • B2BKing — Detection: b2bking_customer role, b2bking_customergroup meta, or b2bking_b2buser meta. All three automatic.
  • WholesaleX by WPXPO — Detection: __wholesalex_role meta (note: double underscore). No config required.
  • WooCommerce Wholesale Pro by Barn2 — Detection: wcwp_wholesale role. No config required.
  • Other B2B plugins: If not listed, configure manually by adding your B2B role to Custom B2B Roles setting.

Excluding Specific Customers

Use cases: test accounts, internal staff with wholesale roles, customers who skew metrics.

Steps:

  1. Navigate to dashboard
  2. Click gear icon
  3. Scroll to B2B Customer Detection section
  4. In the Excluded accounts field, enter user IDs or email addresses comma-separated
  5. Click Save Changes

Example: 42, owner@yourstore.com, 105, accounting@yourstore.com

Excluded accounts are completely removed from all dashboard data.

Guest Checkout Behavior

Guest checkout orders are excluded from all dashboard figures. B2B analytics requires persistent customer identity, and guest orders have no persistent identity.

When guest orders exist in the selected date range, the dashboard displays a notice showing the count of excluded guest orders. See Guest Order Exclusion above.

For accurate B2B analytics, ensure wholesale customers create accounts at checkout. Most B2B plugins enforce this.

Verifying B2B Detection Is Working

  • Check 1: Customer count matches expectations
  • Check 2: Known customers appear (search in customer table)
  • Check 3: Retail customers don’t appear

If detection isn’t working, see the Troubleshooting guide.

Data Export

How to Export

The Export CSV button is located in the customer table section header, next to the search and status filter controls.

  1. Navigate to Kascado → Customer Dashboard.
  2. Apply any filters you want included in the export (status filter, search term, time range).
  3. Click the Export CSV button in the dashboard header.
  4. Your browser downloads a CSV file.

The export reflects your current dashboard state — same customers, same range, same filters, same sort order.

What Gets Exported

The CSV export includes all B2B customers visible in the current dashboard view, with active filters applied.

Filters preserved in the export:

  • Status filter — If you’ve filtered by Active, At Risk, or Dormant, only those customers export.
  • Search term — If you’ve searched for a specific customer, only matching customers export.
  • Time range — Revenue and order counts reflect the selected range (30 Days, 90 Days, This Year, All Time).
  • Sort order — The export preserves the active sort column and direction.

Example: If you set the dashboard to “At Risk” customers in “Last 90 Days” range sorted by revenue descending, the CSV contains only At Risk customers with their last-90-days revenue, in that order.

CSV Filename

The downloaded file is named:

kascado-b2b-customers-YYYYMMDD-HHmmss.csv

When the order history window constrains the data (set to a value other than All Time), the filename includes the window:

kascado-b2b-customers-last-2-years-YYYYMMDD-HHmmss.csv

The year segment uses singular or plural as appropriate (last-1-year vs. last-2-years).

CSV Columns

The export includes these 11 columns:

ColumnDescription
CustomerCustomer display name
CompanyCompany name (from billing or shipping address)
EmailCustomer email address
StatusActive, At Risk, or Dormant
OrdersNumber of orders in the selected range matching configured revenue statuses
RevenueTotal revenue in store’s currency (partial refunds deducted)
AOVAverage order value
Reorder cycle (days)Mean days between consecutive orders
First orderDate of customer’s first order
Last orderDate of customer’s most recent order
Days since lastNumber of days since the most recent order

Spreadsheet Safety

CSV files can be exploited to execute formulas in spreadsheet applications. Customer Dashboard protects against this by neutralizing potentially dangerous characters.

If any field starts with =, +, @, -, tab, or carriage return, Customer Dashboard prefixes the field with a single quote ('). This prevents Excel, Google Sheets, and other apps from interpreting the field as a formula.

Without this protection, a customer with company name =SUM(1+1) could trigger unexpected formula execution. This is a known CSV injection attack vector.

The protection is invisible for normal data. It only activates on fields that would otherwise be unsafe.

UTF-8 Encoding

The CSV export uses UTF-8 encoding with a byte-order mark (BOM). This ensures international characters display correctly in:

  • Microsoft Excel
  • Google Sheets
  • Apple Numbers
  • LibreOffice Calc
  • Most modern text editors

Customers with international characters in names or companies export correctly without manual encoding adjustments.

Common Use Cases

  • Sharing with team members or accountants — Email the export to colleagues without admin access.
  • Analyzing in external tools — Import into Excel, Google Sheets, or a BI tool for deeper analysis. Pivot tables, charts, and cross-referencing work as expected.
  • Building outreach lists — Filter to At Risk or Dormant, then export. Use as the basis for a re-engagement email campaign.
  • Backup and recordkeeping — Periodic exports create snapshots of customer health over time.

Customer Table

Sortable Columns

The customer table supports sorting by any of these 7 columns:

ColumnSort behavior
CustomerAlphabetical by company name (if present) or display name
StatusActive → At Risk → Dormant
OrdersNumeric
RevenueNumeric (default sort, descending)
AOVNumeric
Last OrderBy date
Reorder CycleNumeric; customers with no cycle sort last

Click any column header to sort. Click again to reverse direction. The default sort is Revenue descending.

Tie-breaking

When two customers have the same value in the sorted column, ties are broken by:

  1. Display name (alphabetical ascending, case-insensitive)
  2. User ID (numeric ascending)

This ensures a stable, deterministic order across page loads and pagination.

Search and Filter

The search field matches against customer display name, company name, and email address. Combine search with the status filter pills (All, Active, At Risk, Dormant) and range pills to narrow results.

Pagination

The table shows 10 rows per page by default. The REST endpoint supports 5–100 rows per page via the per_page parameter.

REST API

Endpoint

GET /wp-json/kascado/v1/customers

Requires the manage_woocommerce capability. Returns the same data shown in the dashboard customer table.

Parameters

ParameterTypeDefaultAccepted values
statusstringallall, active, atrisk, dormant
searchstringemptyFree text (matches display name, company, email)
orderbystringrevenuecustomer, status, orders, revenue, aov, last_order, reorder_cycle
orderstringdescasc, desc
pageinteger1Minimum: 1
per_pageinteger105–100
rangestringytd30d, 90d, ytd, all

Response Shape

The response is a JSON object containing:

  • rows — Array of customer objects, each with: id, company, display_name, email, status, orders, orders_fmt, revenue_html, aov_html, last_order_date, days_since, days_since_text, reorder_cycle_days, reorder_cycle_text
  • counts — Object with keys all, active, atrisk, dormant showing totals for each status
  • total — Total matching rows (for pagination)
  • total_pages, page, per_page — Pagination metadata
  • filters — Echo of the active filter parameters
  • history_window — Object with years (integer), label (human-readable string like “last 2 years”), and constrained (boolean indicating whether the selected range extends beyond the history floor)

Need Help?

Can’t find what you’re looking for? Reach out to Kascado support and a team member will get back to you.

Contact Support