Engagement Scoring
Engagement scoring measures how actively a person interacts with your brand across multiple channels. It applies exponential decay for recency, a quality hierarchy to weight high-value actions above passive ones, and per-channel caps to prevent single-source score domination.
Core Concepts
The engagement engine processes a person's activity history through three layers:
- Signal quality --- Each activity type has a quality multiplier reflecting its intent signal strength
- Exponential decay --- Recent activities contribute more than older ones
- Channel caps --- No single channel can contribute more than its cap to the total score
Signal Quality Hierarchy
Every activity type has a quality multiplier between 0.0 and 1.0. Higher multipliers indicate stronger buying intent:
| Activity Type | Quality Multiplier | Channel | Intent Signal |
|---|---|---|---|
demo_request | 1.0 | web | Highest |
event_attend | 0.9 | events | Very high |
meeting_attend | 0.9 | meetings | Very high |
form_fill | 0.8 | web | High |
content_download | 0.7 | content | Medium-high |
intent_signal | 0.7 | intent | Medium-high |
email_click | 0.6 | Medium | |
ad_click | 0.5 | ads | Medium |
email_thread | 0.5 | Medium | |
email_open | 0.4 | Low-medium | |
page_view | 0.2 | web | Low |
email_sent | 0.1 | Minimal |
The meeting_recorded activity type is intentionally excluded from scoring. Recording a meeting is a system action, not a buying signal. This avoids inflating engagement for accounts using Fathom.video.
Unknown activity types default to a quality multiplier of 0.2 and are assigned to the "other" channel.
Exponential Decay
Activity scores decrease over time following an exponential decay curve. The formula is:
decayMultiplier = 2^(-daysSince / halfLifeDays)
Where:
daysSinceis the number of days between the activity and the reference datehalfLifeDaysis the configurable half-life (default: 30 days)
Decay Curve Characteristics
| Days Since Activity | Decay Multiplier (30-day half-life) |
|---|---|
| 0 (today) | 1.000 |
| 15 | 0.707 |
| 30 | 0.500 |
| 60 | 0.250 |
| 90 | 0.125 |
| 120 | 0.063 |
- Short sales cycles (< 30 days): Use a half-life of 14--21 days to emphasize very recent activity
- Medium sales cycles (30--90 days): The default of 30 days works well
- Long enterprise cycles (90+ days): Consider 45--60 days to keep older signals relevant
Edge Cases
- Future activities (negative
daysSince): Treated as day 0, no decay applied - Half-life of 0: Returns a decay multiplier of 0 (all signals discarded)
- The multiplier is always clamped to
[0, 1]
Per-Channel Caps
Each scoring channel has a maximum score contribution to prevent a single data source from dominating:
| Channel | Default Cap | Mapped Activity Types |
|---|---|---|
email | 30 | email_open, email_click, email_thread, email_sent |
web | 25 | page_view, form_fill, demo_request |
meetings | 25 | meeting_attend |
intent | 25 | intent_signal |
events | 20 | event_attend |
content | 20 | content_download |
ads | 15 | ad_click |
other | 15 | Any unmapped activity type |
The theoretical maximum engagement score is the sum of all channel caps: 175, but since the final score is clamped to 100, multi-channel engagement is what drives a person toward the top of the scale.
Scoring Formula
For each activity, the per-signal score is:
signalScore = signalWeight * qualityMultiplier * decayMultiplier
Signals are grouped by channel, summed within each channel, and capped:
channelScore = min(sum(signalScores), channelCap)
The final engagement score is:
engagementScore = min(100, sum(channelScores))
Worked Example
A person has three activities:
| Activity | Days Ago | Quality | Decay (30d) | Signal Score |
|---|---|---|---|---|
| demo_request | 5 | 1.0 | 0.891 | 0.891 |
| email_click | 10 | 0.6 | 0.794 | 0.476 |
| page_view | 45 | 0.2 | 0.354 | 0.071 |
Channel aggregation:
- web: demo_request (0.891) + page_view (0.071) = 0.962 (cap 25: capped at 0.962)
- email: email_click (0.476) (cap 30: capped at 0.476)
Total engagement score: 0.962 + 0.476 = 1.4 (low because only 3 activities)
In practice, active prospects have dozens or hundreds of activities. A person with 20+ activities across multiple channels over the past 30 days will typically score 40--70.
Configuration Reference
interface EngagementConfig {
decayHalfLifeDays: number; // default: 30
signalWeights: Record<string, number>; // default: all 1.0
channelCaps: Record<string, number>; // see table above
qualityHierarchy: Record<string, number>; // see table above
}
Signal Weights
Signal weights (signalWeights) are multipliers applied before quality and decay. They default to 1.0 for all activity types. You can increase weights for high-value signals or decrease them to dampen noisy sources:
{
"signalWeights": {
"demo_request": 2.0,
"page_view": 0.5
}
}
This would double the contribution of demo requests and halve page views.
Related Pages
- Scoring Overview --- Where engagement fits in the pipeline
- Fit Scoring --- The other scoring axis
- Tier Assignment --- How engagement + fit determine tiers
- Account Scoring --- How person engagement rolls up