📊 Reporting & KPI Playbook
Bright Side Plumbing
Revenue Intelligence System
Every metric, every formula, every report template. Built for one purpose: tracing dollars from ad click to closed job, and scaling $3M to $6M.
"We are not interested in activity-based reporting. We are interested in revenue-tied performance."
— Bright Side Leadership
🏢 Bright Side Plumbing · Overland Park, KS
💰 Revenue: $3M → $6M
📣 Marketing: $35K/mo
🎯 CPL Target: $200
📞 Booking Rate: 80%
⚙️ CRM: ServiceTitan
📈 GA4: 298578347
🔍 Ads: 7269555791
SECTION 01
🎯 KPI Dashboard Architecture
Ten KPIs that directly tie to revenue growth. No vanity metrics. Every number connects to dollars in or dollars out.
💵 1. Revenue Per Week
Total Invoiced Revenue / Weeks in Period
Source: ServiceTitan → Revenue Report
Target: $77K/week ($4M pace) → $96K/week ($5M) → $115K/week ($6M)
Current: ~$57.7K/week ($3M pace)
🚨 Red Flag: < $50K/week (below $2.6M pace)
💲 2. Cost Per Lead (by Source)
Total Spend on Source / Total Leads from Source
Source: Google Ads, LSA Dashboard, Vendor invoices
Target: ≤ $200 blended CPL
🚨 Red Flag: CPL > $300 on any single source
📈 3. ROAS by Campaign
Revenue Attributed to Campaign / Spend on Campaign
Source: ServiceTitan revenue + Google Ads spend (GCLID bridge)
Target: ≥ 5:1 ROAS blended
🚨 Red Flag: < 3:1 ROAS on any campaign running > 30 days
📞 4. Booking Rate
Booked Jobs / Total Inbound Calls + Forms
Source: ServiceTitan → CSR Booking Report
Target: ≥ 80%
🚨 Red Flag: < 70% (CSR coaching needed)
💳 5. Average Ticket
Total Revenue / Total Completed Jobs
Source: ServiceTitan → Job Costing Report
Target: ≥ $450 (services), ≥ $8,000 (sewer)
🚨 Red Flag: Avg ticket drops > 15% MoM
📝 6. Close Rate
Won Estimates / Total Estimates Presented
Source: ServiceTitan → Estimate Report
Target: ≥ 40% (general), 30-40% (sewer)
🚨 Red Flag: < 25% on sewer, < 35% general
📥 7. Lead Volume
Count of Unique Leads (deduplicated) per Period
Source: ServiceTitan + all lead source platforms
Target: ≥ 263/month (Feb 2026 baseline: LSA 19, SD 126, SLP 80, Networx 38)
🚨 Red Flag: < 200/month or zero leads in any 24-hour window
👁️ 8. Impression Share
Your Impressions / Total Eligible Impressions
Source: Google Ads → Auction Insights
Target: ≥ 70% on brand, ≥ 40% on core service terms
🚨 Red Flag: < 30% impression share on "plumber overland park"
⭐ 9. Quality Score Average
Sum of Keyword QS / Total Active Keywords
Source: Google Ads → Keywords tab → Quality Score column
Target: ≥ 7/10 average
🚨 Red Flag: < 5/10 average (landing page and ad relevance issues)
👥 10. Customer Acquisition Cost
Total Marketing Spend / New Customers Acquired
Source: All spend sources + ServiceTitan new customer count
Target: ≤ $350 blended CAC
🚨 Red Flag: CAC > $500 (profitability at risk)
💡 Key Principle: Every KPI must answer "how does this connect to revenue?" If it does not, it is a vanity metric and does not belong on the dashboard.
SECTION 02
🔍 Revenue Attribution Model
The GCLID-to-revenue pipeline. How to trace any dollar of revenue back to the exact ad click that started the journey.
🔗 The Full Attribution Chain
🖱️ Ad Click
User clicks Google Ad
→
🍪 GCLID Cookie
Stored in browser
→
📝 Form Submit
GCLID captured in hidden field
→
🌌 GCLID Bridge
PHP proxy passes to ST
→
⚙️ ServiceTitan
Lead created with source tag
→
💰 Offline Conversion
Revenue uploaded to Google Ads
🔧 How Each Step Works
Step 1: Ad Click Captures GCLID
- Google appends
?gclid=ABC123 to the landing page URL automatically
- GTM container
GTM-M3L9374 fires on page load and reads the GCLID parameter
- GCLID is stored in a first-party cookie (
_gcl_aw) with 90-day expiry
Step 2: Form Submission Captures GCLID
- All web forms include a hidden field:
<input type="hidden" name="gclid" id="gclid">
- JavaScript auto-populates this field from the cookie on form load
- On submit, GCLID travels with the lead data to the form processor
Step 3: GCLID Bridge (PHP Proxy)
- File:
wp_gclid_bridge_proxy.php on the WordPress installation
- Receives form data + GCLID, formats it for ServiceTitan's booking API
- Creates lead in ServiceTitan with the GCLID stored in a custom field
- Logs every bridge transaction for audit trail
Step 4: ServiceTitan to Revenue
- CSR books the job. Tech runs the job. Invoice is completed.
- ServiceTitan records the revenue on the job, linked to the original lead
- Custom report pulls: Lead Source + GCLID + Revenue
Step 5: Offline Conversion Upload
- Nexus automation pulls completed jobs with GCLIDs from ServiceTitan
- Formats data as Google Ads Offline Conversion Import CSV
- Uploads to Google Ads account
726-955-5791 via API
- Google Ads now shows actual revenue per keyword, ad, campaign
🔎 How to Trace Any Dollar to Its Source
Revenue Trace Procedure
- Start in ServiceTitan: Open the completed job. Find the Lead record. Note the Lead Source and any GCLID custom field value.
- If GCLID exists: Go to Google Ads → Tools → Conversions → Uploads. Search for the GCLID. This shows you the exact keyword, ad group, campaign, and click time.
- If no GCLID (phone lead): Check the calling tracking number. Map it to the campaign using the call tracking number mapping table (see LSA section).
- If lead source = "Service Direct" or "Networx": Cross-reference the lead timestamp with the vendor dashboard. Match by phone number or name.
- Document in the attribution log: Job # | Revenue | Lead Source | Campaign | Keyword | GCLID | Date
⚠️ Known Gap: Phone calls from Google Ads that do not hit the website (call-only ads, call extensions) bypass the GCLID bridge. These must be attributed via call tracking number mapping. Current coverage is ~75% of Google Ads leads. Target: 95%.
SECTION 03
📋 Weekly Report Template
Delivered every Monday by 10 AM. No fluff. Revenue first, action items last. This is what Stephanie sees.
📧 Subject Line Format
BSP Weekly | Week of [DATE] | Revenue: $[XX]K | CPL: $[XX] | [UP/DOWN] arrow vs last week
Section 1: Executive Summary (3 bullets max)
Template
- Revenue this week: $[XX,XXX] ([+/-]XX% vs last week, [+/-]XX% vs target of $77K)
- Lead volume: [XX] leads at $[XXX] blended CPL ([+/-]XX% vs $200 target)
- Biggest win / Biggest concern: [One sentence each]
Section 2: Revenue vs Target
| Metric | This Week | Last Week | WoW Change | Target | Status |
| Total Revenue | $___ | $___ | ___% | $77,000 | 🟢/🟡/🔴 |
| Completed Jobs | ___ | ___ | ___% | ___ | 🟢/🟡/🔴 |
| Avg Ticket | $___ | $___ | ___% | $450+ | 🟢/🟡/🔴 |
| Booked Jobs | ___ | ___ | ___% | ___ | 🟢/🟡/🔴 |
🟢 On Track = within 10% of target 🟡 Watch = 10-25% below 🔴 Action Needed = >25% below
Section 3: Lead Volume by Source
| Source | Leads | WoW Change | Spend | CPL | CPL Target | Status |
| Google Ads | ___ | ___% | $___ | $___ | $200 | |
| LSA | ___ | ___% | $___ | $___ | $150 | |
| Service Direct | ___ | ___% | $___ | $___ | $150 | |
| Service Local Pro | ___ | ___% | $___ | $___ | $175 | |
| Networx | ___ | ___% | $___ | $___ | $175 | |
| TOTAL | ___ | ___% | $___ | $___ | $200 | |
Section 4: CPL by Source (Trend Sparkline)
Include a 4-week rolling CPL trend for each source. Flag any source where CPL has increased >20% over the 4-week window.
Section 5: Top Campaigns
Format: Top 5 by Revenue Generated
- [Campaign Name]: $[Revenue] from $[Spend] = [X]:1 ROAS | [XX] leads at $[CPL]
- ... (repeat for top 5)
Bottom 3 by ROAS (Candidates for Pause/Rework)
- [Campaign Name]: $[Revenue] from $[Spend] = [X]:1 ROAS | Recommendation: [Pause / Rework / Monitor]
Section 6: Action Items
Format
- ✅ [Action] | Owner: [Name] | Deadline: [Date] | Impact: [Expected result]
- ✅ Max 5 action items per week. Each must be specific and measurable.
🚫 What does NOT go in the weekly report: Impressions without context, click-through rates without revenue tie, "brand awareness" metrics, social media follower counts, keyword rankings without traffic/revenue data.
SECTION 04
📅 Monthly Report Template
Delivered by the 3rd business day of each month. Covers trends, efficiency, and forward-looking recommendations.
Report Structure
1. Monthly Revenue Summary
| Metric | This Month | Last Month | MoM Change | Same Month Last Year | YoY Change |
| Total Revenue | $___ | $___ | ___% | $___ | ___% |
| Total Leads | ___ | ___ | ___% | ___ | ___% |
| Blended CPL | $___ | $___ | ___% | $___ | ___% |
| Total Spend | $___ | $___ | ___% | $___ | ___% |
| Blended ROAS | ___:1 | ___:1 | ___% | ___:1 | ___% |
| Avg Ticket | $___ | $___ | ___% | $___ | ___% |
| Booking Rate | ___% | ___% | ___pts | ___% | ___pts |
| Close Rate | ___% | ___% | ___pts | ___% | ___pts |
2. Trend Analysis (MoM Comparison)
- Revenue trajectory: Are we accelerating or decelerating? Plot last 6 months.
- CPL trajectory: Is efficiency improving? Plot blended CPL by source over 6 months.
- Lead volume trajectory: Are we getting more leads or fewer? Break down by source.
- Seasonality comparison: How does this month compare to same month prior year?
3. Budget Efficiency Analysis
Budget Efficiency Score = (Revenue Generated / Total Marketing Spend) x 100
Target: Score of 500+ (meaning $5 revenue for every $1 spent)
- Break down spend by channel with revenue attributed to each
- Identify the highest and lowest ROI channels
- Calculate marginal CPL (cost of the next incremental lead from each source)
4. Recommendations (3 max, prioritized by revenue impact)
Recommendation Format
Recommendation #[X]: [One-sentence recommendation]
- Why: [Data that supports this]
- Expected Impact: [Projected revenue or cost impact]
- Effort: [Low / Medium / High]
- Timeline: [When we would see results]
5. Revenue Forecast (Next 30 Days)
Forecast = (Current Month Revenue / Days Elapsed) x Days in Next Month
Adjusted Forecast = Forecast x Seasonality Index x Trend Factor
- Provide low / mid / high range estimates
- Flag if forecast suggests we will miss the weekly target for next milestone
SECTION 05
🏦 Quarterly Business Review Template
Presented to Stephanie and Kalen. Big picture. Revenue trajectory. Where the money went and what it produced. What is the plan for next quarter.
QBR Agenda (45 Minutes)
Slide Deck Structure
- Revenue Scorecard (5 min): Q revenue vs target, weekly average, trajectory to $4M/$5M/$6M
- Marketing ROI Summary (10 min): Total spend, total attributed revenue, blended ROAS, CPL by source, CAC
- Channel Deep Dive (10 min): Google Ads performance, LSA performance, lead aggregator performance, organic growth
- Competitive Position (5 min): Impression share trends, new competitors, market changes
- Wins and Losses (5 min): Top 3 wins this quarter, top 3 challenges, lessons learned
- Next Quarter Plan (10 min): Budget allocation recommendation, campaign strategy, growth initiatives, KPI targets
Key QBR Metrics Table
| Metric | Q Target | Q Actual | Variance | Prior Q | QoQ Trend |
| Quarterly Revenue | $___ | $___ | ___% | $___ | ↑/↓ |
| Total Marketing Spend | $105K | $___ | ___% | $___ | |
| Marketing-Attributed Revenue | $___ | $___ | ___% | $___ | |
| Blended ROAS | 5:1 | ___:1 | | ___:1 | |
| Total Leads | ___ | ___ | ___% | ___ | |
| Blended CPL | $200 | $___ | ___% | $___ | |
| New Customers | ___ | ___ | ___% | ___ | |
| CAC | $350 | $___ | ___% | $___ | |
Revenue Trajectory Visualization
Include a chart showing:
- Monthly revenue bars for the last 12 months
- Trend line with projection forward
- Horizontal lines at $77K/week ($4M), $96K/week ($5M), $115K/week ($6M)
- Estimated milestone hit dates at current growth rate
Next Quarter Budget Recommendation
Format
| Channel | Current Monthly | Recommended | Change | Rationale |
| Google Ads | $___ | $___ | $___ | [Based on ROAS data] |
| LSA | $___ | $___ | $___ | [Based on booking rate] |
| Service Direct | $___ | $___ | $___ | [Based on CPL + close rate] |
| Service Local Pro | $___ | $___ | $___ | [Based on lead quality] |
| Networx | $___ | $___ | $___ | [Based on ROI data] |
| Total | $35,000 | $___ | $___ | |
SECTION 06
📣 Google Ads Reporting
Account 726-955-5791 in MCC 844-909-2450. Every report ties spend to revenue.
💰 Campaign-Level ROAS Report
CLICK PATH
- Log into Google Ads → Select account
726-955-5791
- Navigate to Campaigns in left sidebar
- Click Columns → Modify Columns
- Add: Conversions, Conv. Value, Cost, Conv. Value / Cost (this is ROAS)
- Add: All Conv., All Conv. Value (captures offline conversions)
- Set date range to last 30 days
- Sort by All Conv. Value descending
- Export to Google Sheets for trend tracking
🔍 Keyword Performance: Top and Bottom
CLICK PATH
- Go to Keywords → Search Keywords
- Add columns: Quality Score, Conv. Value, Cost, Conv. Rate
- Create two saved views:
- "Top Performers": Filter by Conv. Value > $0, Sort by Conv. Value descending, Top 20
- "Bottom Performers": Filter by Cost > $100, Conv. Value = $0, Sort by Cost descending
- Bottom performers are candidates for pause or negative keyword addition
🔎 Search Term Analysis
CLICK PATH
- Go to Keywords → Search Terms
- Set date range to last 14 days
- Sort by Impressions descending
- Review for: irrelevant terms (add as negatives), high-converting terms (add as exact match keywords), competitor terms (evaluate or negate)
- Export and categorize into: ✅ Keep, ⛔ Negate, 🔍 Monitor
- Weekly cadence: Do this every Monday as part of optimization routine
⭐ Quality Score Tracking
| QS Component | What It Measures | How to Improve | Target |
| Ad Relevance | How closely ad copy matches keyword intent | Tighten ad groups, improve copy match | Above Average |
| Expected CTR | Predicted click-through rate vs competitors | Stronger headlines, better extensions | Above Average |
| Landing Page Experience | Page relevance, speed, mobile-friendliness | Dedicated landing pages per service | Above Average |
QS Impact on CPC: A keyword with QS 10 can pay ~50% less per click than QS 5.
Monthly Savings = (Avg CPC at QS 5 - Avg CPC at QS 8) x Monthly Clicks
Track average QS weekly. Target: improve from current avg to 7+ within 90 days.
🏆 Auction Insights Trends
CLICK PATH
- Go to Campaigns → Select all active campaigns
- Click Auction Insights tab at top
- Segment by Week to see trends
- Track: Impression Share, Overlap Rate, Outranking Share
- Identify: Who is gaining share? Who is new? Who is losing share?
- Export monthly and chart impression share trend for top 5 competitors
SECTION 07
📞 LSA Reporting
Local Services Ads. February 2026 baseline: 19 leads. The lowest-volume but potentially highest-trust channel.
🎯 Lead Quality Scoring System
| Score | Label | Criteria | Action |
| A | 🟢 High Quality | Correct service area, valid need, answered/booked | No action needed |
| B | 🟡 Moderate | Correct area but did not book (schedule conflict, price, etc.) | Follow up within 24h |
| C | 🟠 Low Quality | Out of service area, wrong service type | Dispute the charge |
| D | 🔴 Spam/Fake | Robo-call, competitor, no real customer | Dispute immediately |
💲 Key LSA Metrics
Cost Per Booked Job = Total LSA Spend / Jobs Actually Booked from LSA
LSA Booking Rate = Booked Jobs / Total LSA Leads
LSA Revenue per Lead = Total Revenue from LSA Jobs / Total LSA Leads
⚡ Dispute Tracking
CLICK PATH
- Go to Local Services Ads dashboard (ads.google.com/localservices)
- Click Leads tab
- Listen to each call recording (yes, every one)
- For any lead scored C or D: Click the three dots next to the lead → Dispute
- Select reason: "Wrong service type", "Spam", "Bot/solicitor", or "Out of service area"
- Submit dispute within 30 days of the lead (Google's deadline)
- Track: Disputes submitted, disputes won, dollars recovered
Dispute Recovery Rate = Successful Disputes / Total Disputes Submitted
Monthly Savings from Disputes = Recovered Credits / Total LSA Spend
Target: Dispute at least 15-20% of leads, win 70%+ of disputes
📊 Profile Optimization Score
| Factor | Weight | Current Status | Action if Missing |
| Google Guarantee badge | Critical | ✅ Active | Ensure insurance/license current |
| Review count (50+) | High | Check monthly | Push review collection campaigns |
| Review rating (4.5+) | High | Check weekly | Address negative reviews ASAP |
| Response rate (<1 hour) | High | Track via ST | Train CSRs on speed-to-lead |
| Business hours set correctly | Medium | Verify monthly | Match actual availability |
| Service types (all checked) | Medium | Verify quarterly | Add all applicable services |
| Photos (10+ uploaded) | Low | Check quarterly | Upload job photos |
SECTION 08
⚙️ ServiceTitan Reporting
ServiceTitan is the single source of truth for revenue. Every report in this playbook ultimately connects back to ST data.
💰 Revenue by Lead Source
SERVICETITAN CLICK PATH
- Navigate to Reports → Marketing → Marketing ROI
- Set date range (weekly for weekly report, monthly for monthly)
- Group by: Business Unit then Campaign/Lead Source
- Key columns: Leads, Booked Jobs, Revenue, Avg Ticket, Booking Rate
- Export to CSV for Looker Studio integration
👷 Tech Performance Report
SERVICETITAN CLICK PATH
- Navigate to Reports → Technician Performance
- Key metrics per tech: Revenue Generated, Avg Ticket, Opportunities Presented, Close Rate, Membership Conversions
- Red flag: Any tech with close rate <30% or avg ticket >25% below team average
- Use for: Tech coaching conversations, bonus calculations, routing optimization
📞 Booking Rate by CSR
SERVICETITAN CLICK PATH
- Navigate to Reports → Call Booking
- Group by: CSR Name
- Key metrics: Total Calls Handled, Booked, Not Booked, Booking Rate
- Target: 80%+ booking rate per CSR
- Listen to "Not Booked" calls for coaching opportunities
- Red flag: Any CSR below 70% needs immediate coaching
💳 Average Ticket by Service Type
SERVICETITAN CLICK PATH
- Navigate to Reports → Job Costing or Revenue Report
- Group by: Job Type / Business Unit
- Track avg ticket for: Drain Cleaning, Water Heater, Sewer Repair, Sewer Replacement, General Plumbing, Emergency
- Compare MoM for pricing power trends
✅ Job Completion Rate
Job Completion Rate = Completed Jobs / Total Dispatched Jobs
Target: ≥ 95%
Red Flag: < 90% (indicates scheduling, parts, or customer no-show issues)
SERVICETITAN CLICK PATH
- Navigate to Reports → Job Report
- Filter: Status = All (Completed, Canceled, Rescheduled)
- Calculate completion rate manually or via custom report
- For cancellations: tag reason codes to identify patterns
SECTION 09
📊 GA4 Custom Reports
GA4 Property: 298578347. GTM Container: GTM-M3L9374. Every event must connect to a revenue action.
🎯 Core Conversion Events
| Event Name | Trigger | GTM Tag | Value |
form_submit | Any lead form submission | Form Submit Trigger (CSS selector or dataLayer push) | Estimated lead value ($200) |
phone_click | Click on tel: link (mobile or desktop) | Click trigger on href contains "tel:" | Estimated lead value ($200) |
chat_start | User initiates live chat / chatbot | Custom event from chat widget callback | Estimated lead value ($100) |
🔧 GA4 Conversion Setup (Click-by-Click)
Setting Up form_submit Event
GTM SETUP
- Open Google Tag Manager → Container
GTM-M3L9374
- Go to Tags → New
- Tag Type: Google Analytics: GA4 Event
- Configuration Tag: Select your GA4 Configuration tag
- Event Name:
form_submit
- Event Parameters: Add
form_type = {{Form ID}}, page_url = {{Page URL}}
- Trigger: Create new trigger → Form Submission → Some Forms → Form ID contains "contact" or use CSS selector for your forms
- Save → Preview to test → Submit
Setting Up phone_click Event
GTM SETUP
- Tags → New → GA4 Event
- Event Name:
phone_click
- Trigger: New → Click - Just Links → Some Link Clicks → Click URL contains
tel:
- Event Parameters:
phone_number = {{Click URL}}, click_location = {{Page URL}}
- Preview, verify, submit
Setting Up chat_start Event
GTM SETUP
- This depends on the chat widget. Most widgets fire a JavaScript callback when chat opens.
- In GTM: Create a Custom HTML tag that listens for the chat widget's open event
- Push to dataLayer:
dataLayer.push({event: 'chat_start'})
- Create GA4 Event tag triggered by Custom Event =
chat_start
📏 Custom Dimensions
| Dimension | Scope | How to Populate | Use Case |
lead_source | Event | UTM parameter or referrer logic in GTM | Segment form submissions by where the user came from |
service_type | Event | Form field value (which service did they select) | See which services generate the most leads from the website |
Registering Custom Dimensions in GA4
GA4 ADMIN
- Go to GA4 → Admin → Custom Definitions
- Click Create Custom Dimension
- Dimension Name:
Lead Source
- Scope: Event
- Event Parameter:
lead_source
- Save. Repeat for
service_type.
📊 Marking Events as Conversions
GA4 ADMIN
- Go to GA4 → Admin → Events
- Wait for events to appear (may take 24-48 hours after GTM setup)
- Find
form_submit → Toggle Mark as conversion ON
- Repeat for
phone_click and chat_start
- These will now appear in the Conversions report and can be imported to Google Ads
SECTION 10
💻 Looker Studio Dashboard Build
Six-page dashboard that Stephanie can check any time without asking for a report.
🔧 Data Source Connections
Connect GA4
LOOKER STUDIO
- Go to lookerstudio.google.com
- Click Create → Data Source
- Search for Google Analytics connector
- Select GA4 property
298578347 (Bright Side Plumbing)
- Click Connect
- Review fields. Rename as needed for clarity. Click Create Report or Add to Report
Connect Google Ads
LOOKER STUDIO
- Add Data Source → Search Google Ads
- Select account
726-955-5791
- Choose Campaign level data (gives campaign, ad group, keyword breakdowns)
- Connect → Add to report
Connect Google Sheets (ServiceTitan Data Bridge)
LOOKER STUDIO
- Create a Google Sheet that receives weekly ServiceTitan exports
- Sheet columns: Date, Lead Source, Leads, Booked Jobs, Revenue, Avg Ticket, Completed Jobs
- In Looker Studio: Add Data Source → Google Sheets → Select the sheet
- This bridges ServiceTitan data into Looker Studio since there is no native ST connector
- Automate the export via Nexus cron job (see Section 12)
📄 Six Dashboard Pages
Page 1: Overview
- Scorecards (top row): Revenue This Week, Blended CPL, Total Leads, Booking Rate, ROAS
- Chart: Time series line chart of weekly revenue (12 weeks)
- Chart: Donut chart of leads by source
- Chart: Bar chart of CPL by source
- Filter: Date range selector
Page 2: Google Ads
- Scorecards: Spend, Clicks, CPC, Conversions, Conv Value, ROAS
- Table: Campaign performance (sortable by Conv Value)
- Chart: Time series of spend vs conversion value
- Chart: Stacked bar of conversions by campaign
- Filter: Campaign type, date range
Page 3: LSA
- Scorecards: LSA Leads, LSA Spend, Cost Per Booked Job, Booking Rate
- Table: Lead list with quality score (from Sheets bridge)
- Chart: Weekly LSA leads trend
- Chart: Dispute success rate (pie chart)
- Filter: Date range, quality score
Page 4: Revenue
- Scorecards: Total Revenue, Revenue This Week, Avg Ticket, Close Rate
- Chart: Revenue by service type (stacked bar)
- Chart: Revenue trend line with $4M/$5M/$6M pace lines
- Table: Revenue by lead source
- Filter: Date range, service type, lead source
Page 5: Leads
- Scorecards: Total Leads, Blended CPL, Booking Rate, CAC
- Chart: Leads by source over time (stacked area)
- Chart: CPL by source over time (multi-line)
- Table: Source-level breakdown with all KPIs
- Filter: Date range, source, service type
Page 6: Executive
- Design: Clean, minimal. Stephanie and Kalen see this page.
- Scorecards: Revenue (big number), ROAS, CPL, Revenue vs Target %
- Chart: Monthly revenue bars with target line
- Chart: Revenue milestone progress gauge
- Text: Auto-generated summary (from Sheets formula)
- No filters: Always shows current month + trailing 3 months
💡 Pro Tip: Add a "Last Updated" text field on every page that pulls from a cell in the Google Sheet. This shows Stephanie the data is fresh without her having to ask.
SECTION 11
📊 Lead Source ROI Comparison
February 2026 baseline data, side-by-side. Which sources earn their keep and which need to be renegotiated or cut.
💰 Full Source Comparison Table
| Source |
Feb Leads |
Est. Monthly Cost |
CPL |
Booking Rate |
Booked Jobs |
Close Rate |
Won Jobs |
Est. Revenue |
ROAS |
| Google Ads |
~50* |
~$15,000 |
~$300 |
80% |
~40 |
35% |
~14 |
~$28,000 |
1.9:1 |
| LSA |
19 |
~$2,850 |
~$150 |
80% |
~15 |
35% |
~5 |
~$10,000 |
3.5:1 |
| Service Direct |
126 |
~$16,380 |
$105-200 |
80% |
~101 |
35% |
~35 |
~$70,000 |
4.3:1 |
| Service Local Pro |
80 |
~$12,000 |
~$150 |
80% |
~64 |
35% |
~22 |
~$44,000 |
3.7:1 |
| Networx |
38 |
~$5,700 |
~$150 |
80% |
~30 |
35% |
~11 |
~$22,000 |
3.9:1 |
| TOTAL |
~313 |
~$51,930 |
~$166 |
80% |
~250 |
35% |
~87 |
~$174,000 |
3.4:1 |
*Google Ads lead count is estimated. Actual GCLID-attributed leads will be confirmed once the offline conversion pipeline is fully operational. Revenue estimates use $2,000 blended average ticket.
📏 ROI Formulas Used
CPL = Total Source Spend / Total Leads from Source
Booked Jobs = Leads x Booking Rate
Won Jobs = Booked Jobs x Close Rate
Estimated Revenue = Won Jobs x Avg Ticket ($2,000 blended)
ROAS = Estimated Revenue / Total Source Spend
CAC per Source = Total Source Spend / Won Jobs
🚨 Key Findings
Google Ads CPL is highest at ~$300. Before cutting, check: (1) Are sewer leads coming from Google Ads? Sewer jobs avg $8K+ ticket, which would dramatically improve ROAS. (2) Is the GCLID bridge capturing all conversions? If not, revenue attribution is understated.
Service Direct is the volume leader (126 leads/mo). At $105-200/lead with per-lead pricing, this is controllable cost. Negotiate volume discounts. Verify lead quality is consistent.
LSA is under-scaled. Only 19 leads in February. With the lowest CPL and Google Guarantee trust, this should be scaled aggressively. Target: 50+ LSA leads/month within 90 days.
SECTION 12
🤖 Automated Reporting Pipeline
Nexus automation handles the boring parts. Humans handle the analysis and decisions.
📨 Daily Briefing (Nexus)
Delivered: Every day at 7:00 AM CT via Slack #bsp-reporting
Contents:
- Yesterday's revenue (from ServiceTitan export)
- Yesterday's lead count by source
- Spend so far this month vs budget pace
- Any alerts triggered (see Section 13)
- Week-to-date revenue vs $77K target
🔔 Slack Alerts (Real-Time)
| Alert | Channel | Trigger | Message Format |
| 🔴 Zero Leads | #bsp-alerts | No new leads in 24 hours | "🚨 ALERT: No leads received in the last 24 hours. Last lead: [timestamp]. Check all sources." |
| 🟡 CPL Spike | #bsp-alerts | Any source CPL > $300 | "⚠️ [Source] CPL hit $[XX] (target: $200). Investigate." |
| 🔴 Budget Overpace | #bsp-alerts | Spend pace > 110% of monthly budget | "🚨 Google Ads on pace to overspend by $[XX]. Current daily: $[XX] vs target $[XX]." |
| 🟢 Revenue Milestone | #bsp-wins | Weekly revenue crosses threshold | "🎉 Revenue hit $[XX]K this week! On pace for $[X]M annualized." |
| 🔴 Conversion Drop | #bsp-alerts | Conversion rate drops >20% WoW | "🚨 Conversion rate dropped from [X]% to [X]%. Check landing pages and forms." |
📧 Email Digests
| Digest | Recipients | Frequency | Content |
| Weekly Performance | Stephanie, Kalen, Robert | Monday 10 AM CT | Full weekly report (Section 3) |
| Monthly Recap | Stephanie, Kalen, Robert | 3rd business day | Full monthly report (Section 4) |
| Daily Revenue Flash | Robert | Daily 7 AM CT | Yesterday's revenue + WTD total |
⏰ Cron Schedule (Nexus VM)
# Nexus Reporting Cron Jobs (nexus-vm, 34.55.179.122)
# All times in US/Central
0 7 * * * /opt/nexus/scripts/daily_briefing.sh # Daily briefing at 7 AM
0 10 * * 1 /opt/nexus/scripts/weekly_report.sh # Weekly report Monday 10 AM
0 8 1-5 * * /opt/nexus/scripts/monthly_check.sh # Monthly report check (1st-5th)
*/15 * * * * /opt/nexus/scripts/alert_monitor.sh # Alert check every 15 minutes
0 6 * * * /opt/nexus/scripts/st_export.sh # ServiceTitan data export 6 AM
0 2 * * * /opt/nexus/scripts/offline_conversion_upload.sh # Offline conversion upload 2 AM
🔄 Data Flow Diagram
⚙️ ServiceTitan
Revenue + Lead data
→
📤 Nexus Export
6 AM daily cron
→
📊 Google Sheets
Bridge layer
→
💻 Looker Studio
Auto-refreshes
📊 Google Ads API
Spend + performance
→
🤖 Nexus Processor
Joins ST + Ads data
→
🔔 Slack / Email
Alerts + digests
SECTION 13
🚨 Alert Thresholds
Automated guardrails. When numbers go sideways, the system tells us before the client does.
🔴 Critical Alerts (Immediate Action Required)
| Condition | Threshold | Response | Response Time |
| Zero leads in 24 hours |
0 leads across all sources for 24h |
Check all source dashboards. Verify website forms are working. Check tracking is firing. Contact vendors if their leads stopped. |
Within 1 hour of alert |
| CPL exceeds $500 (any source) |
CPL > $500 over trailing 7 days |
Pause or reduce spend on that source. Investigate: Did leads dry up? Did costs spike? Is tracking broken? |
Within 2 hours |
| Website down |
HTTP status != 200 for > 5 minutes |
All ads are sending traffic to a dead page. Pause ads if not resolved in 15 minutes. Contact hosting. |
Within 15 minutes |
| Google Ads account suspended |
Account status change |
Immediate appeal process. Shift budget to LSA and aggregators. Notify Stephanie. |
Within 30 minutes |
🟡 Warning Alerts (Investigate Within 24 Hours)
| Condition | Threshold | Response |
| CPL exceeds $300 (any source) |
CPL > $300 over trailing 7 days |
Review search terms, check for click fraud, evaluate keyword bids, check landing page conversion rate |
| Budget pace > 110% |
Projected monthly spend exceeds budget by >10% |
Reduce daily budgets, tighten bid strategy, pause underperforming campaigns |
| Conversion rate drop > 20% |
7-day conv rate is >20% below prior 7 days |
Check: landing page changes, form functionality, phone tracking, competitor moves |
| Booking rate below 70% |
Weekly booking rate drops below 70% |
Review CSR call recordings, check for lead quality shift, review after-hours call handling |
| Impression share drops > 15% |
Week-over-week IS drop on core terms |
Check: new competitors, budget constraints, quality score changes, bid adjustments |
🟢 Positive Alerts (Celebrate and Scale)
| Condition | Threshold | Action |
| Weekly revenue exceeds $77K |
$77K+ in a single week |
Celebrate in Slack. Document what worked. Consider scaling the winning channels. |
| CPL drops below $150 (any source) |
CPL < $150 trailing 7 days |
Consider increasing budget for that source to capture more volume at efficient cost. |
| Close rate exceeds 45% |
Weekly close rate > 45% |
Recognize the sales team. Document the approach. Consider if a specific campaign is driving higher-intent leads. |
🔧 Alert Implementation
# Alert logic pseudocode (alert_monitor.sh)
# Check lead volume
leads_24h=$(query_servicetitan "leads WHERE created > NOW() - 24h")
if [ $leads_24h -eq 0 ]; then
send_slack "#bsp-alerts" "CRITICAL" "Zero leads in last 24 hours"
fi
# Check CPL by source
for source in "google_ads" "lsa" "service_direct" "slp" "networx"; do
cpl=$(calculate_trailing_7day_cpl $source)
if [ $cpl -gt 500 ]; then
send_slack "#bsp-alerts" "CRITICAL" "$source CPL hit \$$cpl"
elif [ $cpl -gt 300 ]; then
send_slack "#bsp-alerts" "WARNING" "$source CPL at \$$cpl"
fi
done
# Check budget pace
spend_today=$(query_google_ads "cost WHERE date = TODAY")
days_remaining=$(days_left_in_month)
projected=$(echo "$spend_today * $days_remaining" | bc)
if [ $(echo "$projected > $monthly_budget * 1.10" | bc) -eq 1 ]; then
send_slack "#bsp-alerts" "WARNING" "Budget on pace to overspend"
fi
SECTION 14
🏆 Competitor Benchmarking Metrics
You cannot outperform what you do not measure. Know where you stand relative to the competition in Overland Park.
👁️ Impression Share Targets
| Keyword Category | Current IS (est.) | Target IS | Strategy to Close Gap |
| Brand terms ("bright side plumbing") | ~80% | 95%+ | Brand campaign at max IS. Lost IS = competitor conquesting. Fight back. |
| Core service ("plumber overland park") | ~35% | 50%+ | Increase bids on top terms, improve QS, expand budget |
| Sewer terms ("sewer repair overland park") | ~30% | 60%+ | High-value jobs justify aggressive bidding. Sewer ROAS covers higher CPC. |
| Emergency ("emergency plumber near me") | ~25% | 45%+ | Schedule-based bidding (higher bids after hours), call-only ads |
📊 Auction Insights Tracking
MONTHLY PROCESS
- Export Auction Insights from Google Ads (campaign level, segmented by month)
- Track these competitors monthly in a spreadsheet:
- For each competitor, record: Impression Share, Overlap Rate, Position Above Rate, Top of Page Rate, Outranking Share
- Chart trends over time. Who is gaining? Who is falling?
- New competitors entering the auction get flagged and researched
🔍 Share of Voice (SOV) Tracking in Semrush
SEMRUSH SETUP
- Create a Position Tracking project in Semrush for callbrightside.com
- Target location: Overland Park, KS (and surrounding cities: Olathe, Lenexa, Shawnee, Leawood)
- Add keywords: all service terms (50-100 keywords across plumbing, sewer, water heater, drain, etc.)
- Add competitors: top 5-10 plumbing companies in the area
- Go to Visibility tab to see Share of Voice
Share of Voice (SOV) = Sum of (Estimated Traffic for Each Keyword You Rank For) / Sum of (Total Search Traffic for All Tracked Keywords)
Why SOV matters: SOV is a leading indicator of market share. Companies with higher SOV tend to win a proportional share of revenue. Track monthly.
📋 Monthly Competitor Scorecard
| Competitor | Google Ads IS | LSA Position | Organic SOV | Review Count | Avg Rating | Trend |
| [Competitor A] | ___% | #___ | ___% | ___ | ___ | ↑/↓/↔️ |
| [Competitor B] | ___% | #___ | ___% | ___ | ___ | ↑/↓/↔️ |
| [Competitor C] | ___% | #___ | ___% | ___ | ___ | ↑/↓/↔️ |
| Bright Side | ___% | #___ | ___% | ___ | ___ | |
SECTION 15
🚀 Revenue Milestone Tracker
The road from $3M to $6M. Visual tracker with the math, the pace needed, and Robert's bonus triggers.
🎯 Milestone Visualization
$3M
$3,000,000
Current Revenue
~$57.7K/week
$4M
$4,000,000
First Target
$77K/week needed
$5M
$5,000,000
Stretch Goal
$96K/week needed
$6M
$6,000,000
Ultimate Target
$115K/week needed
💵 Robert's Bonus Milestones
| Milestone | Annual Revenue | Weekly Revenue Needed | Bonus | Gap from Current | Growth Needed |
| TIER 1 |
$4,000,000 |
$76,923/week |
$5,000 |
+$19,223/week |
+33.3% |
| TIER 2 |
$5,000,000 |
$96,154/week |
$5,000 (cumulative: $10K) |
+$38,454/week |
+66.6% |
| TIER 3 |
$6,000,000 |
$115,385/week |
$5,000 (cumulative: $15K) |
+$57,685/week |
+100% |
📈 Pace Calculator
Weeks Remaining in Year = 52 - Current Week Number
Revenue Needed to Hit $4M = $4,000,000 - YTD Revenue
Required Weekly Pace = Revenue Needed / Weeks Remaining
Example (as of March 12, 2026):
Week 11 of 52. Weeks remaining: 41.
If YTD Revenue = ~$635K (11 weeks x $57.7K):
Revenue needed for $4M = $4,000,000 - $635,000 = $3,365,000
Required weekly pace = $3,365,000 / 41 = $82,073/week
That is 42% above current pace. Must start accelerating NOW.
📊 Acceleration Scenarios
| Scenario | Weekly Revenue | Annual Pace | Hits $4M? | Hits $5M? | Hits $6M? |
| Current Pace (No Change) |
$57,700 |
$3,000,000 |
❌ No |
❌ No |
❌ No |
| +20% Growth (Marketing Only) |
$69,240 |
$3,600,000 |
❌ Close |
❌ No |
❌ No |
| +35% Growth (Marketing + Ops) |
$77,895 |
$4,050,000 |
✅ Yes |
❌ No |
❌ No |
| +65% Growth (Aggressive Scale) |
$95,205 |
$4,950,000 |
✅ Yes |
✅ Nearly |
❌ No |
| +100% Growth (Full Throttle) |
$115,400 |
$6,000,000 |
✅ Yes |
✅ Yes |
✅ Yes |
🔧 Growth Levers (Ranked by Impact)
💰 Revenue Growth Levers
- Increase sewer close rate from 35% to 45%: Sewer jobs are $8K-$15K. Every 10% close rate improvement = ~$200K+ annual revenue.
- Scale LSA from 19 to 50+ leads/month: Lowest CPL channel. 31 more leads at 35% close x $2K avg = $21.7K/month more.
- Improve Google Ads ROAS from 1.9:1 to 4:1: Fix GCLID tracking, optimize keywords, improve landing pages. Same spend, more revenue.
- Increase average ticket by 15%: Membership upsells, water heater add-ons, maintenance agreements. $57.7K/week becomes $66.3K/week.
- Reduce CSR missed calls to zero during business hours: Every missed call is a missed booking. At 80% booking rate, each answered call = 0.8 x $2K = $1,600.
📅 Bonus Trigger Date Estimates
If Growth Starts Now
- $4M Pace ($77K/week): At +35% growth rate, achievable by ~Q3 2026 (July-September)
- $5M Pace ($96K/week): Requires sustained momentum. Realistic by Q1-Q2 2027 if sewer pipeline and marketing scale both hit.
- $6M Pace ($115K/week): Requires operational capacity expansion (more techs, more trucks). Potentially achievable by Q3-Q4 2027.
Key assumption: Revenue milestones are measured by run rate (weekly average), not cumulative annual total. Confirm with Stephanie whether the bonus triggers on sustained weekly average or annual total.
📋 Weekly Milestone Check-In Template
Add to Every Weekly Report
| Metric | This Week | 4-Week Avg | Needed for $4M | Gap |
| Weekly Revenue | $___ | $___ | $77,000 | $___ |
| Weekly Leads | ___ | ___ | ___ | ___ |
| Booking Rate | ___% | ___% | 80% | ___pts |
| Avg Ticket | $___ | $___ | $___ | $___ |
| Blended CPL | $___ | $___ | ≤$200 | $___ |
🎯 The Math is Clear: To hit $4M, Bright Side needs to grow weekly revenue by ~33% from $57.7K to $77K. The fastest path is: (1) Fix Google Ads attribution so we can optimize with real revenue data, (2) Scale LSA aggressively, (3) Improve sewer close rate. These three moves alone could close the gap.