---
name: hubspot-audit
description: Run a comprehensive scan of a HubSpot portal across hygiene axes (database, enrichment, segmentation, automation, metadata) and score each issue by impact and severity. For generic requests like "audit my HubSpot", ask a scoping questionnaire first instead of launching a full sweep. Produces a single audit report for quarterly cleanup planning. Audit-only metadata skill — does not write to HubSpot. Use this skill whenever the user mentions full HubSpot audit, CRM health scan, "audit the whole portal", first-time-running-the-pack discovery, board-prep CRM hygiene audit, or end-to-end portal assessment.
metadata:
version: 0.1.0
pack: hubspot-revops
skill_type: metadata
---
# HubSpot Audit
A comprehensive one-shot scan of a HubSpot portal. Aggregates findings from every hygiene axis into a single ranked report.
This is the **starting point** for using the pack. Run it first to understand the state of the portal; the report tells you which remediation skills will deliver the most value.
## What this skill does
1. Run every audit-axis query in the pack (without building Baseloop workflows — pure read).
2. Score every issue by impact (records affected, revenue/billing exposure) and severity.
3. Produce a single `audit.csv` (every flagged item across all axes) and `summary.md` (exec-ready overview).
This skill is read-only and never builds Baseloop workflows. The remediation skills do that, run individually after this audit.
## Before you start
- `references/_shared-architecture-overview.md`
- `references/_shared-hubspot-data-model.md`
- `references/_shared-revops-rules.md`
- `references/_shared-output-conventions.md`
## Step 0 — Pre-flight
Standard pack pre-flight (HubSpot MCP only). Before running any HubSpot queries, decide whether the user has already provided enough audit scope.
### Generic audit request gate
If the user asks a generic request like "audit my HubSpot", "run a HubSpot audit", "check our portal", "audit the CRM", or otherwise does not specify scope/audience/focus, **do not start the full audit yet**. Ask one scoping questionnaire first and wait for the answer.
Use this exact shape in chat (or equivalent choice controls if the environment supports them):
```markdown
Before I run it, a few audit details so I don't over-scan the portal.
1. How wide should the audit go?
- Full sweep (recommended): all 21 axes, ~5-10 min
- Data hygiene only: duplicates, bouncers, ghosts, enrichment
- Metadata only: lists, workflows, forms, dashboards
2. Any axes you want me to skip? Pick any, or say "skip nothing".
- Dedupe (contacts/companies)
- Deliverability (bouncers/unsubs)
- Enrichment (names, titles, sizes)
- Lifecycle stages
- Orphan records
- Lists/workflows/forms/dashboards
- Skip nothing
3. Who's the audience for the summary?
- Just me / RevOps
- Leadership / exec readout
- Board-prep / QBR slide source
4. Anything specific bothering you about the portal right now?
- Example: "marketable count keeps creeping", "reports broke after migration", or leave blank.
```
Do not continue until the user answers or explicitly says to skip the questionnaire. If they skip it, use defaults: full sweep, skip nothing, RevOps audience, no special focus.
### When the user already gives scope
If the initial request already includes the important details, summarize the inferred settings and ask for a quick confirmation instead of re-asking the full questionnaire. Example:
> I'll run a metadata-only HubSpot audit focused on workflows and dashboards, with a leadership-ready summary. Pure read; no writes. Sound good?
### Scope mapping
Use the questionnaire answers to decide which axes to run:
| User scope / skip answer | Axes included or removed |
|--------------------------|--------------------------|
| Full sweep | Start with all axes in Step 1 |
| Data hygiene only | Data axes only: dedupe, suppression, orphan records, enrichment, geo, lifecycle |
| Metadata only | Metadata axes only: lists, forms, workflows, dashboards, properties, deal pipelines, inactive users, integrations |
| Skip dedupe | Remove `dedupe_companies`, `dedupe_contacts` |
| Skip deliverability | Remove `bouncers`, `unsubscribers` |
| Skip enrichment | Remove `missing_names`, `missing_industries`, `missing_titles`, `missing_size`, `geo_variants` |
| Skip lifecycle stages | Remove `lifecycle_repair` |
| Skip orphan records | Remove `orphan_records` |
| Skip lists/workflows/forms/dashboards | Remove `lists`, `workflows`, `forms`, `dashboards` |
Record the final scope, skipped axes, audience, and user concern at the top of `summary.md`.
## Step 1 — Run audit queries (in parallel where possible)
For each in-scope axis, run a read-only HubSpot discovery query or count check derived from the corresponding skill. Do not build Baseloop workspaces, do not run Baseloop source imports, and do not run remediation-skill build steps during the audit. If a referenced remediation skill's Step 1 now creates a Baseloop source table, use only its filter criteria and scoring logic for this audit.
| Axis | Read-only discovery source | What it counts |
|-------------------|-------------------------------------------------------|--------------------------------------------------|
| dedupe_companies | `hubspot-dedupe-companies` Step 2 | Duplicate pair count, severity distribution |
| dedupe_contacts | `hubspot-dedupe-contacts` Step 2 | Duplicate pair count |
| no_email | `hubspot-suppress-no-email-contacts` Step 1+2 | Affected contacts |
| bouncers | `hubspot-suppress-hard-bouncers` Step 1+2 | Affected contacts |
| orphan_records | `hubspot-reassign-orphan-records` Step 1+2 | Affected records (across types) |
| ghost_contacts | `hubspot-suppress-ghost-contacts` Step 1+2 | Affected contacts |
| unsubscribers | `hubspot-suppress-unsubscribers` Step 1 | Compliance-gap contacts |
| missing_names | `hubspot-populate-company-names` Step 1+2 | Affected companies |
| missing_industries| `hubspot-populate-industries` Step 1+2 | Affected companies |
| missing_titles | `hubspot-populate-job-titles` Step 1+2 | Affected contacts |
| missing_size | `hubspot-populate-company-size` Step 1+2 | Affected companies |
| geo_variants | `hubspot-normalize-geo-values` Step 1+2 | Variant counts |
| lifecycle_repair | `hubspot-repair-lifecycle-stages` Step 2 | Mismatch count |
| lists | `hubspot-cleanup-lists` Step 3 | Per-classification counts |
| forms | `hubspot-cleanup-forms` Step 2 | Per-classification counts |
| workflows | `hubspot-cleanup-workflows` Step 2 | Per-classification counts |
| dashboards | `hubspot-cleanup-dashboards` Step 2 | Per-classification counts |
| properties | `hubspot-cleanup-properties` Step 3 | Per-classification counts |
| deal_pipelines | `hubspot-cleanup-deal-pipelines` Step 2 | Per-classification counts |
| inactive_users | `hubspot-cleanup-inactive-users` Step 2 | Per-classification counts + projected savings |
| integrations | `hubspot-cleanup-integrations` Step 2 | Per-classification counts |
Aggregate everything. Use lightweight count queries where possible to keep runtime reasonable.
## Step 2 — Score and rank
For each finding, assign impact tier:
- **HIGH** — compliance/safety or material business impact: unsubscribers still marketable, conflicting workflows producing bad data, duplicate companies / contacts at scale, hard bouncers, customer-stuck-as-lead.
- **MEDIUM** — hygiene at scale: ghost contacts, missing firmographics, stale lists.
- **LOW** — housekeeping: stale dashboards, unused properties, dormant integrations.
Rank within tier by record count or revenue/billing exposure.
## Step 3 — Write outputs
```
./outputs/hubspot-audit/{YYYY-MM-DD-HHMM}/
audit.csv # one row per finding across all axes
summary.md # exec-ready report
```
`audit.csv` columns per shared convention plus:
`axis, finding_type, count, suggested_skill, impact_estimate`.
`summary.md` structure:
```markdown
# HubSpot Audit — {date}
## Scope
- Audit scope: {full_sweep | data_hygiene_only | metadata_only}
- Skipped axes: {none | comma-separated list}
- Audience: {RevOps | leadership | board/QBR}
- User concern: {provided concern | none}
## Portal grade
{A | B | C | D | F} based on weighted issue density.
## What we found
- HIGH: {N issues} — compliance, data-corruption, or material business impact.
- MEDIUM: {N issues} — at-scale hygiene.
- LOW: {N issues} — housekeeping.
## Top 10 fix-now items
| Rank | Issue | Count | Suggested skill |
|------|--------------------------------------------------|----------|------------------------------------------|
| 1 | Unsubscribers still marketable | 1,247 | hubspot-suppress-unsubscribers |
| 2 | Duplicate companies | 247 pairs| hubspot-dedupe-companies |
| ... | ... | ... | ... |
## Per-axis breakdown
(One section per axis, with count + severity + remediation pointer)
## What to do next
Suggested order of remediation:
1. Run `hubspot-suppress-unsubscribers` (compliance HIGH priority, fast).
2. Run `hubspot-reassign-orphan-records` (sales unblock).
3. Run `hubspot-cleanup-roadmap` to turn this audit into a quarterly plan with ROI estimates.
```
## Step 4 — Hand off
Tell the user:
```
Audit complete. Open outputs/hubspot-audit/{date}/summary.md.
Suggested next step: run `hubspot-cleanup-roadmap` to turn this into a prioritized plan with ROI estimates. Or jump straight to remediation — the summary points you to the right per-skill action.
```
## Edge cases
- **Large portals**: count queries on 100k+ records can take minutes. Show progress per axis as each completes.
- **MCP variant capabilities**: some checks may not be available depending on which HubSpot MCP variant is installed. Surface what was skipped at the end of `summary.md`.
- **First-time run**: a portal that's never been audited will have eye-watering counts. Frame the grade against typical portals to give context (most 3-year-old portals start at C; A is achievable after running the pack quarterly).
## Why this matters
This is the skill that pays the cost of installing the pack. One run produces a single document the user can take to leadership and say "here's what's wrong and here's the plan to fix it." Without this orchestrating audit, the pack is 33 separate skills the user has to discover one at a time.