# Buying Signals Detection - 0.1% Plan

## Overview
Detect and act on buying signals throughout the customer journey - in SMS, during calls, and post-call analysis. Currently the system only detects objections; buying signals are ignored.

**Status:** ✅ COMPLETE
**Priority:** #4
**Target:** Missing → 0.1%
**Completed:** Jan 16, 2026

---

## 0.1% Vision

**The best sales CRM would:**
- Detect buying signals in real-time during calls
- Classify SMS replies for buying intent, not just positive/negative
- Extract buying signals from call transcripts
- Boost lead scores when buying intent detected
- Alert the agent immediately when hot signals detected
- Surface buying history on lead cards

**User Experience:**
```
[During call with Mike]
Mike: "What's the next step to get started?"

┌─────────────────────────────────────────────────┐
│ 🔥 BUYING SIGNAL DETECTED                       │
│                                                 │
│ "What's the next step to get started?"          │
│                                                 │
│ This is a CLOSING SIGNAL. They're ready!        │
│                                                 │
│ SUGGESTED RESPONSE:                             │
│ "Great question! I can get you set up right     │
│ now. I just need your email to send the         │
│ signup link. What's the best email?"            │
└─────────────────────────────────────────────────┘

[Lead score: 65 → 85 (+20 buying signal bonus)]
```

---

## Buying Signal Patterns

### High Intent (Score +30)
| Pattern | Example |
|---------|---------|
| Ready to start | "When can you start?", "How do I sign up?" |
| Next steps | "What's the next step?", "What do I need to do?" |
| Commitment | "Let's do it", "I'm ready", "Sign me up" |
| Urgency | "Need workers ASAP", "Starting Monday" |

### Medium Intent (Score +15)
| Pattern | Example |
|---------|---------|
| Pricing acceptance | "That's reasonable", "Cheaper than our agency" |
| Comparison shopping | "Better than", "How do you compare?" |
| Timeline discussion | "We're starting a job next month" |
| Specific needs | "Need 3 electricians", "Looking for carpenters" |

### Low Intent (Score +5)
| Pattern | Example |
|---------|---------|
| Information gathering | "Tell me more", "How does it work?" |
| Budget questions | "What does it cost?", "What are the fees?" |
| General interest | "Sounds interesting", "Could be useful" |

---

## Implementation Steps

### Step 1: Add Buying Signal Patterns to Intent Detection
**File:** `src/utils/intent.js`

Add new pattern category alongside existing positive/negative/question:
```javascript
const BUYING_SIGNAL_PATTERNS = {
  high: [
    /when.*(?:can|do).*(?:start|begin|sign)/i,
    /what(?:'s| is).*next.*step/i,
    /how.*(?:sign|get started|begin)/i,
    /(?:let's|lets).*(?:do it|go|start)/i,
    /(?:i'm|im|i am).*ready/i,
    /sign.*(?:me|us).*up/i,
    /(?:need|want).*(?:asap|immediately|urgently|today|tomorrow)/i,
  ],
  medium: [
    /(?:cheaper|better|faster).*than/i,
    /(?:how|what).*compare/i,
    /(?:starting|begin|have).*(?:job|project|work).*(?:next|this)/i,
    /need.*\d+.*(?:workers|guys|people|electricians|carpenters)/i,
    /(?:that's|thats).*(?:reasonable|acceptable|good|fair)/i,
  ],
  low: [
    /tell.*more/i,
    /how.*(?:does|do).*(?:it|this).*work/i,
    /what.*(?:cost|fee|price|charge)/i,
    /sound.*(?:interesting|good|useful)/i,
  ],
};
```

### Step 2: Update SMS Intent Classification
**File:** `src/utils/intent.js`

Update `classifyIntent()` to return buying signal level:
```javascript
function classifyIntent(message) {
  // ... existing logic
  return {
    intent: 'positive' | 'negative' | 'question' | 'unclear',
    confidence: 0-1,
    buyingSignal: 'high' | 'medium' | 'low' | null,
    buyingSignalScore: 30 | 15 | 5 | 0,
  };
}
```

### Step 3: Update Scoring for Buying Signals
**File:** `src/services/scoring.js`

Add buying signal scoring rules:
```javascript
const SCORING_RULES = {
  // ... existing
  buying_signal_high: 30,
  buying_signal_medium: 15,
  buying_signal_low: 5,
};
```

### Step 4: Store Buying Signals in Lead Metadata
**File:** `src/routes/webhooks.js`

When SMS received, store buying signal in lead metadata:
```javascript
// Update lead with buying signal
if (buyingSignal) {
  const signals = lead.metadata?.buying_signals || [];
  signals.push({
    type: buyingSignal,
    source: 'sms',
    text: Body.substring(0, 100),
    detected_at: new Date().toISOString(),
  });
  await supabase.from('leads').update({
    metadata: { ...lead.metadata, buying_signals: signals },
  }).eq('id', lead.id);
}
```

### Step 5: Add Real-Time Detection in LiveCopilot
**File:** `admin/src/components/LiveCopilot.jsx`

Add buying signal detection alongside objection detection:
```javascript
const BUYING_SIGNAL_KEYWORDS = [
  'when can you start', 'how do i sign up', 'what\'s the next step',
  'let\'s do it', 'i\'m ready', 'sign me up', 'send me',
  'need asap', 'starting monday', 'need workers',
];

const detectBuyingSignal = (text) => {
  const lowerText = text.toLowerCase();
  return BUYING_SIGNAL_KEYWORDS.some(kw => lowerText.includes(kw));
};
```

### Step 6: Create Buying Signal Suggestion Component
**File:** `admin/src/components/LiveCopilot.jsx`

Show green "buying signal detected" card (opposite of red objection card):
- Highlight the signal phrase
- Provide closing suggestion
- Show "They're ready!" encouragement

### Step 7: Add Buying Signal to Post-Call Analysis
**File:** `src/services/ai.js`

Update `generatePostCallSummary()` prompt to extract buying signals:
```javascript
// Add to prompt:
"buying_signals": [
  {
    "phrase": "exact phrase they said",
    "signal_type": "high|medium|low",
    "timestamp_approx": "early|middle|late in call"
  }
],
"buying_signal_score": 0-100
```

### Step 8: Update Call List Priority for Buying Signals
**File:** `src/services/callListRanker.js`

Add buying signal weight to priority calculation:
```javascript
// Check for recent buying signals
const recentSignals = lead.metadata?.buying_signals?.filter(s =>
  new Date(s.detected_at) > new Date(now - 7 * 24 * 60 * 60 * 1000)
);
if (recentSignals?.length > 0) {
  const signalBonus = recentSignals.reduce((sum, s) =>
    sum + (s.type === 'high' ? 100 : s.type === 'medium' ? 50 : 20), 0
  );
  score += Math.min(150, signalBonus);
  reason = `${recentSignals.length} buying signal${recentSignals.length > 1 ? 's' : ''} detected`;
}
```

### Step 9: Show Buying Signals in UI
**File:** `admin/src/pages/CallList.jsx`

Add buying signal badge to lead cards:
```jsx
{lead.metadata?.buying_signals?.length > 0 && (
  <span className="px-2 py-0.5 bg-green-500/20 text-green-400 text-xs rounded-full">
    🔥 {lead.metadata.buying_signals.length} buying signal{lead.metadata.buying_signals.length > 1 ? 's' : ''}
  </span>
)}
```

### Step 10: Build & Deploy
- Build frontend
- Deploy to production

### Step 11: Documentation
- Update SYSTEM-INTEL.md
- Update this plan file

---

## Files to Modify

| File | Changes |
|------|---------|
| `src/utils/intent.js` | Add buying signal patterns + detection |
| `src/services/scoring.js` | Add buying signal scoring rules |
| `src/routes/webhooks.js` | Store buying signals in lead metadata |
| `admin/src/components/LiveCopilot.jsx` | Real-time buying signal detection + UI |
| `src/services/ai.js` | Extract buying signals in post-call analysis |
| `src/services/callListRanker.js` | Factor buying signals into priority |
| `admin/src/pages/CallList.jsx` | Show buying signal badges |

---

## No Schema Changes Required

Using existing JSONB fields:
- `leads.metadata.buying_signals` - array of detected signals
- `communications.metadata.buying_signal` - per-message signal

---

## Success Criteria

1. **SMS detection** - "When can you start?" classified as high buying signal
2. **Real-time alerts** - LiveCopilot shows green card when signal detected
3. **Score boost** - Lead score increases when buying signal detected
4. **Priority boost** - Leads with signals move up call list
5. **Post-call extraction** - AI identifies buying signals in transcripts
6. **Visual indicator** - Buying signal badge on lead cards

---

## Testing Scenarios

| Scenario | Expected Result |
|----------|-----------------|
| SMS: "When can you start?" | High buying signal, +30 score |
| SMS: "What does it cost?" | Low buying signal, +5 score |
| Call: "Let's do it, sign me up" | Green card in LiveCopilot |
| Post-call transcript with signals | AI extracts and lists them |
| Lead with 3 buying signals | Shows badge, higher priority |

---

**✅ IMPLEMENTATION COMPLETE**

Build order (all done):
1. ✅ Intent patterns + classification
2. ✅ SMS webhook storage
3. ✅ Scoring rules
4. ✅ LiveCopilot real-time detection
5. ✅ Post-call AI extraction
6. ✅ Call list priority
7. ✅ UI badges
8. ✅ Build & deploy
9. ✅ Document
