Skip to main content

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:

  1. Signal quality --- Each activity type has a quality multiplier reflecting its intent signal strength
  2. Exponential decay --- Recent activities contribute more than older ones
  3. 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 TypeQuality MultiplierChannelIntent Signal
demo_request1.0webHighest
event_attend0.9eventsVery high
meeting_attend0.9meetingsVery high
form_fill0.8webHigh
content_download0.7contentMedium-high
intent_signal0.7intentMedium-high
email_click0.6emailMedium
ad_click0.5adsMedium
email_thread0.5emailMedium
email_open0.4emailLow-medium
page_view0.2webLow
email_sent0.1emailMinimal
Excluded Signal: meeting_recorded

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:

  • daysSince is the number of days between the activity and the reference date
  • halfLifeDays is the configurable half-life (default: 30 days)

Decay Curve Characteristics

Days Since ActivityDecay Multiplier (30-day half-life)
0 (today)1.000
150.707
300.500
600.250
900.125
1200.063
Choosing Your Half-Life
  • 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:

ChannelDefault CapMapped Activity Types
email30email_open, email_click, email_thread, email_sent
web25page_view, form_fill, demo_request
meetings25meeting_attend
intent25intent_signal
events20event_attend
content20content_download
ads15ad_click
other15Any 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:

ActivityDays AgoQualityDecay (30d)Signal Score
demo_request51.00.8910.891
email_click100.60.7940.476
page_view450.20.3540.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)

Real-World Scores

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.