follow-up-sla.md13.5 KBView on GitHub
# Follow-up SLA

How fast the team responds, how consistently it follows up, and how that maps to revenue. SLA targets: **first response < 1h**, **post-meeting follow-up < 24h**, **follow-up gap < 3 days**. Last 90 days, 100 deals per rep. All figures are demo data.

## The SLA standard

The rings fill toward each metric's SLA target — a full ring means the team is at (or past) budget. Compliance is the share of first responses that beat the 1-hour target.

```dashboard
{
  "id": "sla_standard",
  "dataSources": {
    "headline": {
      "mock": [
        { "response": 2520, "postMeeting": 61200, "followup": 181000, "compliance": 68 }
      ]
    }
  },
  "layout": {
    "type": "grid",
    "columns": 4,
    "gap": "lg",
    "children": [
      {
        "type": "stat",
        "source": "headline",
        "field": "response",
        "label": "Avg first response",
        "format": "duration",
        "style": "radial",
        "max": 3600
      },
      {
        "type": "stat",
        "source": "headline",
        "field": "postMeeting",
        "label": "Avg post-meeting follow-up",
        "format": "duration",
        "style": "radial",
        "max": 86400
      },
      {
        "type": "stat",
        "source": "headline",
        "field": "followup",
        "label": "Avg follow-up gap",
        "format": "duration",
        "style": "radial",
        "max": 259200
      },
      {
        "type": "stat",
        "source": "headline",
        "field": "compliance",
        "label": "First responses within 1h",
        "format": "percent",
        "style": "radial",
        "max": 100,
        "highlight": true
      }
    ]
  },
  "spec_version": "2.0"
}
```

## Why it matters

Speed is a consistent separator between won and lost deals. Win and reply rates slide the longer the first response takes.

```dashboard
{
  "id": "sla_why",
  "dataSources": {
    "outcome": {
      "mock": [
        { "outcome": "Won deals", "firstResponse": 2520, "followupGap": 129600, "replyRate": 71, "deals": 42 },
        { "outcome": "Lost deals", "firstResponse": 19440, "followupGap": 540000, "replyRate": 31, "deals": 58 },
        { "outcome": "All deals", "firstResponse": 6480, "followupGap": 226800, "replyRate": 49, "deals": 100 }
      ]
    },
    "decay": {
      "mock": [
        { "bucket": "<1h", "winRate": 56, "replyRate": 66 },
        { "bucket": "1–4h", "winRate": 50, "replyRate": 60 },
        { "bucket": "4–24h", "winRate": 44, "replyRate": 54 },
        { "bucket": "1–3d", "winRate": 38, "replyRate": 48 },
        { "bucket": ">3d", "winRate": 32, "replyRate": 42 }
      ]
    }
  },
  "layout": {
    "type": "column",
    "gap": "lg",
    "children": [
      {
        "type": "table",
        "source": "outcome",
        "title": "Response & follow-up by outcome",
        "columns": [
          { "key": "outcome", "label": "Outcome", "weight": 2 },
          { "key": "firstResponse", "label": "Avg first response", "format": "duration", "align": "right" },
          { "key": "followupGap", "label": "Avg follow-up gap", "format": "duration", "align": "right" },
          { "key": "replyRate", "label": "Reply rate", "format": "percent", "align": "right" },
          { "key": "deals", "label": "Deals", "format": "number", "align": "right" }
        ]
      },
      {
        "type": "chart",
        "source": "decay",
        "chart": "line",
        "title": "Win & reply rate by first-response speed",
        "xAxis": "bucket",
        "series": [
          { "key": "winRate", "label": "Win %" },
          { "key": "replyRate", "label": "Reply %" }
        ]
      }
    ]
  },
  "spec_version": "2.0"
}
```

## Per-rep follow-up

Each card compares the rep's response, follow-up, and post-meeting times against the team average, beside their win rate, with a sample deal's activity timeline. A tight, regular cadence (Willem) keeps deals alive; widening gaps (Marcus) let them stall. Click a card to open the rep's playbook.

```dashboard
{
  "id": "sla_per_rep",
  "dataSources": {
    "reps": {
      "mock": [
        {
          "name": "Willem",
          "initials": "WE",
          "label": "Top rep",
          "response": 1500,
          "followup": 129600,
          "postMeeting": 18000,
          "winRate": 38,
          "docPath": "user/files/users/willem",
          "events": [
            { "kind": "inbound_email", "at": "2026-05-01T09:00:00Z", "title": "Inbound: pricing question" },
            { "kind": "outbound_email", "at": "2026-05-01T09:30:00Z", "title": "Reply + book demo" },
            { "kind": "meeting", "at": "2026-05-04T16:00:00Z", "title": "Demo" },
            { "kind": "outbound_email", "at": "2026-05-04T18:00:00Z", "title": "Recap + next steps" },
            { "kind": "outbound_email", "at": "2026-05-07T10:00:00Z", "title": "Check-in + mutual action plan" },
            { "kind": "meeting", "at": "2026-05-11T15:00:00Z", "title": "Exec readout" },
            { "kind": "outbound_email", "at": "2026-05-11T17:00:00Z", "title": "Order form" }
          ]
        },
        {
          "name": "Lily",
          "initials": "LP",
          "label": "Account Exec",
          "response": 2700,
          "followup": 172800,
          "postMeeting": 54000,
          "winRate": 22,
          "docPath": "user/files/users/lily",
          "events": [
            { "kind": "inbound_email", "at": "2026-05-01T09:00:00Z", "title": "Inbound: demo request" },
            { "kind": "outbound_email", "at": "2026-05-01T14:00:00Z", "title": "Reply" },
            { "kind": "meeting", "at": "2026-05-05T16:00:00Z", "title": "Demo" },
            { "kind": "outbound_email", "at": "2026-05-06T12:00:00Z", "title": "Recap" },
            { "kind": "outbound_email", "at": "2026-05-10T10:00:00Z", "title": "Follow-up" },
            { "kind": "outbound_email", "at": "2026-05-14T09:00:00Z", "title": "Check-in" }
          ]
        },
        {
          "name": "Sarah",
          "initials": "SK",
          "label": "Account Exec",
          "response": 4200,
          "followup": 226800,
          "postMeeting": 75600,
          "winRate": 21,
          "docPath": "user/files/users/sarah",
          "events": [
            { "kind": "inbound_email", "at": "2026-05-01T09:00:00Z", "title": "Inbound" },
            { "kind": "outbound_email", "at": "2026-05-02T11:00:00Z", "title": "Reply (next day)" },
            { "kind": "meeting", "at": "2026-05-06T16:00:00Z", "title": "Demo" },
            { "kind": "outbound_email", "at": "2026-05-08T10:00:00Z", "title": "Recap (2 days later)" },
            { "kind": "outbound_email", "at": "2026-05-13T10:00:00Z", "title": "Follow-up" }
          ]
        },
        {
          "name": "Marcus",
          "initials": "MR",
          "label": "Account Exec",
          "response": 9000,
          "followup": 432000,
          "postMeeting": 129600,
          "winRate": 10,
          "docPath": "user/files/users/marcus",
          "events": [
            { "kind": "inbound_email", "at": "2026-05-01T09:00:00Z", "title": "Inbound" },
            { "kind": "outbound_email", "at": "2026-05-03T15:00:00Z", "title": "Reply (2 days later)" },
            { "kind": "meeting", "at": "2026-05-07T16:00:00Z", "title": "Demo" },
            { "kind": "outbound_email", "at": "2026-05-12T10:00:00Z", "title": "Recap (5 days later)" },
            { "kind": "outbound_email", "at": "2026-05-15T10:00:00Z", "title": "Still there?" }
          ]
        }
      ]
    }
  },
  "layout": {
    "type": "repeater",
    "source": "reps",
    "as": "rep",
    "layout": "grid",
    "columns": 1,
    "gap": "lg",
    "template": {
      "type": "entityCard",
      "linkField": "docPath",
      "children": [
        {
          "type": "row",
          "gap": "md",
          "align": "center",
          "children": [
            { "type": "profile", "name": "{{rep.name}}", "initials": "{{rep.initials}}", "label": "{{rep.label}}" },
            { "type": "stat", "field": "winRate", "label": "Win rate", "format": "percent" }
          ]
        },
        {
          "type": "comparison",
          "format": "duration",
          "rowLabel": "This rep",
          "teamLabel": "Team avg",
          "fields": [
            { "key": "response", "label": "First response" },
            { "key": "followup", "label": "Follow-up gap" },
            { "key": "postMeeting", "label": "Post-meeting follow-up" }
          ]
        },
        {
          "type": "timeline",
          "rowField": "events",
          "title": "Sample deal activity",
          "rangeStart": "2026-05-01T00:00:00Z",
          "rangeEnd": "2026-05-16T00:00:00Z"
        }
      ]
    }
  },
  "spec_version": "2.0"
}
```

## Breaking the no-reply streak

The emails that revive a dead thread — short, specific, and easy to answer yes or no.

```dashboard
{
  "id": "sla_breakers",
  "dataSources": {
    "breakers": {
      "mock": [
        {
          "name": "The permission-to-close",
          "subject": "Should I close your file?",
          "body": "Haven't heard back, which usually means one of three things: it's not a priority right now, the timing is off, or I dropped the ball. Totally fine either way — just tell me which and I'll act accordingly.",
          "replyRate": 61,
          "context": "After 2 unanswered follow-ups"
        },
        {
          "name": "The trigger event",
          "subject": "Saw the Series B — congrats",
          "body": "Congrats on the raise. New headcount usually means more pipeline than the team can follow up on — which is exactly the gap we close. Worth 15 minutes now that you're scaling the team?",
          "replyRate": 58,
          "context": "Triggered by funding news"
        },
        {
          "name": "The case-study drop",
          "subject": "How Ramp cut follow-up time 60%",
          "body": "You mentioned reps forgetting to follow up. Ramp had the same problem — attached is the one-pager on how they fixed it in 3 weeks. Happy to walk through it live if useful.",
          "replyRate": 52,
          "context": "Mapped to a stated pain"
        }
      ]
    }
  },
  "layout": {
    "type": "repeater",
    "source": "breakers",
    "as": "breaker",
    "layout": "list",
    "gap": "md",
    "template": {
      "type": "entityCard",
      "children": [
        { "type": "text", "markdown": "**{{breaker.name}}** · {{breaker.context}} · replies {{breaker.replyRate}}%" },
        { "type": "text", "markdown": "**Subject:** {{breaker.subject}}" },
        { "type": "text", "markdown": "{{breaker.body}}", "className": "text-muted-foreground italic" }
      ]
    }
  },
  "spec_version": "2.0"
}
```

## Where the time goes

Most first responses land inside the SLA window — the long tail is where deals quietly die. Post-meeting speed compounds the effect.

```dashboard
{
  "id": "sla_distribution",
  "dataSources": {
    "dist": {
      "mock": [
        { "bucket": "<1h", "count": 38 },
        { "bucket": "1–4h", "count": 27 },
        { "bucket": "4–24h", "count": 18 },
        { "bucket": "1–3d", "count": 11 },
        { "bucket": ">3d", "count": 6 }
      ]
    },
    "pmSplit": {
      "mock": [
        { "window": "Same day", "win": 52 },
        { "window": "Next day", "win": 34 },
        { "window": ">2 days", "win": 15 }
      ]
    }
  },
  "layout": {
    "type": "grid",
    "columns": 2,
    "gap": "lg",
    "children": [
      {
        "type": "chart",
        "source": "dist",
        "chart": "bar",
        "title": "First-response time distribution",
        "xAxis": "bucket",
        "series": [{ "key": "count", "label": "Deals" }]
      },
      {
        "type": "chart",
        "source": "pmSplit",
        "chart": "bar",
        "title": "Win rate by post-meeting follow-up window",
        "xAxis": "window",
        "series": [{ "key": "win", "label": "Win %" }]
      }
    ]
  },
  "spec_version": "2.0"
}
```

## Breaching SLA right now

Open deals whose last inbound has gone unanswered past the 1-hour target. Work these first.

```dashboard
{
  "id": "sla_breaching",
  "dataSources": {
    "breaching": {
      "mock": [
        { "deal": "Acme Corp", "owner": "Marcus", "waiting": 320000, "path": "user/files/deals/acme-corp" },
        { "deal": "Globex", "owner": "Sarah", "waiting": 280000, "path": "user/files/deals/globex" },
        { "deal": "Initech", "owner": "Lily", "waiting": 210000, "path": "user/files/deals/initech" }
      ]
    },
    "cadence": {
      "mock": [
        { "outcome": "Won deals", "touches": 6, "avgGap": 129600 },
        { "outcome": "Lost deals", "touches": 3, "avgGap": 540000 }
      ]
    }
  },
  "layout": {
    "type": "column",
    "gap": "lg",
    "children": [
      {
        "type": "table",
        "source": "breaching",
        "title": "Unanswered inbound — breaching SLA",
        "columns": [
          { "key": "deal", "label": "Deal", "weight": 2 },
          { "key": "owner", "label": "Owner", "type": "rep", "weight": 1 },
          { "key": "waiting", "label": "Waiting", "format": "duration", "align": "right" },
          { "key": "path", "label": "Open", "type": "docLink", "linkLabel": "Open →", "weight": 1 }
        ]
      },
      {
        "type": "table",
        "source": "cadence",
        "title": "Touches to reply — won vs lost",
        "columns": [
          { "key": "outcome", "label": "Outcome", "weight": 2 },
          { "key": "touches", "label": "Avg follow-ups before reply", "format": "number", "align": "right" },
          { "key": "avgGap", "label": "Avg gap between touches", "format": "duration", "align": "right" }
        ]
      }
    ]
  },
  "spec_version": "2.0"
}
```