HubScan
Seat & health audit

Prepared for Cadence

Generated 2026-09-06T10:12:03+00:00 · 14 active user(s) · 90-day activity window · Tier: enterprise

Health score

74/100 (hygiene pillars) 11 Red12 Amber

Top findings

1 fixed sequence sender(s) cannot send: ivo.stern@cadence.example (deactivated). These enabled workflows name the user as the sender, but HubSpot requires a sender to hold a paid Sales/Service seat and a connected personal inbox, so every such enrollment fails. Reassign the sender or turn the workflow off.

Automation health: notifications with no recipient

2 internal notifications on enabled workflows can reach nobody. Every user the action names is deactivated or gone from the portal, and every team it names is empty or gone — the last column says which. HubSpot answers each send with “No valid recipients were identified for this notification.” Repoint the recipient or turn the action off.
WorkflowActionWhy nobody is reached
Escalation: alert deal deskinternal email notificationivo.stern@cadence.example is deactivated
Renewal risk: notify renewals teamin-app notificationteam Renewals has no active members
HubSpot no longer names a notification's individual recipients. The workflow API still returns the teams and the owner properties an action addresses, but it stops returning its named people once the action is saved: only actions left untouched for a long time still carry them, while the workflow editor shows them on all of them. Every action here names a team or an owner, so none of them went unchecked, but the same gap bounds what a row above can prove. And a recipient HubSpot does return is still not a delivery. A workflow notification only arrives if that person has workflow notifications switched on in their own preferences, which no API exposes, so HubSpot can report a partial send failure on an action nothing here flags. An empty table is not evidence that these notifications are landing, only that their recipients still exist.

Automation health: owner rotation that can assign nobody

1 enabled workflow rotates record ownership between teams that hold nobody eligible. HubSpot only assigns to users with a Sales or Service seat, so these rotations fail with “Owner rotation failed: no eligible users” and the record keeps the owner it already had. Give a pool member a Sales/Service seat, or point the rotation at a team that has one.
WorkflowRotates betweenWhy nobody is eligible
Inbound lead rotation (round-robin)Marketing Opsno member of Marketing Ops holds a Sales/Service seat
Notifications addressed to a record owner reach nobody when the record has no owner, or an owner who has been deactivated. These workflows notify the owner; the counts are the records that silently notify no one. Assign an owner, or reassign the records off the deactivated user.
ObjectOwner fieldRecords at risk No ownerDeactivated ownerWorkflows
dealshubspot_owner_id 235 14095 Deal stage change: notify owner

Automation health: workflows reading fields that are always empty

6 workflow conditions test a field that no record carries. Each one resolves the same way on every enrolment, and the column below says which way: a condition that can never match leaves its path unreachable, while one that always matches is a gate standing open. HubSpot reports the empty field under Data Model health; what it does not say is that something is reading it.

FieldObjectRecords with a value On an empty fieldRead by
nps_segmentcontacts property no longer existsnever matchesLifecycle: MQL on form submit
form_fill_countcontacts 0 of 48,200never matchesLifecycle: MQL on form submit
onboarding_stagecontacts 0 of 48,200always matchesNew deal from qualified lead
trial_blockedcontacts 0 of 48,200never matchesOutbound cadence: enroll new SQLs
churn_risk_scoredeals 0 of 3,120never matchesRenewal risk: notify renewals team
escalation_reasondeals 0 of 3,120not statedLifecycle: customer on closed-won deal

1 of these is a checkbox (trial_blocked), which will look populated when you go and check. An unset checkbox displays as “No” throughout HubSpot and in every export, but it holds no value at all, and that is what the condition sees: an empty checkbox matches neither “is false” nor “is true”.

1 condition matches every record rather than none, so the path is not unreachable: every enrolment takes it. That can be the intent, a filter written to exclude nobody yet, so confirm what it is for before changing it.

1 of these names a property that is not on the object at all, so the condition can never match anything.

1 is also written by another workflow, which has either never run or never enrolled a record. That explains the empty column; the branch reading it is stuck either way.

Writers are a floor too: a field no enabled workflow writes can still be filled by an integration, an import, a form or a person. Anything owned by a connected phone system, chat tool or data provider arrives that way. The blast-radius section inventories which non-human actors already write to this portal.

Read from workflow enrolment criteria and branch conditions only. Emails, lists, calculated properties and reports also read fields and are not visible here, so treat this as a floor. A further 1 branch condition reads a field on an associated record (contact_country). Reading a field from a record the workflow does not enrol is ordinary HubSpot; the workflow names the association but not the object behind it, so these were not checked either way and are not findings.

2 of 13 workflows are switched off and untouched for over 180 days (3 are switched off in total). Pausing a workflow is normal; leaving it parked for a year is clutter every admin has to read past. Archive what is done with, and the list starts telling the truth about what runs.
WorkflowLast edited
Webinar follow-up 2024 (paused)2024-05-21
Copy of trade-show import cleanup2024-09-03
1 enabled workflow(s) enroll contacts into sequences sent from the contact owner. Any contact owner is then an effective sequence sender and needs a paid Sales/Service Enterprise seat -- verify a user does not own contacts flowing through these workflows before actioning a Sales-to-Core downgrade. Users named as a fixed sender are already kept on Sales Hub automatically.

Access drift

Governance hygiene over the portal's users. Severity: Good Watch Act

SignalCount%Severity
Super Admins214.3% Good
Super Admins inactive in window0 Good
Deactivated users still Super Admin1 Watch

Super Admins

EmailSeatActivity totalStatus
dane.koch@cadence.example sales-enterprise 1,275 active
lena.roos@cadence.example sales-enterprise 0 deactivated
rosa.lindt@cadence.example sales-enterprise 1,275 active

Data quality

Per-object hygiene signals (read-only counts). Severity: Good Watch Act

contacts — 48,200 records

SignalCount%Severity
No owner9,10018.9% Watch
Owned by deactivated users1,2402.6% Act
Stale (>180d)23,80049.4% Act
Missing email7,40015.4% Act
Missing lifecyclestage7,40015.4% Act
Custom properties82 Watch

66 of 82 custom properties on contacts carry no description. Nothing is wrong with the data; the portal's own vocabulary is simply unexplained, which is what makes a field nobody recognises survive for years. This counts the property description the editor shows; the data-entry instructions box beside it is not exposed by the API, and nothing here can be written back.

companies — 6,400 records

SignalCount%Severity
No owner82012.8% Watch
Owned by deactivated users1602.5% Act
Stale (>180d)2,90045.3% Act
Missing name1,10017.2% Act
Missing domain1,10017.2% Act
Custom properties44 Good

35 of 44 custom properties on companies carry no description. Nothing is wrong with the data; the portal's own vocabulary is simply unexplained, which is what makes a field nobody recognises survive for years. This counts the property description the editor shows; the data-entry instructions box beside it is not exposed by the API, and nothing here can be written back.

deals — 3,120 records

SignalCount%Severity
No owner1404.5% Good
Owned by deactivated users953.0% Act
Stale (>180d)54017.3% Watch
Missing amount2809.0% Watch
Missing closedate2809.0% Watch
Open, past close date (of 819 open with a close date)40249.1% Act
Open, 90+ days in the same stage (of 880 open)17319.7% Watch
Custom properties41 Good

At least 402 of the 819 open deals that carry a close date are past it. A further 61 carry no close date at all, so they cannot be counted either way and the figure is a floor rather than a total.

This counts how long a deal has sat in its current stage, and nothing else: a deal here may well have been worked recently. Activity dates are too sparsely filled across portals to qualify it without understating.

33 of 41 custom properties on deals carry no description. Nothing is wrong with the data; the portal's own vocabulary is simply unexplained, which is what makes a field nobody recognises survive for years. This counts the property description the editor shows; the data-entry instructions box beside it is not exposed by the API, and nothing here can be written back.

tickets — 1,980 records

SignalCount%Severity
No owner1,24062.6% Act
Owned by deactivated users221.1% Watch
Stale (>180d)41020.7% Watch
Missing subject1306.6% Watch
Missing hs_pipeline_stage1306.6% Watch
Custom properties18 Good

The no-owner count above is at least partly by design: 1 enabled workflow blanks the owner on tickets (Ticket queue: release owner overnight). Records cleared this way are counted here, because they genuinely have no owner and every owner-addressed notification and rotation on them still fails. Confirm the intent before reading this row as neglect.

14 of 18 custom properties on tickets carry no description. Nothing is wrong with the data; the portal's own vocabulary is simply unexplained, which is what makes a field nobody recognises survive for years. This counts the property description the editor shows; the data-entry instructions box beside it is not exposed by the API, and nothing here can be written back.

Duplicate detection is left to HubSpot's native Data Quality tools (Breeze); this section complements them with portable, scored signals that need no Data Hub.

Agent-readiness: workflow collision surface

7 properties are already written by enabled workflows. Before an AI agent is pointed at one of these fields, know that a workflow already sets it on a trigger — an agent and a workflow writing the same property is a collision to resolve first. Read-only: this names the overlap, it does not recommend changing any workflow.

PropertyWorkflows writing it Records enrolled (90d) Enabled workflows
form_fill_count1 4,180 Form fill: stamp date and count
form_fill_date1 4,180 Form fill: stamp date and count
phone1 4,180 Form fill: stamp date and count
hubspot_owner_id2 2,392 Inbound lead rotation (round-robin) · Ticket queue: release owner overnight
lifecyclestage2 1,336 Lifecycle: MQL on form submit · Lifecycle: customer on closed-won deal
dealstage1 118 New deal from qualified lead
pipeline1 118 New deal from qualified lead

Records enrolled counts records entering those workflows in the window, not property writes: one enrolment may write the field once, several times or not at all. Read it as how hard the automation around a field is running, which is what separates a field many workflows could write from one they actually do.

At least one workflow writes lifecyclestage on an associated record, not on the object the workflow enrols. The collision to resolve is on that associated object.

Agent-readiness: automated write access (blast radius)

3 automated actors already write to this portal without a human in the loop. An AI agent joins these, not an empty portal — know what already acts before adding another. Read-only: this inventories what writes, it does not judge or change any integration.

ActorObjectRecords written
Workflow automationcontacts2,380
Browser extension / connected appcontacts812
Workflow automationdeals190
Integrationcontacts145
Integrationdeals36
Total potential annual savings
EUR 5,400
EUR 5,400/year from re-allocating seats . Current monthly: EUR 1,725; recommended monthly: EUR 1,275.
Pricing used (source: HubSpot list (Enterprise))
SeatMonthlyAnnual
core EUR 75 EUR 900
developer EUR 0 EUR 0
partner EUR 0 EUR 0
revenue-hub EUR 140 EUR 1,680
sales-hub EUR 150 EUR 1,800
service-hub EUR 150 EUR 1,800
view-only EUR 0 EUR 0

Seat distribution (current vs recommended)

SeatCurrentRecommended
sales-hub 7 4
service-hub 2 2
core 5 5
view-only 0 3

Change summary

4 potential seat change(s) (4 downgrade, 0 upgrade); 10 unchanged.

1 seat could not be assessed and are counted as unchanged above, so no saving is claimed for them. Service Hub work cannot be measured on this portal: 'Ticket queue: release owner overnight' blanks ticket ownership on a schedule, and owned tickets are the only Service signal the API exposes.

Marketing-contact bloat

Marketable contacts that never engage still consume the marketing-contacts tier. Read-only counts; engagement = marketing-email opens or clicks (last 180d).

Marketing-contacts add-on cost (source: HubSpot list (Enterprise marketing contacts, estimate)): current EUR 800/month; after trimming the idle slice EUR 400/month.

Potential saving: EUR 4,800/year (EUR 400/month) if the idle slice is trimmed below the next tier boundary — a renewal-negotiation starting point, not a quote.

Hub-tier fit

Which Enterprise and Data Hub features this portal demonstrably uses, from data the scan already reads. Two limits frame it. Portal-wide Enterprise features come with any Enterprise hub, so dropping the last Enterprise hub loses them all, not only that hub's own. And the most common reasons to hold each product leave no trace in a public API. So this table says what was found, never that a tier is unneeded.

FeatureRequiresStatusEvidence
Custom objectsEnterprise, any hubnot foundno custom schema
Sequence enrolment in workflowsSales or Service Hub Enterprisefound1 fixed sender(s), 1 contact-owner workflow(s)
Custom codeData Hub Professionalnot foundno enabled workflow
Format dataData Hub Professionalfound1 workflow(s): Form fill: stamp date and count
Send a webhookData Hub Professionalnot foundno enabled workflow
Dataset enrolmentData Hub Professionalnot foundno enabled workflow
Scheduled enrolmentData Hub Professionalnot foundno enabled workflow

Not measurable here, so verify before changing tier. Marketing Hub Enterprise: multi-touch revenue attribution, customer journey analytics, adaptive testing, lookalike lists, email approvals, predictive lead scoring, partitioned assets, hierarchical teams (the teams endpoint lists members, not parents), custom behavioral events and business units (scopes not requested). Data Hub: data sync, datasets used anywhere but workflow enrolment, dedupe and the Data Quality Command Center, Snowflake data share.

Action items

Seats to downgrade (4 user(s))

Currently on a paid seat that exceeds measured activity. Downgrade frees the seat cost without affecting their work.

EmailCurrentRecommendedConfidenceRationale
emma.voss@cadence.example sales-enterprise core ↓ high 12 contacts created; 12 lead(s) owned; 12 quote(s) built
leon.fischer@cadence.example sales-enterprise view-only ↓ low no measured activity in window. Reading zero here is not evidence of idleness: this portal counts tickets by who owns them, and an enabled workflow blanks that owner on a schedule ('Ticket queue: release owner overnight'), so the count shows only what survived the last run
tom.adler@cadence.example sales-enterprise view-only ↓ low no measured activity in window. Reading zero here is not evidence of idleness: this portal counts tickets by who owns them, and an enabled workflow blanks that owner on a schedule ('Ticket queue: release owner overnight'), so the count shows only what survived the last run
bram.ott@cadence.example core view-only ↓ low no measured activity in window. Reading zero here is not evidence of idleness: this portal counts tickets by who owns them, and an enabled workflow blanks that owner on a schedule ('Ticket queue: release owner overnight'), so the count shows only what survived the last run

Orphan sequences to transfer or archive (3 sequence(s), 1 ex-owner(s))

Owned by deactivated or deleted users. They remain visible to active Sales Hub users but have no live owner. Transfer to a current user or archive.

Owner userIdSequencesSample names
213 3 Outbound: demo no-show follow-up; Trial day-3 nudge; Re-engagement: cold leads

Seat recommendations

Email Current Recommended Confidence Rationale
leon.fischer@cadence.example sales-enterprise view-only ↓ low no measured activity in window. Reading zero here is not evidence of idleness: this portal counts tickets by who owns them, and an enabled workflow blanks that owner on a schedule ('Ticket queue: release owner overnight'), so the count shows only what survived the last run
tom.adler@cadence.example sales-enterprise view-only ↓ low no measured activity in window. Reading zero here is not evidence of idleness: this portal counts tickets by who owns them, and an enabled workflow blanks that owner on a schedule ('Ticket queue: release owner overnight'), so the count shows only what survived the last run
emma.voss@cadence.example sales-enterprise core ↓ high 12 contacts created; 12 lead(s) owned; 12 quote(s) built
dane.koch@cadence.example sales-enterprise sales-hub high Super Admin -- review configuration activity manually
rosa.lindt@cadence.example sales-enterprise sales-hub high Super Admin -- review configuration activity manually
jules.maas@cadence.example sales-enterprise sales-hub high 140 HubSpot-dialed call(s) in window; 3 forecast submission(s) in window
paul.frei@cadence.example sales-enterprise sales-hub high owns 1 sequence(s); 140 HubSpot-dialed call(s) in window; 3 forecast submission(s) in window
rens.kuiper@cadence.example service-enterprise service-hub low Service Hub work cannot be measured on this portal: 'Ticket queue: release owner overnight' blanks ticket ownership on a schedule, and owned tickets are the only Service signal the API exposes
ada.wolff@cadence.example service-enterprise service-hub high 264 ticket(s) owned and touched in window -- measured Service Hub work
bram.ott@cadence.example core view-only ↓ low no measured activity in window. Reading zero here is not evidence of idleness: this portal counts tickets by who owns them, and an enabled workflow blanks that owner on a schedule ('Ticket queue: release owner overnight'), so the count shows only what survived the last run
finn.devries@cadence.example core core high 12 contacts created; 12 lead(s) owned; 12 quote(s) built
mia.dahl@cadence.example core core high 110 contacts created; 25 task(s) touched; 18 note(s) authored; 110 lead(s) owned; 110 quote(s) built
nora.berg@cadence.example core core high 110 contacts created; 25 task(s) touched; 18 note(s) authored; 110 lead(s) owned; 110 quote(s) built
sara.holm@cadence.example core core high 110 contacts created; 25 task(s) touched; 18 note(s) authored; 110 lead(s) owned; 110 quote(s) built

Appendix: per-user activity (90-day window for contacts & calls)

Email Seat Contacts Sequences Meeting links RR/team links Calls Custom objs Deals Tasks Notes Forecasts Leads Quotes Tickets Logged in Total
leon.fischer@cadence.example sales-enterprise 0 0 0 0 0 0 0 0 0 0 0 0 0 no 0
tom.adler@cadence.example sales-enterprise 0 0 0 0 0 0 0 0 0 0 0 0 0 no 0
emma.voss@cadence.example sales-enterprise 12 0 0 0 0 0 0 3 2 0 12 12 0 no 41
dane.koch@cadence.example sales-enterprise 320 0 0 0 140 0 22 90 60 3 320 320 0 no 1275
rosa.lindt@cadence.example sales-enterprise 320 0 0 0 140 0 22 90 60 3 320 320 0 no 1275
jules.maas@cadence.example sales-enterprise 320 0 0 0 140 0 22 90 60 3 320 320 0 no 1275
paul.frei@cadence.example sales-enterprise 320 1 0 0 140 0 22 90 60 3 320 320 0 no 1276
rens.kuiper@cadence.example service-enterprise 0 0 0 0 0 0 0 0 0 0 0 0 0 no 0
ada.wolff@cadence.example service-enterprise 0 0 0 0 0 0 0 4 2 0 0 0 264 no 270
bram.ott@cadence.example core 0 0 0 0 0 0 0 0 0 0 0 0 0 no 0
finn.devries@cadence.example core 12 0 0 0 0 0 0 3 2 0 12 12 0 no 41
mia.dahl@cadence.example core 110 0 0 0 0 0 4 25 18 0 110 110 0 no 377
nora.berg@cadence.example core 110 0 0 0 0 0 4 25 18 0 110 110 0 no 377
sara.holm@cadence.example core 110 0 0 0 0 0 4 25 18 0 110 110 0 no 377

Custom-object coverage

Marketing email language tagging

HubSpot matches a subscription type's translation on the **exact** language code an email declares, with no fallback from `nl-nl` to `nl`. One language declared under two codes therefore splits the audience across two translation sets, and a code with no translation defined renders its subscription name, preference centre and unsubscribe text in the portal default instead.

nl is declared under 2 codes — 6 emails, 31,700 sends

CodeEmailsSends
nl325,200
nl-nl36,500

1 emails declare no language at all (1,200 sends) — they fall back to the portal default whatever the copy is written in.

“Klantnieuwsbrief” is sent in nl-nl but translated into nl — 3 emails, 6,500 sends. Same language, different code, and HubSpot matches the code exactly: those sends fall back to the subscription's default text and the translation is never used.

Fix by standardising on one code per language, or by defining the subscription-type translation for every code in use.

1 of these email uses smart content (1,800 sends), varying SUBJECT. HubSpot names the smart fields but exposes neither their rules nor their variations, so HubScan cannot read what they swap in. Worth knowing: a smart rule can serve a different language, while the preference centre and unsubscribe text still follow the email's single declared language code — so those readers get one language in the body and another in the footer. Check those emails by hand.

Caveats