Interest Signals Detection¶
Overview¶
Interest Signals Detection analyzes visitor messages to identify buying signals and trigger demo proposals at the right moment. The system scores signals cumulatively across the conversation.
How It Works¶
flowchart TD
A[Visitor message] --> B[interest_signals_detector]
B --> C{Analyze for signals}
C --> D[Score each signal 0-100]
D --> E[Add to cumulative score]
E --> F{Score > threshold?}
F -->|Yes| G[Propose demo with 👇]
F -->|No| H[Continue conversation]
Signal Categories¶
The detector looks for three categories of buying signals:
Engagement Signals¶
- Message count and conversation depth
- Time spent in conversation
- Questions about specific features
Buying Signals¶
- Pricing questions
- Timeline/urgency mentions
- Budget discussions
- Decision-maker language
Context Signals¶
- Company size mentions
- Use case descriptions
- Industry/sector information
Scoring System¶
Each detected signal gets a score from 0-100 based on evidence strength:
| Signal Strength | Score Range | Example |
|---|---|---|
| Weak | 0-30 | "Just browsing" |
| Moderate | 31-60 | "Looking at options" |
| Strong | 61-100 | "Need this by Q2, budget approved" |
Scores accumulate across turns until the threshold triggers a demo proposal.
Emoji Marker¶
- 👇 (pointing down) marks a demo proposal
- Detected by
dialog_state_extractor.py - Triggers special handling in the frontend (shows CTA buttons)
Key Files¶
Backend¶
| File | Purpose |
|---|---|
ixchat/nodes/interest_signals_detector.py |
Main detection logic |
ixchat/pydantic_models/interest_signals.py |
Signal definitions and scoring |
ixchat/pydantic_models/interest_signals_state.py |
State tracking |
ixchat/utils/demo_proposal.py |
Threshold checking |
State Tracking¶
class InterestSignalsState(BaseModel):
cumulative_score: int = 0 # Current session score
lifetime_interest_score: int = 0 # Persists across sessions
detected_signals: list[KeySignal] # Signals found
demo_proposed: bool = False # Whether demo was proposed this session
LLM Output¶
class InterestSignalsDetectionOutput(BaseModel):
detected_signals: list[KeySignal] = Field(
description="List of detected interest signals with scores"
)
Demo Proposal Flow¶
When cumulative score exceeds the threshold:
interest_signals_detectorsetsshould_propose_demo = True- Answer includes 👇 emoji marker
dialog_state_extractordetects marker and updates state- Frontend shows demo CTA buttons
- Score resets after demo is proposed
Lifetime Score Persistence¶
Interest scores persist across sessions via lifetime_interest_score:
- Stored in Supabase
conversationstable - Loaded on session start via
get_lifetime_interest_score() - Ensures returning high-interest visitors get appropriate treatment
Debugging¶
Backend logs use prefixes:
📊 [INTEREST SIGNALS] Analyzing conversation for buying signals
📊 [INTEREST SIGNALS] Detected signals: pricing_inquiry (85), timeline_mention (60)
📊 [INTEREST SIGNALS] Cumulative score: 145 (threshold: 100)
👇 [INTEREST SIGNALS] Proposing demo - score exceeds threshold
Configuration¶
Demo proposal threshold can be configured per site in custom_config:
Testing¶
Related¶
- In-Chat Booking Email - Email capture after demo proposal
- Form Field Extraction - Extracting qualification data