---
# === IDENTITY ===
id: software/startup-dashboard/sales-operations-dashboard/2026
canonical_question: "How do I build a sales ops dashboard — CRM data model, pipeline visualization, activity tracking, forecasting?"
aliases:
  - "sales operations dashboard setup"
  - "CRM pipeline dashboard build"
  - "sales forecasting dashboard implementation"
  - "startup sales dashboard with HubSpot or Pipedrive"
entity_type: execution_recipe
domain: software > startup-dashboard > sales-operations-dashboard
region: global
jurisdiction: global
temporal_scope: 2025-2026

# === VERIFICATION ===
last_verified: 2026-03-12
confidence: 0.88
version: 1.0
first_published: 2026-03-12

# === TEMPORAL VALIDITY ===
temporal_validity:
  status: evolving
  last_breaking_change: "HubSpot API v3 deprecated v1 endpoints; Pipedrive webhooks v2 replaced legacy push notifications (Q4 2025)"
  next_review: 2026-09-08
  change_sensitivity: high

# === CONSTRAINTS ===
constraints:
  - "CRM API rate limits: HubSpot free = 100 calls/10s, Pipedrive = 80 calls/2s. Batch requests and cache aggressively."
  - "Pipeline stage definitions must match CRM configuration exactly — mismatched stages produce incorrect conversion metrics."
  - "Forecasting models require at least 90 days of historical deal data to produce statistically meaningful predictions."
  - "PII in deal records (contact emails, phone numbers) must be handled per GDPR/CCPA — mask in dashboard views shared outside sales team."
  - "Dashboard refresh intervals should be 15-60 minutes for operational views — real-time polling burns API quota without meaningful insight gain."

# === SKIP CONDITIONS ===
skip_this_unit_if:
  - condition: "User needs a sales strategy or process design, not a dashboard"
    use_instead: "business/startup-sales/sales-process-design/2026"
  - condition: "User wants a pre-built CRM analytics tool without custom development"
    use_instead: "Search knowledgelib.io for BI/dashboard tool selection — no dedicated unit yet"
  - condition: "User is building an enterprise BI warehouse, not a startup dashboard"
    use_instead: "software/system-design/data-warehouse-data-lake/2026"

# === AGENT HINTS ===
inputs_needed:
  - key: crm_platform
    question: "Which CRM does the team use?"
    type: choice
    options: ["HubSpot", "Pipedrive", "Salesforce", "Close", "no CRM yet — auto-select"]
  - key: technical_skill
    question: "What is the user's technical skill level?"
    type: choice
    options: ["non-technical (no-code only)", "semi-technical (can edit code)", "developer (can write code)"]
  - key: budget_for_tools
    question: "What's the dashboard tool budget?"
    type: choice
    options: ["free tier only", "up to $50/month", "up to $200/month", "no limit"]
  - key: team_size
    question: "How many sales reps will use the dashboard?"
    type: choice
    options: ["1-3 reps", "4-10 reps", "11-25 reps", "25+ reps"]

# === EXECUTION METADATA ===
execution:
  required_inputs:
    - name: "CRM account with API access"
      source: "user's existing CRM"
      format: "API key or OAuth credentials"
    - name: "Pipeline stage definitions"
      source: "user's CRM configuration"
      format: "ordered list of stage names with win probabilities"

  outputs:
    - name: "Sales operations dashboard"
      format: "deployed web application or embedded BI dashboard"
      description: "Live dashboard showing pipeline value, stage conversion rates, rep activity metrics, deal velocity, and weighted forecast"
    - name: "Data sync pipeline"
      format: "scheduled ETL job (cron or webhook-triggered)"
      description: "Automated data extraction from CRM to dashboard data store, refreshing every 15-60 minutes"

  tools_required:
    - name: "Retool"
      purpose: "Dashboard UI builder with drag-and-drop components"
      tier: "free"
      cost: "$0 (free for 5 users) to $10/user/month"
      alternatives: ["Metabase", "Grafana", "Google Looker Studio"]
    - name: "PostgreSQL"
      purpose: "Data warehouse for CRM data staging"
      tier: "free"
      cost: "$0 (Supabase free tier) to $25/month"
      alternatives: ["MySQL", "SQLite", "BigQuery"]
    - name: "n8n or Pipedream"
      purpose: "ETL automation for CRM data sync"
      tier: "free"
      cost: "$0 (self-hosted n8n) to $19/month"
      alternatives: ["Airbyte", "Fivetran", "custom cron script"]

  credentials_needed:
    - service: "CRM platform (HubSpot/Pipedrive/Salesforce)"
      type: "API key or OAuth token"
      where_to_get: "CRM Settings > Integrations > API"
      free_tier_limits: "HubSpot: 100 calls/10s; Pipedrive: 80 calls/2s"
    - service: "PostgreSQL database"
      type: "connection string"
      where_to_get: "https://supabase.com or self-hosted"
      free_tier_limits: "Supabase: 500MB storage, 2 GB transfer"

  estimated_duration: "4-8 hours for initial setup; 1-2 hours for customization"
  estimated_cost: "$0 (all free tiers) to $75/month (paid tiers at startup scale)"

# === DISTRIBUTION ===
canonical_source: "https://knowledgelib.io/software/startup-dashboard/sales-operations-dashboard/2026"
suggested_citation: "Source: knowledgelib.io — AI Knowledge Library (verified 2026-03-12)"

# === RELATED UNITS ===
related_kos:
  feeds_into:
    - id: "software/startup-dashboard/financial-operations-dashboard/2026"
      label: "Finance dashboard consumes revenue data from sales pipeline"
  related_to:
    - id: "business/sales-ops/sales-metrics-benchmarks/2026"
      label: "Benchmark targets for sales KPIs"

# === SOURCES ===
sources:
  - id: src1
    title: "HubSpot CRM API Documentation"
    author: HubSpot
    url: https://developers.hubspot.com/docs/api/crm/deals
    type: official_docs
    published: 2025-12-01
    reliability: authoritative
  - id: src2
    title: "Pipedrive API Reference"
    author: Pipedrive
    url: https://developers.pipedrive.com/docs/api/v1
    type: official_docs
    published: 2025-11-15
    reliability: authoritative
  - id: src3
    title: "Retool Dashboard Building Guide"
    author: Retool
    url: https://retool.com/resources/build-your-first-dashboard-in-retool
    type: official_docs
    published: 2025-10-01
    reliability: authoritative
  - id: src4
    title: "Sales Dashboard Templates and Best Practices"
    author: monday.com
    url: https://monday.com/blog/crm-and-sales/sales-dashboard-templates/
    type: industry_guide
    published: 2025-11-20
    reliability: high
  - id: src5
    title: "Metabase Open Source BI Documentation"
    author: Metabase
    url: https://www.metabase.com/docs/latest/
    type: official_docs
    published: 2025-12-01
    reliability: authoritative
  - id: src6
    title: "Sales Pipeline Forecasting with Data Analytics"
    author: ClicData
    url: https://www.clicdata.com/blog/how-to-build-a-sales-pipeline-forecast/
    type: industry_guide
    published: 2025-08-15
    reliability: high
---

# Sales Operations Dashboard

## Purpose

This recipe produces a fully functional sales operations dashboard that visualizes CRM pipeline data in real time, tracks rep activity metrics, calculates stage conversion rates, and generates weighted revenue forecasts. The output is a deployed internal tool (Retool, Metabase, or Grafana) connected to your CRM via automated data sync, giving sales leadership a single-pane view of pipeline health, deal velocity, and forecast accuracy. [src1]

## Prerequisites
<!-- Agents: verify ALL prerequisites before executing. Missing prerequisites = failed execution. -->

- [ ] **CRM account with API access enabled** — HubSpot (Settings > Integrations > API Key), Pipedrive (Settings > Personal > API), or Salesforce (Setup > API)
- [ ] **Pipeline stages defined in CRM** — at minimum: Lead, Qualified, Proposal, Negotiation, Closed Won, Closed Lost with win probabilities assigned
- [ ] **PostgreSQL database** — free tier at [Supabase](https://supabase.com) or [Neon](https://neon.tech) (500MB sufficient for <25 reps)
- [ ] **Dashboard tool account** — [Retool](https://retool.com) (free for 5 users) or [Metabase](https://www.metabase.com) (open source, self-hosted)
- [ ] **90+ days of historical deal data** in CRM — required for meaningful forecasting; 30 days minimum for basic pipeline views

## Constraints
<!-- Hard rules. Agents: enforce throughout execution. Violating these = broken output or legal risk. -->

- CRM API rate limits: HubSpot = 100 requests/10 seconds (free), Pipedrive = 80 requests/2 seconds. Implement exponential backoff and batch fetching. [src1]
- Pipeline stage names in the dashboard schema MUST exactly match CRM stage names — any mismatch produces zero-value conversion metrics. [src2]
- Forecasting requires minimum 90 days of closed deal data. With fewer than 50 closed deals, weighted pipeline forecast error exceeds 40%. [src6]
- PII fields (contact email, phone) must be excluded from shared dashboard views or masked per GDPR/CCPA. Store raw data in database only.
- Dashboard refresh interval: 15 minutes minimum for operational views. Sub-minute polling wastes API quota and creates UI flicker without meaningful data changes.

## Tool Selection Decision

<!-- Agent selects the right tool path based on user inputs. -->

```
Which path?
├── User is non-technical AND budget = free
│   └── PATH A: No-Code Free — Google Looker Studio + CRM native export
├── User is non-technical AND budget > $0
│   └── PATH B: No-Code Paid — Retool (free tier) + Supabase + n8n Cloud
├── User is semi-technical or developer AND budget = free
│   └── PATH C: Code + Free — Metabase (self-hosted) + PostgreSQL + cron script
└── User is developer AND budget > $0
    └── PATH D: Code + Paid — Retool + Supabase + n8n + custom transforms
```

| Path | Tools | Cost | Speed | Output Quality |
|------|-------|------|-------|---------------|
| A: No-Code Free | Looker Studio + CSV export | $0 | 2-3 hours | Basic — manual refresh, limited interactivity |
| B: No-Code Paid | Retool + Supabase + n8n | $0-19/mo | 4-6 hours | Good — auto-refresh, interactive filters |
| C: Code + Free | Metabase + PostgreSQL + cron | $0 | 6-8 hours | Good — full SQL control, self-hosted |
| D: Code + Paid | Retool + Supabase + n8n | $25-75/mo | 4-6 hours | Excellent — real-time sync, custom components |

## Execution Flow

### Step 1: Design the Data Model

**Duration**: 30-60 minutes
**Tool**: SQL client (psql, DBeaver, or Supabase dashboard)

Create the staging tables that normalize CRM data into a consistent schema regardless of CRM platform.

```sql
-- Sales pipeline data model
CREATE TABLE deals (
  id TEXT PRIMARY KEY,
  deal_name TEXT NOT NULL,
  stage TEXT NOT NULL,
  amount NUMERIC(12,2) DEFAULT 0,
  currency TEXT DEFAULT 'USD',
  close_date DATE,
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW(),
  owner_id TEXT,
  owner_name TEXT,
  pipeline_name TEXT DEFAULT 'default',
  win_probability NUMERIC(3,2) DEFAULT 0,
  days_in_stage INTEGER DEFAULT 0,
  source TEXT,
  crm_id TEXT UNIQUE
);

CREATE TABLE activities (
  id SERIAL PRIMARY KEY,
  deal_id TEXT REFERENCES deals(id),
  activity_type TEXT NOT NULL, -- 'call', 'email', 'meeting', 'note'
  subject TEXT,
  performed_at TIMESTAMPTZ DEFAULT NOW(),
  owner_id TEXT,
  owner_name TEXT,
  duration_minutes INTEGER
);

CREATE TABLE stage_history (
  id SERIAL PRIMARY KEY,
  deal_id TEXT REFERENCES deals(id),
  from_stage TEXT,
  to_stage TEXT,
  changed_at TIMESTAMPTZ DEFAULT NOW(),
  days_in_previous_stage INTEGER
);

CREATE TABLE pipeline_snapshots (
  id SERIAL PRIMARY KEY,
  snapshot_date DATE DEFAULT CURRENT_DATE,
  stage TEXT NOT NULL,
  deal_count INTEGER DEFAULT 0,
  total_value NUMERIC(14,2) DEFAULT 0,
  weighted_value NUMERIC(14,2) DEFAULT 0
);

-- Indexes for dashboard query performance
CREATE INDEX idx_deals_stage ON deals(stage);
CREATE INDEX idx_deals_owner ON deals(owner_id);
CREATE INDEX idx_deals_close_date ON deals(close_date);
CREATE INDEX idx_activities_deal ON activities(deal_id);
CREATE INDEX idx_activities_date ON activities(performed_at);
CREATE INDEX idx_snapshots_date ON pipeline_snapshots(snapshot_date);
```

**Verify**: Run `SELECT COUNT(*) FROM deals;` — should return 0 (tables created successfully).
**If failed**: Check PostgreSQL connection string and user permissions. Supabase free tier requires enabling the table via Dashboard > SQL Editor.

### Step 2: Build the CRM Data Sync

**Duration**: 1-2 hours
**Tool**: n8n, Pipedream, or custom Node.js script
**Rate limit**: HubSpot = 100/10s, Pipedrive = 80/2s. Batch in groups of 50 with 1s delay.

For HubSpot (Path B/D using n8n):

```javascript
// n8n HTTP Request node configuration for HubSpot deals
// Endpoint: GET https://api.hubapi.com/crm/v3/objects/deals
// Headers: Authorization: Bearer {HUBSPOT_API_KEY}
// Query params: limit=100, properties=dealname,amount,dealstage,closedate,hubspot_owner_id,pipeline

// Transform node: Map HubSpot fields to staging schema
const deals = items.map(item => ({
  id: `hs-${item.json.id}`,
  deal_name: item.json.properties.dealname,
  stage: item.json.properties.dealstage,
  amount: parseFloat(item.json.properties.amount) || 0,
  close_date: item.json.properties.closedate,
  owner_id: item.json.properties.hubspot_owner_id,
  crm_id: item.json.id,
  updated_at: item.json.properties.hs_lastmodifieddate
}));
```

For Pipedrive (alternative):

```javascript
// Pipedrive API: GET https://api.pipedrive.com/v1/deals
// Query: api_token={PIPEDRIVE_TOKEN}&limit=500&status=open

const deals = items.map(item => ({
  id: `pd-${item.json.id}`,
  deal_name: item.json.title,
  stage: item.json.stage_id.toString(),
  amount: item.json.value || 0,
  currency: item.json.currency,
  close_date: item.json.expected_close_date,
  owner_id: item.json.user_id?.id?.toString(),
  owner_name: item.json.user_id?.name,
  crm_id: item.json.id.toString()
}));
```

Set sync schedule: every 15 minutes for active pipeline, every 6 hours for historical snapshots.

**Expected output**: Deals table populated with all open and recently closed deals from CRM.
**Verify**: `SELECT COUNT(*) FROM deals WHERE updated_at > NOW() - INTERVAL '1 hour';` should return > 0 after first sync.
**If failed**: Check API key validity, verify rate limit headers in response, ensure deal properties are accessible on your CRM plan.

### Step 3: Build Pipeline Visualization Queries

**Duration**: 1-2 hours
**Tool**: SQL + Retool/Metabase

Create the core dashboard queries:

```sql
-- 1. Pipeline funnel by stage
SELECT
  stage,
  COUNT(*) as deal_count,
  SUM(amount) as total_value,
  SUM(amount * win_probability) as weighted_value,
  ROUND(AVG(days_in_stage), 1) as avg_days_in_stage
FROM deals
WHERE stage NOT IN ('closed_won', 'closed_lost')
GROUP BY stage
ORDER BY MIN(win_probability) ASC;

-- 2. Conversion rates between stages
SELECT
  from_stage,
  to_stage,
  COUNT(*) as transitions,
  ROUND(
    COUNT(*) FILTER (WHERE to_stage != 'closed_lost')::NUMERIC /
    NULLIF(COUNT(*), 0) * 100, 1
  ) as pass_rate
FROM stage_history
WHERE changed_at > NOW() - INTERVAL '90 days'
GROUP BY from_stage, to_stage
ORDER BY from_stage, COUNT(*) DESC;

-- 3. Rep activity scoreboard
SELECT
  owner_name,
  COUNT(*) FILTER (WHERE activity_type = 'call') as calls,
  COUNT(*) FILTER (WHERE activity_type = 'email') as emails,
  COUNT(*) FILTER (WHERE activity_type = 'meeting') as meetings,
  COUNT(*) as total_activities
FROM activities
WHERE performed_at > NOW() - INTERVAL '7 days'
GROUP BY owner_name
ORDER BY total_activities DESC;

-- 4. Weighted forecast by close month
SELECT
  DATE_TRUNC('month', close_date) as forecast_month,
  SUM(amount) as pipeline_value,
  SUM(amount * win_probability) as weighted_forecast,
  COUNT(*) as deal_count
FROM deals
WHERE close_date >= CURRENT_DATE
  AND stage NOT IN ('closed_won', 'closed_lost')
GROUP BY DATE_TRUNC('month', close_date)
ORDER BY forecast_month;

-- 5. Deal velocity (days from creation to close)
SELECT
  DATE_TRUNC('month', close_date) as month,
  ROUND(AVG(EXTRACT(EPOCH FROM (updated_at - created_at)) / 86400), 1) as avg_days_to_close,
  PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY EXTRACT(EPOCH FROM (updated_at - created_at)) / 86400) as median_days
FROM deals
WHERE stage = 'closed_won'
  AND close_date > NOW() - INTERVAL '6 months'
GROUP BY DATE_TRUNC('month', close_date)
ORDER BY month;
```

**Verify**: Each query returns data with no SQL errors. Pipeline funnel query should show all active stages.
**If failed**: Check column names match your schema. If stage names differ, update the `NOT IN` exclusions.

### Step 4: Assemble the Dashboard UI

**Duration**: 1-2 hours
**Tool**: Retool or Metabase

In Retool, create a new app with these components:

```
Dashboard Layout:
┌─────────────────────────────────────────────────────┐
│  KPI Row: Total Pipeline | Weighted Forecast |      │
│           Win Rate (30d) | Avg Deal Velocity        │
├─────────────────────────┬───────────────────────────┤
│  Pipeline Funnel Chart  │  Forecast by Month Chart  │
│  (horizontal bar)       │  (stacked bar: pipeline   │
│                         │   vs weighted)             │
├─────────────────────────┴───────────────────────────┤
│  Stage Conversion Table  | Rep Activity Scoreboard  │
├─────────────────────────────────────────────────────┤
│  Deal Velocity Trend (line chart, 6-month)          │
├─────────────────────────────────────────────────────┤
│  Deals Table (sortable, filterable by stage/rep)    │
└─────────────────────────────────────────────────────┘
```

KPI card configuration (Retool):
- **Total Pipeline**: Query 1, SUM of total_value, format as currency
- **Weighted Forecast**: Query 1, SUM of weighted_value, format as currency
- **Win Rate**: Query 2, filter closed_won / (closed_won + closed_lost) * 100
- **Avg Deal Velocity**: Query 5, latest month avg_days_to_close

**Verify**: All 6 dashboard sections render with data. KPI values match CRM totals within 5%.
**If failed**: Check query bindings in Retool. Most common error: query not connected to correct data source.

### Step 5: Configure Alerts and Scheduled Snapshots

**Duration**: 30-60 minutes
**Tool**: n8n or Pipedream + Slack/Email

```javascript
// Daily pipeline snapshot (run at 6:00 AM via cron)
// n8n: Schedule Trigger → PostgreSQL → IF → Slack

// PostgreSQL node: Insert daily snapshot
// INSERT INTO pipeline_snapshots (snapshot_date, stage, deal_count, total_value, weighted_value)
// SELECT CURRENT_DATE, stage, COUNT(*), SUM(amount), SUM(amount * win_probability)
// FROM deals WHERE stage NOT IN ('closed_won', 'closed_lost')
// GROUP BY stage;

// Alert conditions (IF node):
// 1. Pipeline value dropped > 20% vs 7-day average
// 2. Any rep has 0 activities in past 48 hours
// 3. Deals stuck in same stage > 2x average days_in_stage

// Slack notification template:
const message = {
  text: `📊 Sales Pipeline Alert`,
  blocks: [
    { type: "section", text: { type: "mrkdwn",
      text: `*Pipeline:* $${totalPipeline.toLocaleString()} (${deltaPercent}% vs last week)\n*Weighted Forecast:* $${weightedForecast.toLocaleString()}\n*Stale Deals:* ${staleCount} deals stuck > ${avgDays * 2} days`
    }}
  ]
};
```

**Verify**: Slack notification fires on test trigger. Pipeline_snapshots table has today's row.
**If failed**: Check Slack webhook URL. For email alerts, verify SMTP settings in n8n.

### Step 6: Deploy and Share Access

**Duration**: 30 minutes
**Tool**: Retool/Metabase deployment settings

For Retool:
- Share app URL with sales team members
- Set viewer-only permissions for reps, editor for managers
- Enable Retool Mobile for field sales access

For Metabase (self-hosted):
- Configure public sharing link or embed in internal portal
- Set up collection permissions by team role
- Enable email subscriptions for weekly snapshots

**Verify**: At least one non-admin user can access the dashboard and see current data.

## Output Schema

```json
{
  "output_type": "sales_operations_dashboard",
  "format": "deployed web application",
  "components": [
    {"name": "pipeline_funnel", "type": "chart", "description": "Horizontal bar chart showing deal count and value by stage", "required": true},
    {"name": "forecast_chart", "type": "chart", "description": "Monthly stacked bar of pipeline value vs weighted forecast", "required": true},
    {"name": "kpi_cards", "type": "metrics", "description": "Total pipeline, weighted forecast, win rate, deal velocity", "required": true},
    {"name": "rep_scoreboard", "type": "table", "description": "Activity counts per rep: calls, emails, meetings", "required": true},
    {"name": "conversion_table", "type": "table", "description": "Stage-to-stage conversion rates with pass rate percentages", "required": true},
    {"name": "deals_table", "type": "table", "description": "Filterable table of all active deals with sort by amount, stage, close date", "required": true}
  ],
  "refresh_interval": "15 minutes",
  "data_source": "PostgreSQL staging database synced from CRM"
}
```

## Quality Benchmarks

| Quality Metric | Minimum Acceptable | Good | Excellent |
|---------------|-------------------|------|-----------|
| Data freshness | < 60 min lag from CRM | < 15 min lag | < 5 min lag (webhook-driven) |
| Pipeline value accuracy | Within 10% of CRM total | Within 5% | Within 1% (full reconciliation) |
| Stage coverage | All active stages shown | + historical stages | + custom pipeline support |
| Forecast accuracy (30-day) | Within 40% of actual | Within 25% | Within 15% |
| Dashboard load time | < 10 seconds | < 5 seconds | < 2 seconds |

**If below minimum**: Check data sync job logs for failures. Pipeline value discrepancy usually means deals with $0 amount or unmapped stages are excluded.

## Error Handling

| Error | Likely Cause | Recovery Action |
|-------|-------------|----------------|
| CRM API 429 (rate limit) | Too many sync requests in time window | Implement exponential backoff: wait 2^n seconds, reduce batch size to 25 |
| CRM API 401 (auth failed) | API key expired or revoked | Regenerate key in CRM settings, update n8n/Pipedream credentials |
| Empty pipeline data | No deals match filter criteria or stage mapping broken | Verify stage names in CRM vs database schema, check deal status filters |
| Stale dashboard data | Sync job crashed or cron not running | Check n8n execution log, verify cron schedule, restart sync workflow |
| Forecast shows $0 | No deals with future close dates or win_probability not set | Ensure CRM deals have close_date populated and stages have probability values |
| Duplicate deals in dashboard | Upsert key mismatch — crm_id not matching | Add UNIQUE constraint on crm_id, use ON CONFLICT DO UPDATE in sync |

## Cost Breakdown

| Component | Free Tier | Paid Tier | At Scale (25+ reps) |
|-----------|-----------|-----------|----------|
| Dashboard tool (Retool) | $0 (5 users) | $10/user/mo | $250/mo (25 users) |
| Database (Supabase) | $0 (500MB) | $25/mo (8GB) | $25/mo |
| ETL automation (n8n) | $0 (self-hosted) | $20/mo (cloud) | $50/mo |
| CRM API access | Included in CRM plan | Included | Included |
| **Total** | **$0** | **$55/mo** | **$325/mo** |

## Anti-Patterns

### Wrong: Building pipeline views directly on CRM API calls
Every dashboard load fires dozens of API requests to the CRM. At 5 users refreshing 10 times daily, that's 500+ API calls/day on basic metrics — hitting rate limits within weeks and creating brittle, slow dashboards. [src1]

### Correct: ETL to staging database with scheduled sync
Extract CRM data to PostgreSQL on a 15-minute schedule. Dashboard queries hit the local database with sub-second response. API quota used only for sync, not for every page load.

### Wrong: Showing weighted forecast without calibrating win probabilities
Default CRM stage probabilities (e.g., "Proposal = 50%") are arbitrary. Teams that use uncalibrated probabilities see 30-50% forecast error, making the weighted number worse than useless. [src6]

### Correct: Calibrate probabilities from historical conversion data
Calculate actual conversion rates per stage from 6+ months of closed deal data. Update CRM stage probabilities to match reality. Re-calibrate quarterly.

## When This Matters

Use when a startup sales team has outgrown CRM-native reporting and needs a unified view of pipeline health, rep performance, and revenue forecast. Requires at least one active CRM with 90+ days of deal history. This recipe builds the dashboard — for sales process design or strategy, use a playbook card instead.

## Related Units

- [Financial Operations Dashboard](/software/startup-dashboard/financial-operations-dashboard/2026) — consumes revenue data from closed deals
- [Marketing Operations Dashboard](/software/startup-dashboard/marketing-operations-dashboard/2026) — feeds lead source attribution into pipeline
- [Sales Metrics Benchmarks](/business/sales-ops/sales-metrics-benchmarks/2026) — benchmark targets for dashboard KPIs
- [Startup Metrics Dashboard](/software/startup-dashboard/startup-metrics-overview/2026) — aggregated view consuming sales data
