HubSpot Workflow Recipes - Ready-to-Implement
Production-ready workflow patterns for B2B SaaS RevOps (€15M-150M ARR, Benelux region).
1. Lead Lifecycle Automation: Lead → MQL → SQL → Opportunity
Workflow: Auto-MQL on Lead Score Threshold
Purpose: Automatically promote leads to MQL status when they meet fit + engagement thresholds.
| Component | Details |
|---|---|
| Trigger | Contact property changed: hs_lead_score becomes ≥ 60 |
| Conditions | • AND fit_score ≥ 60• AND engagement_score ≥ 40• AND lifecycleStage = "Lead" or "Subscriber" |
| Actions | 1. Set property: lifecycleStage → "MQL"2. Set property: lead_status → "Open"3. Create task: Assign to BDR, due in 2 days 4. Send notification: Notify lead owner in Slack 5. Enroll in workflow: "MQL to SQL Nurture Sequence" |
| Notes | • Threshold aligned with marketing-ops lead-scoring-models.md • Triggers BDR contact within 2 days • Prevents duplicate enrollments with "is not already enrolled" check |
Workflow: Auto-SQL on First Sales Activity
Purpose: Promote MQL to SQL when sales rep engages (call, meeting, email).
| Component | Details |
|---|---|
| Trigger | Contact property changed: last_activity_date occurs |
| Conditions | • AND lifecycleStage = "MQL"• AND lead_status = "Open" or "Working"• AND days_inactive < 2 (recent activity)• AND activity type = Email, Call, or Meeting Log |
| Actions | 1. Set property: lifecycleStage → "SQL"2. Set property: lead_status → "Contacted"3. Increment: num_contacted_notes4. Create opportunity (if not exists): Deal amount = €0 (TBD) 5. Notify: Slack alert to sales manager 6. Add note: "Promoted to SQL - [rep name] engaged on [date]" |
| Notes | • Sales qualifies MQL through conversation (MEDDIC/BANT check) • Opportunity created at contact, not yet deal creation • Sales rep populates deal amount, timeline, budget, champion • Prevents spam/accidental promotions with conditions |
Workflow: Auto-Opportunity Creation on Deal Qualification
Purpose: Create formal sales opportunity when SQL is fully qualified.
| Component | Details |
|---|---|
| Trigger | Contact property changed: deal_qualification_method is set |
| Conditions | • AND lifecycleStage = "SQL"• AND budget_confirmed = true• AND timeline_confirmed = true• AND decision_process_understood = true• AND NO opportunity already associated |
| Actions | 1. Create deal: Associated to contact + company 2. Set deal stage: "Qualification" 3. Set deal amount: Copy from estimated_annual_value (if exists) 4. Assign deal owner: Inherit from contact owner 5. Set probability: 20% (for Qualification stage) 6. Set closedate: 90 days out (default) 7. Create task: Sales rep to schedule discovery call 8. Enroll: "Deal Progression Automation" workflow 9. Send email: Qualified opportunity notification to AE team |
| Notes | • Requires sales rep to confirm MEDDIC elements before trigger • Amount pulled from estimated value, updated later in deal stage • Closedate is estimate; updated as deal progresses • Prevents duplicate opportunities with "no associated deals" check |
2. Lead Routing Workflows
Workflow: Territory-Based Routing
Purpose: Auto-assign leads to AEs based on company location/industry.
| Component | Details |
|---|---|
| Trigger | Contact created or Lead status property changes to "Open" |
| Conditions | • lifecycleStage = "MQL"• Contact does not have an owner assigned • company.country = "Netherlands" OR "Belgium" OR "Germany" |
| Actions | Route by Territory + Company Size: Netherlands: 1. IF company.country = "Netherlands"- Assign to: AE1 (Primary territory) - Create task: "Netherlands - First contact in 48 hours" Belgium: 1. IF company.country = "Belgium"- Assign to: AE2 (Primary territory) - Create task: "Belgium - First contact in 48 hours" Germany: 1. IF company.country = "Germany"- Assign to: AE3 (Primary territory) - Create task: "Germany - First contact in 48 hours" All Routes: • Set property: owner_assigned_date → Today• Send email: Welcome email to assigned rep • Send notification: Slack to regional manager |
| Notes | • Assumes 3 AEs covering Benelux + Germany • Customize territory definitions per org • Prevents double-assignment with "does not have owner" condition • Escalation: If no assignment in 72 hours, notify manager |
Workflow: Round-Robin Lead Assignment
Purpose: Distribute new MQLs equally across available AEs (capacity-based).
| Component | Details |
|---|---|
| Trigger | Contact property changed: lifecycleStage → "MQL" |
| Conditions | • Contact owner = empty (unassigned) • company.industry = target industries (SaaS, FinTech, MarTech, etc.)• arr_eur between €15M-150M (ICP match) |
| Actions | Round-Robin Assignment: 1. Get list of active AEs: [AE1, AE2, AE3, AE4] 2. Count open MQLs for each AE (must be < 20) 3. Assign to AE with lowest count 4. Set property: owner → Assigned AE5. Set property: owner_assigned_date → Today6. Create task: "Welcome call - Introduce yourself, 48 hour target" 7. Send Slack: Notify AE with MQL card 8. Send email: Auto-confirmation to contact (CRM automation) If all AEs at capacity: • Hold in queue (wait 24 hours) • Retry assignment (workflow logic) • If still no capacity: Notify sales manager |
| Notes | • "Open" = currently has <20 active leads • Capacity check prevents overloading • Round-robin rotates per MQL received • Manual override: sales manager can reassign |
Workflow: Capacity-Based Lead Routing (Alternative)
Purpose: Route new MQLs to AEs with lowest pipeline/opportunity count.
| Component | Details |
|---|---|
| Trigger | Contact property changed: lifecycleStage → "MQL" |
| Conditions | • Contact owner = empty • icp_match_status = "Perfect Fit" OR "Good Fit"• Company not already in account management |
| Actions | Capacity Check: 1. Calculate for each AE: - Open opportunities count (dealstage ≠ Closed) - MQL assignments in last 7 days - Total pipeline value (EUR) 2. Assign to AE with: - Lowest open opportunity count (target: <15) - AND lowest pipeline value (enables growth) 3. Set property: owner → Selected AE4. Create task: Assigned AE → "Reach out within 24 hours" 5. Notify: Assigned AE via Slack + email 6. Set priority: High (red flag) if AE at max capacity |
| Notes | • Prevents BDRs from overloading AEs • Capacity measured by opportunities, not just count • Helps junior AEs build pipeline at sustainable pace • High-value leads routed first |
3. Deal Stage Automation
Workflow: Auto-Create Tasks on Deal Stage Change
Purpose: Ensure sales team follows process by auto-creating next-step tasks per stage.
| Component | Details |
|---|---|
| Trigger | Deal property changed: dealstage changes |
| Conditions | Trigger on any stage change |
| Actions | Stage: Qualification • Create task: "Schedule discovery call" (due in 3 days) • Create task: "Document MEDDIC elements" (due in 5 days) • Set property: next_step → "Discovery call scheduled"• Expected close: 45-60 days out Stage: Proposal • Create task: "Send proposal" (due in 1 day) • Create task: "Schedule proposal review" (due in 5 days) • Create task: "Get champion internal approval" (due in 7 days) • Set property: next_step → "Awaiting proposal acceptance"• Expected close: 30-45 days out Stage: Contract/Negotiation • Create task: "Send contract via e-sign" (due in 1 day) • Create task: "Follow up on signature" (due in 5 days) • Create task: "Prepare onboarding" (due in 10 days) • Set property: next_step → "Awaiting legal signature"• Expected close: 7-14 days out Stage: Closed Won • Create task: "CS - Schedule kickoff" (due in 1 day) • Create task: "Create renewal reminder" (recurring, 11 months) • Set property: lifecycleStage → "Customer" (on contact)• Send email: Sales + CS team (deal won notification) • Create renewal record (custom workflow or manual) Stage: Closed Lost • Create task: "Document loss reason" (due in 1 day) • Create task: "Follow up in 6 months" (due in 180 days) • Set property: lifecycleStage → "Evangelist" or back to "SQL" (if pursuing)• Send email: Sales leadership (loss analysis) |
| Notes | • Tasks auto-assign to deal owner • Keeps deals moving; prevents stalls • Customize task templates per AE preference • Prevent task spam: Check "not already task" condition |
Workflow: Deal Escalation on Stall
Purpose: Alert manager when deal stalls (no activity) for >7 days.
| Component | Details |
|---|---|
| Trigger | Workflow timer: Daily check |
| Conditions | • Deal stage = "Qualification" OR "Proposal" OR "Contract" • Days inactive > 7 • Deal amount ≥ €50k (escalate high-value only) • Deal owner assigned |
| Actions | 1. Create task: Deal owner → "Stalled deal - Check in with buyer" (due in 1 day) 2. Notify: Sales manager via Slack (escalation) 3. Alert email: "Deal [name] inactive 7+ days" 4. Add note: "Auto-escalated [date] - No activity since [last_date]" 5. Recommendation: Call/email buyer + check if still interested 6. If no response in 3 days: Move to "On Hold" pipeline OR close as "No Decision" |
| Notes | • Only escalates significant deals (€50k+) • Prevents deals from dying in pipeline • Gives AE 3 days to respond before closure • Customizable: Change threshold for your team |
4. Re-Engagement Workflows
Workflow: Stale Lead Re-Engagement
Purpose: Re-nurture leads that haven't engaged in 30+ days.
| Component | Details |
|---|---|
| Trigger | Workflow timer: Weekly (check every Monday) |
| Conditions | • lifecycleStage = "MQL" OR "SQL"• days_inactive ≥ 30• Last email open > 30 days ago • NOT recently unsubscribed |
| Actions | Automated Re-Engagement Sequence: 1. Send email: "We miss you - Here's what's new" (personalized) 2. Wait: 3 days 3. If no open: Send follow-up (different subject) 4. Wait: 5 days 5. If no engagement after 3 emails: Create task - Task: Sales rep → "Reach out by phone" (due in 2 days) - Set property: re_engagement_sequence_enrolled = trueIf Engagement Detected: • Increment: engagement_score + 10 points• Recalculate MQL status • If newly qualified: Route to AE (per routing workflow) • Send notification: Marketing team (lead re-activated) If No Engagement After 60 Days: • Unenroll from nurture sequence • Move to "Nurture" list (lower priority) • Set property: lifecycleStage → "Subscriber"• Keep in CRM for future re-targeting |
| Notes | • Prevents false negatives (stale doesn't = uninterested) • Sales touch adds human element • Email sequence should be valuable, not salesy • Segment by interest (recent webinar attendee, download recent content, etc.) |
Workflow: Stalled Deal Recovery
Purpose: Re-engage buyers when deal stalls for 14+ days in middle stages.
| Component | Details |
|---|---|
| Trigger | Workflow timer: Daily check |
| Conditions | • Deal stage = "Qualification" OR "Proposal" • days_inactive ≥ 14• Deal amount ≥ €30k • Deal not marked as "On Hold" • Last contact was sales activity (call/meeting/email) |
| Actions | Day 14 (First Alert): 1. Create task: AE → "Reach out to champion" (due in 1 day) 2. Send Slack: AE reminder 3. Suggest action: "Follow up on proposal" OR "Check on internal approval" Day 21 (Escalation): 1. If no response: Create task - Task: Sales manager → "Discuss deal strategy" (due in 1 day) 2. Notify: Sales director 3. Recommendation: Likely stalled, consider "On Hold" Day 30 (Final): 1. If still no activity: - Move to: dealstage = "On Hold" OR close as "No Decision"- Set property: stalled_deal_date = [date]- Create task: Follow-up in 60 days 2. Document: "Buyer not responsive; paused outreach" |
| Notes | • Timings: 14, 21, 30 days (customize per company) • Escalation ensures visibility • "On Hold" vs "Closed Lost": Manager judgment call • Can re-open deal if buyer reaches out |
5. Data Hygiene Workflows
Workflow: Fill Missing Firmographic Data
Purpose: Append missing company/contact data to improve lead quality.
| Component | Details |
|---|---|
| Trigger | Contact created |
| Conditions | • Email domain exists • Company property = empty OR domain doesn't match email • NOT a bounced/invalid email • do_not_contact = false |
| Actions | 1. Lookup & Auto-Populate: - Use Clearbit/Apollo/similar integration - Find company by email domain - Auto-populate: Company name, industry, size, location 2. Enrich Contact: - Find contact title, phone, LinkedIn URL - Auto-populate: Job title, phone number 3. Create Contact Association: - Link contact to company - If company doesn't exist in HubSpot: Create it 4. Scoring: - Calc fit_score based on new data - If score ≥ 60: Set as lead candidate 5. QA: - Create task: "Review auto-enriched data" (for BDR) - Flag high-confidence data vs. lower-confidence - Manual correction if needed - Set property: data_enrichment_date = Today |
| Notes | • Requires third-party enrichment tool integration • Only use high-confidence data (80%+ match) • Flag lower-confidence fields for manual review • Prevents bad data from skewing scoring • Cost: Track enrichment API usage |
Workflow: Standardize Industry & Company Size
Purpose: Ensure consistent data format for reporting accuracy.
| Component | Details |
|---|---|
| Trigger | Contact created OR company property changed: industry |
| Conditions | • industry field populated• Value not in standardized list • Example: "SaaS" vs "Software as a Service" vs "saas" |
| Actions | 1. Standardize Values: - IF industry CONTAINS "saas" OR "software" (case-insensitive) - Set to: "SaaS" - IF industry CONTAINS "finance" OR "banking" - Set to: "FinTech" - IF industry CONTAINS "marketing" OR "advertising" - Set to: "MarTech" - (etc. for all target verticals) 2. Standardize Company Size: - IF numberofemployees = empty BUT annualrevenue populated- Estimate employees from revenue (use benchmark rules) - IF multiple size indicators conflict: Flag for manual review 3. QA Flag: - If automation made change: Create task → "Verify auto-standardized data" - Note: "Auto-standardized from [original value]" - Allow sales to override if incorrect |
| Notes | • Prevents duplicate/similar values from breaking reports • Use lookup table for standardization rules • Document mappings (SaaS includes "Cloud Software", etc.) • Review quarterly as new variations appear |
Workflow: Duplicate Detection & Merge
Purpose: Identify and merge duplicate contacts/companies.
| Component | Details |
|---|---|
| Trigger | Contact created |
| Conditions | • Email exists • Company exists (either provided or enriched) • Check: Email OR (First + Last name + Company) already in CRM |
| Actions | If Exact Match Found: 1. Flag: Create task → "Possible duplicate - Review and merge" 2. Notify: Data ops team or BDR 3. Provide: Link to existing record + comparison If Duplicate Confirmed: 1. Merge: Use HubSpot merge tool - Primary record: The one with more activity - Secondary: Archive 2. Consolidate: History, notes, deal associations 3. Update: All associations to point to primary After Merge: 1. Create task: "Update sales notes with merged record" 2. Notify: Sales team (avoid orphaned deals) 3. Document: Why merged (duplicate email, etc.) |
| Notes | • Run automated duplicate check weekly • Don't auto-merge; always require human confirmation • Risk: Merging loses deal history; use care • Cleanup helps: Accurate reporting, no duplicate follow-ups |
6. Renewal & Expansion Trigger Workflows
Workflow: Renewal Reminder (Recurring)
Purpose: Alert account managers/CSM before contract renewal with enough lead time.
| Component | Details |
|---|---|
| Trigger | Contact property changed: contract_renewal_month = next month |
| Conditions | • lifecycleStage = "Customer"• Contact has associated deal (Closed Won) • Deal age ≥ 1 month (exclude new customers) |
| Actions | 60 Days Before Renewal: 1. Create task: CSM → "Initiate renewal conversation" (due in 5 days) 2. Create task: AE → "Review renewal terms, prepare quote" (due in 10 days) 3. Send email: CSM reminder 4. Set property: renewal_initiated_date = Today45 Days Before Renewal: 1. If no response: Create follow-up task 2. Notify: Sales director (flag for attention) 30 Days Before Renewal: 1. Check: Renewal amount set? Quote sent? 2. If not: Escalate to manager At Renewal: 1. Create new deal: dealtype = "Renewal"2. Copy: Previous deal amount (adjusted for expansion) 3. Set closedate: Contract end date 4. Assign: To CSM/renewal AE After Renewal: 1. If won: Update contract_renewal_month for next year 2. If lost: Set lifecycleStage → "Churned" |
| Notes | • Customize timing per company (some prefer 90-day notice) • CSM + AE collaboration needed • Expansion upsell opportunity: Included in renewal conversation • Set up before customer onboarding |
Workflow: Expansion Opportunity Trigger
Purpose: Identify and create expansion opportunities for growing customers.
| Component | Details |
|---|---|
| Trigger | Deal property changed: dealstage → "Closed Won" |
| Conditions | • Deal is new business (not renewal) • Customer was land-and-expand strategy • Deal closed in last 90 days |
| Actions | 1. Post-Sales Handoff: - Send email: CSM + Account Manager (closed deal notification) - Create task: CSM → "Schedule onboarding" (due in 1 day) 2. Monitor Usage (automated via integration, or manual): - After 30 days: Check product usage metrics - IF high engagement (80%+ feature adoption): Flag expansion candidate - Recommend: Add users, upgrade tier, additional modules 3. Create Expansion Opportunity: - On day 45 post-close: - Create deal: dealtype = "Expansion"- Deal name: "[Customer] - Expansion: [Module/Tier]" - Amount: €0 initially (CSM to estimate) - Stage: "Proposal" (CSM identifies specific product fit) - Owner: CSM → present to customer → handoff to AE when ready to close 4. Expansion Nurture: - Create task: CSM → "Discuss expansion opportunity" (due in 60 days) - Suggest: New user seats, add-on modules, premium tier - Provide: ROI analysis based on usage |
| Notes | • Expansion drives ARR growth post-land • CSM + AE partnership: CSM identifies, AE closes • Usage data integration critical (product analytics) • Set ARR growth targets per renewal + expansion |
Workflow Implementation Checklist
- Test each workflow in sandbox environment first
- Define all custom properties needed (reference: property-catalog.md)
- Train sales + marketing teams on workflow triggers
- Set up Slack notifications for key handoffs (MQL to AE, deal escalation)
- Document workflow logic in team playbook
- Create monthly audit: Check for workflow failures, task completion rates
- Set success metrics per workflow (e.g., MQL routing time < 24 hours)
- Review and update quarterly as team processes evolve
- Archive old/unused workflows to avoid clutter
- Monitor API/action limits (avoid throttling)
Quick Reference: When to Use Each Workflow
| Workflow | When to Enable | Owner | Key Metric |
|---|---|---|---|
| Lead Lifecycle Auto-Promotion | Day 1 (foundation) | Marketing Ops | MQL time < 48 hours |
| Territory Routing | Day 1 | Sales Ops | Routing time < 4 hours |
| Deal Stage Tasks | Week 1 | Sales Ops | Task completion 90%+ |
| Stale Lead Re-Engagement | Week 2 | Marketing | Re-engagement rate 20%+ |
| Data Enrichment | Week 3 | Marketing Ops | Data completeness 85%+ |
| Renewal Triggers | Month 3 (post-first-customer) | Revenue Ops | Renewal rate 90%+ |
| Expansion Opportunities | Month 3 (post-first-customer) | RevOps | Expansion rate 30%+ |