Each card shows a key business metric with a status color (healthy / watch / needs help / informational) and a button to fire the matching automation. Connect data sources to populate the numbers.
Charts that populate once tenant data is connected:
Monthly new customer trend
How customers found the business (lead source attribution)
Top ZIPs and neighborhoods for new customers
Customer loyalty tiers (jobs completed bands)
Year-over-year growth (signup year, recurring vs one-time)
Subscription plan mix detail
Cohort retention by signup year
Seasonal signup pattern
Historical charts render once data sources are connected.
📊 Average Stop Revenue
Basic intelligence about your routes — revenue per stop by day, by route, by ZIP. Identifies which routes generate the highest per-stop revenue. Connect data sources to populate.
📊 Revenue per Stop — By Day
No data — connect data sources to populate
📍 Revenue per Stop — By ZIP (Top 10)
No data — connect data sources to populate
📋 Revenue per Stop — By Service Type
No data — connect data sources to populate
📉 Route Profitability
Cost-per-stop comes from your operating expenses divided by total stops. Revenue comes from your payment data. Built for ownership decisions: keep the route, restructure it, cancel it, or adjust frequency. Connect data sources to populate.
📈 Route Profitability by Day and Route
📅 Daily Route Composition — What's Inside Each Route
⚠ Losing Routes — Cycle-Week Detail
📍 ZIP-Level Profitability
🔎 Decision Support — Where Action Is Needed
⚙ Route Inputs — Data Sources for Profitability Calculation
Route Profitability needs accurate inputs. This is where the data comes from. For multi-tenant deployment, this is where each business owner uploads their own numbers.
📊 Required Inputs — What Profitability Math Needs
Total Operating Expenses (year-to-date): Payroll, fuel, vehicle, insurance, software, rent. Pulled from accounting (QuickBooks, Xero, etc.) or uploaded manually.
Total Stops Completed (year-to-date): Number of customer service stops actually performed. Pulled from field-service software (GorillaDesk, Jobber, etc.) or uploaded.
Revenue per Stop (by day & route): Total revenue collected at each stop. Pulled from payment processor (Square, Stripe, etc.) or uploaded.
Route Schedule (day-by-day): Which routes run which days, how many trucks, how many runs per cycle. Pulled from field-service schedule.
Cycle-Week Rotation: If you use a 4-week rotating route schedule, the system needs to know which customers fall in which week.
📂 Connected Data Sources (For Your Tenant)
For the active tenant, these data sources are connected:
Payment processor:Status pending — will show: Connected / Disconnected once wired
Accounting:Status pending
Field-service software:Status pending
💾 Manual Upload (For New Tenants Without API Connections)
If a tenant doesn't have API-connected sources, upload the four required inputs as CSVs. Each tile accepts one file and shows status. Click Download Template to grab a starter file with the right column headers.
💵
Operating Expenses
Annual P&L breakdown by category
Pending
No file selected
🚚
Stops Completed
Year-to-date stops with date + route
Pending
No file selected
💰
Revenue per Stop
Total collected per service date
Pending
No file selected
📅
Route Schedule
Cycle-week rotation, days, trucks
Pending
No file selected
0 of 4 files uploaded
CSV files are parsed client-side first for column-header validation. On Apply, they upload to the tenant\'s data layer and trigger a recalculation of the Route Profitability tab.
🔗 Integrations — Live Data Sources
Drop GorillaDesk exports here and the dashboard refreshes live. No hardcoded numbers, no D1 cache — what you upload is what you see. Future API connections (WooCommerce, Square, QuickBooks) plug in here too.
📤 Drop GorillaDesk Export
📤
Drop a GorillaDesk CSV here
or click to choose a file
Supported: new_customers (*).csv from GorillaDesk export
✅ Currently Loaded
No data loaded. Drop a file above.
📊 QuickBooks — Live API
Click "Pull QB P&L" to fetch live operating-expense data from QuickBooks. This unlocks Route Profitability Margin (KPI 3).
🔒 Other Live API Connections
🛒 WooCommerce Off
Source of truth for: new orders, signup source, promos, recurring vs one-time
◯ Square Off
Source of truth for: live payments, declines, AR aging, refunds
📊 QuickBooks Live
Connected via occ-bi-api worker
🚚 GorillaDesk Live (CSV)
Source of truth for: route schedule, job status, completed cleanings
💎 Customer Lifetime Value
Estimated total revenue you'll earn from a customer over their full relationship with you. Calculation method: Average revenue per customer per year ÷ annual churn rate. Industry-standard formula. Connect data sources to populate.
💎 Lifetime Value Summary
Connecting to lifetime value endpoint…
Median Lifetime Value
—
across active customers
Top Decile Lifetime Value
—
90th percentile
Average Tenure
—
months active
Total Active Lifetime Value
—
portfolio value
🏆 Top 50 Customers by Lifetime Value
Click "Sync" to load top customers from live data
📊 Lifetime Value by Plan Type
Plan-type breakdown loads after sync
High-lifetime-value customers = highest satisfaction = best referral source
📊 Per-Customer P&L
Profit and loss broken down by individual customer. Revenue from payments minus allocated cost-to-serve (route share + extra-can handling + missed visits). Identifies the profitable customers, the marginal customers, and the unprofitable customers you may need to re-route, re-price, or release. Connect data sources to populate.
💸 Profitability Distribution
No data — connect data sources to populate
Profitable
—
contribution margin > $0
Marginal
—
margin between −$50 and $50
Unprofitable
—
contribution margin < -$50
Avg Margin / Customer
—
trailing 12 mo
⚠ Bottom 25 by Contribution Margin
🏆 Top 25 by Contribution Margin
Unprofitable customers in re-routable ZIPs → Route Profitability decisions
🔄 One-Time Customer Conversion
One-time customers tracked through their conversion window. The funnel: Day 0 (just had service) → Day 80 (final touch). After Day 80 with no conversion to recurring, they move to the Lost bucket.
🔄 Conversion Funnel
Connecting to one-time conversion endpoint…
In Funnel (Day 0–80)
—
awaiting conversion
Converted
—
one-time → recurring
Conversion Rate
—
trailing 90 days
Lost (past Day 80)
—
no conversion
Funnel Stages
Funnel stage breakdown loads after sync
One-time customers in funnel → activate drip sequence
💰 Pricing Intelligence
Compares your prices to comparable markets — same population size, similar income level, similar competition density. Tells you if you're under-priced (room to raise on new signups), at market (good), or over-priced (hurting conversion). The comparable-market dataset is research-driven; the framework is built and waiting for the research to be loaded.
📋 Pricing Catalog — Per-Cleaning Rates by Plan and Can Count
Your published rate matrix. New signups quote from this. Existing grandfathered customers stay at their original rate (locked rule).
No data — connect pricing source to populate
📊 Internal — Catalog Price vs Realized Average (Per Plan)
Catalog price = your published rate per cleaning. Realized average = what you're actually collecting per stop. Gap reveals grandfathered customers, prepaid bonuses, or pricing erosion.
No data — connect data sources to populate
🔎 Comparable Market Analysis — Research Pending
What this will show when the research dataset is loaded:
Comparable-market pricing range per plan/can-count combination
Your position: under market / at market / over market — by percentage
Estimated annual revenue opportunity if catalog rates align with market for new signups
Research methodology:
Match comparable markets by: city/town size, residential density, median household income, population
Pull actual competitor pricing per plan/can-count from those markets (not approximated, not guessed)
Filter to markets with similar income profile (avoid comparing high-income suburb to low-income market)
Status: Research project on the build queue. UI shell ready to receive the dataset.
💡 Decision Support — Pricing Actions
Locked rules (cannot be overridden by recommendations):
Catalog price applies to NEW signups only. Existing grandfathered customers stay at their original rate.
Bulk price increases on existing customers require explicit timing approval — never automated.
Specific price-action recommendations populate here once both the internal data is connected and the comparable-market research is loaded.
Multi-channel reactivation sequence for dormant customers (60+ days no activity). Email + SMS drip with progressively stronger offers — soft check-in → discount offer → final win-back. Auto-suppresses customers on the marketing-exclusions list.
⚙ Campaign Status
No data — connect data sources to populate
Dormant Customers
—
60+ days inactive
Eligible for Outreach
—
passes suppression rules
In Sequence Now
—
worker pending
Recovered MTD
—
customers returned
📋 Touch Sequence (configurable)
🛠 Trigger & Suppression Rules
Trigger: Customer status = dormant (no completed job in last 60 days) AND not on marketing-exclusions list AND has paid at least one invoice.
Frequency cap: Each customer can enter the win-back sequence once every 180 days. After completing the sequence (success or fail), they are locked out for 6 months.
Suppression: Customers in active dispute, with open support tickets, or flagged on the marketing-exclusions table are skipped automatically.
Conversion tracking: When a dormant customer schedules a new cleaning during the 21-day window or up to 14 days after the final touch, the sequence is marked converted and the credited touch logged for attribution.
⚙ Activation Controls
Last fire: never · Last sequence completion: never
Toggle and Fire Now button are wired. Real sequence runs against tenant data once they connect their customer database, email provider, and text-message provider.
📈 Active Dormant Upsell Worker Ready — Awaiting Tenant Connection
Truck-proximity-triggered upsell. When your truck is routed through a customer's neighborhood, the system pitches relevant upgrades. Quarterly customers are NOT targets — they chose quarterly for lowest cost. Real targets: bi-monthly → monthly upgrades, can-count expansion (extra cans observed by crew), add-on services.
⚙ Campaign Status
No data — connect data sources to populate
Bi-Monthly Targets
—
eligible for monthly upgrade
Can-Count Expansion
—
crew-flagged extra cans
Add-On Candidates
—
top-decile lifetime value
Converted MTD
—
worker pending
🎯 Targeting Tiers (configurable)
🛠 Trigger & Suppression Rules
Trigger: A truck route runs through a customer's neighborhood AND that customer matches a targeting tier AND has not received an upsell touch in the last 60 days.
NOT targeted: Quarterly customers. They picked quarterly for the lowest cost — pushing them to monthly is the wrong target.
Channels: Email (primary) and in-crew-app prompt during the cleaning visit.
Frequency cap: One upsell touch per customer per 60 days, regardless of which tier they qualify for.
Pricing rule: The published catalog price applies only to NEW signups. Existing grandfathered customers stay at their original rate even if they accept an upgrade.
⚙ Activation Controls
Last fire: never · Last upgrade: never
Toggle and Fire Now button are wired. Real campaign runs against tenant data once they connect their route schedule, customer database, and email provider.
Payment recovery worker handles declined-card retries, dunning emails, and overdue-invoice nudges. This panel shows live counts (and lets you trigger manual retry runs) once tenant payment + accounting data is connected.
⚙ Worker Status
Worker ready — not yet connected to tenant data
Declined YTD
—
cards declined
Overdue AR
—
accounting balance
Recovered MTD
—
retries succeeded
Active Dunning
—
in sequence
📋 Worker Behavior
Decline retry: Three attempts (T+0, T+3 days, T+7 days) before flagging for manual review.
Dunning sequence: Email at 7 / 14 / 21 / 28 days overdue, text at 14 days, phone-call task at 21 days.
Charge timing: Authorize at crew check-in, capture in the evening batch.
Suppression: Skip if the customer is in dispute or has an open support ticket.
Missed-cleaning / fuel fee charge: Auto-tracking and messaging run automatically, but the actual dollar charge requires owner approval per incident.
⚙ Activation Controls
Last fire: never · Last recovered: never
Toggle pauses the entire payment-follow-up sequence (decline retries + dunning + phone tasks). Manual Fire runs the retry sweep on demand against currently overdue accounts.
A drip sequence that nurtures one-time customers through the Day 0–80 conversion window with timed email and text touches designed to convert them to a recurring plan.
⚙ Worker Status
Worker ready — not yet connected to tenant data
In Drip
—
currently active
Converted MTD
—
one-time → recurring
Email Open Rate
—
drip avg
Avg Time to Convert
—
days from one-time job
📋 Drip Schedule
Day 1: Thank-you / "Did everything go well?" email
Day 7: Recurring-plan benefits email — soft pitch
Day 21: Discount offer — "10% off your first 3 cleanings if you go recurring"
Day 45: Social-proof email — neighborhood testimonials
Day 80: Final offer — last chance for the discount before the customer exits the funnel
Schedule, copy, and discount amounts are draft — tenant configures their own.
⚙ Activation Controls
Last fire: never · Last converted: never
Toggle pauses the entire one-time drip sequence (all 5 touches). Manual Fire runs a sweep on demand against every one-time customer currently inside the Day 0–80 conversion window.
Referral attribution and reward worker. Tracks customers who came in via word-of-mouth, attributes each new customer back to their referring customer, and triggers the configured credit reward automatically.
⚙ Worker Status
Worker ready — not yet connected to tenant data
Referrals YTD
—
attributed customers
Top Referrers
—
5+ referrals each
Credits Issued
—
YTD
Avg Tenure
—
referred customers
📋 Reward Mechanics
Trigger: A new customer whose lead source is "word of mouth" and who names a referring customer.
Reward: Credit automatically applied to the referrer's next invoice (amount configurable).
Two-sided bonus: The referred customer gets a discount on their first cleaning.
Top referrers: Tracked for VIP recognition (potential annual gift or extra perk).
Reward amounts and bonus structure are tenant-configurable.
⚙ Activation Controls
Last fire: never · Last credit issued: never
Toggle pauses referral attribution and credit issuance. Manual Fire sweeps recently-added customers, attributes any whose lead source is "word of mouth" with a referrer name, and issues the configured credit reward.
Editor
Editor
Saved — will persist once data sources are connected