Lead Scoring at Scale with Custom Behavioral Events
/ 10 min read
Table of Contents
HubSpot’s lead scoring can’t include Custom Events. I spent an hour looking for the option before accepting that it genuinely doesn’t exist. An hour I’ll never get back.
If you’re tracking product usage, login frequency, or in-app behaviour through Custom Events and want those signals in your lead score, there’s no dropdown for that. But there’s a workaround — and it’s now running in three of my enterprise implementations.
The Lead Scoring Landscape in 2025
Before diving into the solution, let’s clarify what’s happening with HubSpot lead scoring. There’s been significant change recently.
The Score Property Sunset
HubSpot is retiring the legacy score properties:
| Date | Change |
|---|---|
| May 1, 2025 | Cannot create new score properties |
| July 1, 2025 | Cannot edit existing score properties |
| August 31, 2025 | Existing score properties stop updating |
If you’re reading this before August 2025, you have time to migrate. If after, you’re already on the new system.
The New Lead Scoring Tool
HubSpot’s replacement separates scoring into two distinct dimensions:
Fit Score — How well does this record match your ICP? Based on demographic and firmographic properties like industry, company size, job title, and revenue.
Engagement Score — How actively is this record interacting with your brand? Based on behavioural events like email opens, page views, form submissions, and meeting bookings.
This is conceptually cleaner than the old single-score model. But it still has gaps. Gaps you’ll discover at the exact moment you need them not to exist.
The Custom Events Problem
Custom Events (formerly Custom Behavioral Events) let you track virtually anything:
- Product logins and feature usage
- In-app actions and milestones
- Third-party system events via API
- JavaScript-tracked interactions beyond standard HubSpot tracking
You can create up to 500 unique custom events per portal. They appear in contact timelines, can trigger workflows, and work with lists.
But here’s the gap: The native lead scoring tool has limited support for custom events in its criteria. Specifically:
- You can’t use “contains” logic on event names (e.g., “any event where name contains ‘upgrade’”)
- Event property filtering is limited
- Aggregate counting (e.g., “completed event X more than 5 times in 30 days”) requires workarounds
- Legacy custom behavioral events work differently from new custom events
The HubSpot Ideas forum has been asking for better custom event integration in scoring since 2020. Progress has been made, but for complex scoring requirements, you’ll likely need to augment the native tool.
The Workflow-Driven Scoring Pattern
The solution is to use workflows as your scoring engine, with custom number properties storing the calculated scores.
Architecture Overview
┌─────────────────────────────────────────────────────────────┐│ CUSTOM EVENTS ││ (Product usage, app interactions, external system events) │└─────────────────────────────────────────────────────────────┘ │ ▼┌─────────────────────────────────────────────────────────────┐│ SCORING WORKFLOWS ││ • Event triggers increment/decrement score properties ││ • Time-based decay via scheduled workflows ││ • Aggregate logic via branching │└─────────────────────────────────────────────────────────────┘ │ ▼┌─────────────────────────────────────────────────────────────┐│ CUSTOM SCORE PROPERTIES ││ • Behavior Score (number, workflow-controlled) ││ • Engagement Score (number, workflow-controlled) ││ • Combined Score (calculated field) │└─────────────────────────────────────────────────────────────┘ │ ▼┌─────────────────────────────────────────────────────────────┐│ DOWNSTREAM ACTIONS ││ • Lifecycle stage updates ││ • Sales notifications ││ • List membership for segmentation ││ • Native HubSpot lead score (optional hybrid) │└─────────────────────────────────────────────────────────────┘Step 1: Create Score Properties
Create custom contact properties to hold your workflow-calculated scores:
| Property | Type | Description |
|---|---|---|
behavior_score | Number | Points from behavioural events |
fit_score | Number | Points from demographic attributes |
engagement_velocity | Number | Recent engagement intensity |
total_lead_score | Calculation | behavior_score + fit_score |
For the calculated property, use this formula:
behavior_score + fit_scoreYou can also add weighting:
(behavior_score * 0.6) + (fit_score * 0.4)Step 2: Build Event-Triggered Scoring Workflows
Create workflows that trigger when custom events occur and increment the appropriate score.
Example: Product Login Scoring
Workflow: [Scoring] Product LoginTrigger: When event occurs → Custom Events → "app_login"Re-enrollment: Yes, every time
Actions:1. Increase property value - Property: behavior_score - Increase by: 5
2. Branch: If behavior_score > 200 - Yes → Set behavior_score to 200 (cap) - No → ContinueExample: Feature Usage Scoring
Workflow: [Scoring] Premium Feature UsedTrigger: When event occurs → Custom Events → "feature_used" AND event property "feature_tier" equals "premium"Re-enrollment: Yes, every time
Actions:1. Increase property value - Property: behavior_score - Increase by: 15
2. Increase property value - Property: engagement_velocity - Increase by: 1Step 3: Implement Score Decay
Scores should decrease over time if engagement stops. Without decay, a contact who was highly engaged two years ago still appears valuable. They’re not. They’ve forgotten who you are.
Option A: Scheduled Workflow (Simple)
Workflow: [Scoring] Weekly Score DecayTrigger: Contact-based → Scheduled → Every Monday at 6:00 AMEnrollment: All contacts where behavior_score > 0
Actions:1. Decrease property value - Property: behavior_score - Decrease by: 5
2. Branch: If behavior_score < 0 - Yes → Set behavior_score to 0 - No → ContinueOption B: Time-Since-Event Decay (Advanced)
For more sophisticated decay based on time since last engagement:
Workflow: [Scoring] Engagement Decay CheckTrigger: Contact-based → Scheduled → Daily at 2:00 AMEnrollment: All contacts where behavior_score > 0
Actions:1. Branch: Days since last event > 30 - Yes → Decrease behavior_score by 20 - No → Continue to next branch
2. Branch: Days since last event > 14 - Yes → Decrease behavior_score by 10 - No → Continue
3. Branch: If behavior_score < 0 - Yes → Set behavior_score to 0Step 4: Handle Score Caps and Floors
Prevent scores from going negative or exceeding sensible limits:
Workflow: [Scoring] Score Bounds CheckTrigger: Property value changed → behavior_scoreRe-enrollment: Yes
Actions:1. Branch: behavior_score > 200 - Yes → Set behavior_score to 200
2. Branch: behavior_score < 0 - Yes → Set behavior_score to 0Step 5: Trigger Downstream Actions
Use score thresholds to drive lifecycle changes and notifications:
Workflow: [Lifecycle] MQL QualificationTrigger: Filter-based → total_lead_score >= 100 AND lifecycle_stage is any of [Subscriber, Lead]Re-enrollment: No
Actions:1. Set lifecycle stage to "Marketing Qualified Lead"
2. Create task for sales - Title: "New MQL: [Contact Name]" - Assigned to: Contact owner - Due: Today
3. Send internal notification email - To: Sales team - Subject: "High-scoring lead ready for outreach"Handling the “Contains” Problem
One of the most common requirements is scoring based on event name patterns. For example:
- Score any event containing “upgrade” in the name
- Score all “webinar_” prefixed events the same way
- Score different “feature_used” events differently based on properties
Pattern: Event Name Routing Workflow
Since you can’t filter by “event name contains”, create a router workflow:
Workflow: [Scoring] Event RouterTrigger: When event occurs → Any Custom EventRe-enrollment: Yes, every time
Actions:1. Branch: Event name equals "upgrade_prompt_shown" - Yes → Increase behavior_score by 10
2. Branch: Event name equals "upgrade_button_clicked" - Yes → Increase behavior_score by 25
3. Branch: Event name equals "upgrade_completed" - Yes → Increase behavior_score by 50
4. Branch: Event name starts with "webinar_" - Yes → Increase behavior_score by 15
5. Branch: Event name starts with "feature_used" - Yes → Go to sub-branch on feature_tier property - "premium" → +15 points - "standard" → +5 points - Other → +2 pointsNote: You’ll need to update this workflow whenever you add new event types you want to score. Document your scoring logic externally so the team knows what’s being tracked. Future you will thank present you.
Aggregate Scoring: “5+ Events in 30 Days”
The native scoring tool struggles with aggregate requirements like “score contacts who have completed event X at least 5 times in the last 30 days.”
Solution: Counter Properties + Scheduled Reset
Step 1: Create counter property
Property: webinar_registrations_30d (Number)
Step 2: Increment on event
Workflow: [Counter] Webinar RegistrationTrigger: When event occurs → "webinar_registered"Re-enrollment: Yes
Actions:1. Increase webinar_registrations_30d by 1Step 3: Reset counter monthly
Workflow: [Counter] Monthly Reset - WebinarsTrigger: Scheduled → 1st of each month at 1:00 AMEnrollment: All contacts
Actions:1. Set webinar_registrations_30d to 0Step 4: Score based on counter
Workflow: [Scoring] High Webinar EngagementTrigger: Filter-based → webinar_registrations_30d >= 5Re-enrollment: No (or Yes with suppression list)
Actions:1. Increase behavior_score by 302. Add to list "High Webinar Engagement"This pattern is more manual than native scoring but gives you precise control over aggregate logic.
Velocity Scoring: Rewarding Engagement Bursts
Sometimes you want to reward contacts who show sudden spikes in engagement — visiting 10 pages in a day, or attending 3 events in a week.
Pattern: Rolling Engagement Window
Step 1: Track daily engagement
Workflow: [Velocity] Daily Engagement CounterTrigger: Any engagement event (page view, email click, form submission)Re-enrollment: Yes
Actions:1. Increase engagement_today by 1Step 2: Calculate velocity score nightly
Workflow: [Velocity] Nightly Velocity CalcTrigger: Scheduled → Daily at 11:59 PM
Actions:1. Branch: engagement_today >= 10 - Yes → Increase engagement_velocity by 20 - No → Branch: engagement_today >= 5 - Yes → Increase engagement_velocity by 10 - No → Decrease engagement_velocity by 2
2. Set engagement_today to 0 (reset for tomorrow)Step 3: Use velocity in qualification
Add engagement_velocity to your MQL criteria alongside behavior_score. A contact with moderate lifetime engagement but high recent velocity might be more valuable than one with high historical engagement but no recent activity.
Hybrid Approach: Workflow Scores + Native Scoring
You don’t have to choose entirely between workflow-driven and native scoring. A hybrid approach works well:
| Score Type | Method | Use For |
|---|---|---|
| Demographic/Fit | Native Lead Score | Industry, company size, job title, geography |
| Standard Engagement | Native Lead Score | Email opens, page views, form submissions |
| Custom Events | Workflow-driven | Product usage, app events, third-party triggers |
| Aggregate/Velocity | Workflow-driven | ”5+ events in 30 days”, engagement spikes |
Your final qualification logic can reference both:
MQL Criteria:- Native HubSpot Score >= 50- AND behavior_score >= 30- AND (engagement_velocity >= 10 OR total_lead_score >= 100)Performance Considerations
Workflow-driven scoring at scale requires attention to performance:
Workflow Execution Limits
- HubSpot allows up to 500 workflow enrollments per contact per day
- High-volume event tracking can hit this limit
- Consider batching low-value events or sampling
Property Update Frequency
- Score properties update nearly instantly for simple operations
- Complex calculated properties may take up to 2 hours to recalculate
- Build in tolerance for eventual consistency. Patience is a virtue.
Monitoring
Create a dashboard to monitor your scoring system:
- Contacts by score tier (0-25, 26-50, 51-100, 100+)
- Score distribution over time
- MQL conversion rates by score range
- Workflow error rates
Example: SaaS Product Usage Scoring
Here’s a complete example from a recent implementation for a B2B SaaS client:
Events Tracked
| Event | Trigger | Points |
|---|---|---|
app_login | Daily login | +5 (capped at 25/week) |
feature_used | Any feature interaction | +2 to +15 based on tier |
integration_connected | Connects third-party tool | +20 |
team_member_invited | Invites colleague | +25 |
upgrade_page_viewed | Views pricing/upgrade | +10 |
support_ticket_created | Opens support ticket | -5 (friction indicator) |
export_data | Exports their data | -15 (churn risk signal) |
Score Thresholds
| Score Range | Stage | Action |
|---|---|---|
| 0-25 | Evaluating | Nurture sequence |
| 26-50 | Engaged | Product tips sequence |
| 51-100 | Activated | CSM introduction |
| 100+ | Power User | Expansion opportunity alert |
Results
After 90 days:
- 34% increase in CSM-initiated conversations with high-scoring accounts
- 22% improvement in expansion revenue from score-triggered outreach
- 45% reduction in time-to-first-contact for engaged trial users
Migration Path: Legacy to New Scoring
If you’re moving from legacy score properties to the new system (or workflow-driven scoring), here’s a migration checklist:
- Document current scoring logic — Export all criteria from existing score properties
- Map to new structure — Decide what goes in native Fit/Engagement vs workflow-driven
- Build new system in parallel — Don’t turn off old scoring until new is validated
- Compare scores — Run both systems for 2-4 weeks and compare MQL rates
- Validate with sales — Confirm new scores align with actual opportunity quality
- Cut over — Disable legacy scoring, update all downstream workflows and lists
Key Takeaways
- Native scoring has custom event limitations — Complex requirements need workflow augmentation
- Workflow-driven scoring gives full control — Event routing, aggregates, velocity, and decay
- Hybrid approaches work well — Use native for standard signals, workflows for custom events
- Build in decay — Scores without time decay become meaningless
- Monitor and iterate — Scoring models need regular validation against actual conversion data
- Legacy scores are sunsetting — Plan your migration before August 2025
If you’re building enterprise lead scoring in HubSpot and hitting the limitations of the native tool, the workflow pattern described here has worked reliably across multiple implementations. It’s not elegant, but it works — which, in enterprise software, is often the higher virtue.
What scoring patterns have you found effective in HubSpot? I’d be interested to hear other approaches — find me on LinkedIn.