---
name: hubspot-implementation-plan
description: Plans a HubSpot implementation in dependency order and produces an implementation brief, a capability register, a property and ownership register, an import rehearsal and a launch checklist, with the failure modes seen in production and hand-offs to HubSpot's remote MCP server and Agent CLI. Use when asked to set up HubSpot, plan a HubSpot rollout or HubSpot CRM setup, write a HubSpot onboarding plan, setup checklist or go-live checklist, or say what to set up first in HubSpot; when starting, rescuing or re-platforming a portal; to migrate to HubSpot or import contacts, companies or deals; to define lifecycle stages, lead status or a HubSpot deal pipeline; to decide property versus custom object; to plan HubSpot workflows, forms or the HubSpot tracking code; or when connecting HubSpot to Salesforce, Stripe or a product database.
license: CC-BY-4.0
metadata:
  tier: free
  category: crm-revops
  version: "0.1.0"
  last_reviewed: "2026-10-17"
  status: reviewed
---

# HubSpot implementation plan

Produces one HubSpot release plan in dependency order, as proposed files: brief, capability register, property register, import rehearsal, launch checklist and dated decisions. The plan is done when real users complete the first workflows on verified records, not when the portal is configured.

## When to use

Use this skill when:

- A new HubSpot portal needs a first release, or a team asks what to set up first.
- An existing portal is being rescued: duplicates, wrong lifecycle stages, owners lost, integrations overwriting values.
- Data is about to be imported or migrated into HubSpot.
- Salesforce sync, Stripe, billing or product data is being added to a live portal.
- Someone must decide property versus standard object versus custom object for one entity.

Use something else for narrower questions. Each skill named applies only if installed; otherwise use the reference given.

- The CRM is not chosen yet: crm-selection-and-pricing.
- One custom object needs a full design: hubspot-custom-objects-design after step 4, otherwise [the data model reference](references/data-model-and-properties.md).
- A live portal needs a monthly cleanup: crm-data-hygiene-audit, otherwise [the merge rules](references/import-and-dedupe.md#merges).
- Two systems fight over a field: crm-sync-and-field-ownership, otherwise [the integrations reference](references/integrations.md).
- Stripe, billing or product data in depth: product-and-billing-data-in-crm, otherwise the same reference.
- Moving off Salesforce entirely: salesforce-to-hubspot-migration-kit, otherwise the integrations reference's Salesforce section.
- Routing or scoring is the whole question: lead-routing-and-speed-to-lead or lead-scoring-model, otherwise [the workflows reference](references/workflows-and-reporting.md).
- Website events and UTMs: tracking-plan-builder and utm-convention-and-registry.
- Creating, updating or merging records: hand off to HubSpot's own tooling (see Boundaries).

## Inputs

Read these first if they exist:

- `martech-context/stack.md`: hubs and editions, other systems and connectors, owners, environments.
- `martech-context/data-dictionary.md`: existing field definitions and owners.
- `martech-context/metrics.md`: lifecycle and pipeline metric definitions.
- `martech-context/decisions.md`: identity, account boundary and consent decisions.
- `martech-context/naming-rules.md`: property internal-name conventions.

Then gather what is missing:

- The first two or three workflows, each as "a named person needs to...", with trigger, population, owner, required data, expected response and failure path.
- The order form: hubs, editions, seat types and counts, marketing contact tier, and the pricing programme (Hub-based seats or flexible seats-and-credits). Entitlements differ by programme.
- Source systems and their stable IDs: product account, person, workspace, billing customer, subscription, Salesforce record IDs.
- Record counts per source, duplicate estimates, opt-out and hard-bounce counts, and which records the team intends to market to.
- Named owners: business owner, HubSpot admin, integration owner, privacy owner.

Never ask for, print or store API keys, service keys, OAuth tokens or customer records. Use counts, schemas and fictional or redacted samples.

## Procedure

Each step has a gate. Do not start a step whose inputs failed the previous gate. Detail per layer: [build order](references/build-order.md).

### 1. Define the first release as work people do

- Write the first release as two or three workflows, for example "a demo request reaches an eligible owner who records acceptance or a rejection reason". Copy [implementation-brief](assets/implementation-brief.yaml).
- For each workflow, write what must not happen (an existing customer entering a new-prospect sequence because they submitted another form).
- Exclude everything that does not serve those workflows. Scoring, extra objects and AI steps wait until assignment is reliable.

### 2. Build the capability register before designing

- One line per dependency: outcome, feature, required hub, edition and seat, confirmed (yes or no), fallback.
- Always check: custom objects, owner rotation, the leads object, association labels, calculated properties, property view and edit restrictions, multi-currency, standard sandbox, data sync custom mappings, Stripe subscription sync and the native subscriptions object, deal create and deal revenue attribution reports, and any feature that consumes HubSpot Credits.
- Confirm in the portal Limits tab and the order form, not a public pricing page: [entitlements](references/data-model-and-properties.md#entitlements-to-confirm).
- Gate: every feature the first release needs is confirmed or has a written fallback.

### 3. Account settings and users

- Set account time zone and company currency before importing deals or building reports. Changing company currency later does not convert existing deal amounts automatically.
- Create users, teams, seats and permission sets before importing owners, then test one allowed and one denied record per role. Owner rotation only assigns users with paid Sales or Service seats.
- Turn off "Create and associate companies with contacts" before any import, form or integration when companies are keyed on a source account ID or Salesforce is connected. On a shared domain it attaches contacts to one company you cannot choose. Record the decision in `decisions.md`.
- With the privacy owner, define subscription types and consent fields before any form or marketing import, and authenticate the email sending domain before the first marketing send.
- List external domains that will carry the tracking code. New system-to-system integrations use service keys; legacy private app creation is disabled for existing accounts from 26 October 2026.
- Gate: owner list, seat map, permission tests and account defaults recorded in the brief. Seat rules: [layer 1](references/build-order.md#1-account-settings-and-users).

### 4. Design records, identity and properties

- Map entities to objects: contact for a person, company for the commercial account, deal for a real commercial opportunity. Never create a deal per product event.
- Property versus object, decide with these rules:
  - Property: one maintained fact about an existing record.
  - Numbered repeats (`workspace_1_status`, `workspace_2_status`) mean the entity is wrong. Model it, or keep detail in the warehouse and sync a summary.
  - Custom object only when a named person acts on each instance separately, no standard or activatable object fits, a stable source key and associations can be maintained, the entitlement is confirmed and the downgrade effect is recorded.
  - Event-grain history stays in analytics or the warehouse.
- Give every synced entity a unique-value property holding the source ID (up to ten per object). Companies created through the API are not deduplicated by domain, so any integration that creates companies needs this key.
- Fill [property-register](assets/property-register.csv) for every property the release reads or writes: internal name, type, allowed values, source of truth, single writer, blank meaning, freshness field. Internal names cannot be edited after creation.
- Gate: the register has one writer per property and no near-duplicates (`plan`, `current_plan`, `stripe_plan`).

### 5. Define lifecycle stage, lead status and deal stage separately

- Lifecycle stage is the relationship; lead status (or the leads object) is sales follow-up state; deal stage is one opportunity's progress. One state lives in one field.
- Write the evidence for each transition. A booked meeting is not qualification.
- Imports, forms, the API, workflows and the Salesforce integration only move lifecycle forward. A backward correction needs the value cleared first, so design that path now.
- Decide each lifecycle automation setting (stage on create, deal created, deal won, lead associated, sync to primary company) and record it in `decisions.md`.
- Detail: [lifecycle-and-pipelines](references/lifecycle-and-pipelines.md).

### 6. Build pipelines with stage evidence

- Each stage gets entry evidence and required properties. Required stage properties are documented only for manual creates and moves in the UI, not for imports, integrations, workflows or the API. Test each writer and keep a per-stage view of deals missing them.
- Record stage internal IDs; integrations and imports use them, not labels.
- Keep Won and Lost stages. Do not add stages to show product usage.
- Detail: [lifecycle-and-pipelines](references/lifecycle-and-pipelines.md#pipelines-and-stage-evidence).
- Gate: a stage list with evidence, required properties, probability and internal IDs.

### 7. Rehearse the import

- Separate files for new records and updates. Export the current values of everything the import touches. Restore CRM changes (Super Admin, Starter or above) can roll back a named import, integration or workflow for 14 days; the export is the evidence after that and for API-only writers.
- Keys: Record ID for updates, email for contacts, the unique source-ID property for companies and custom objects. Record ID overrides every other identifier. Rows with no identifier create new records.
- Load opt-outs and hard bounces from the old system before, or in the same load as, any marketing-status change. Never clear an opt-out because a new source has the address.
- Contacts from a single-object import are non-marketing unless you choose otherwise; multiple-object imports are always non-marketing. Set marketing status only for contacts with a named campaign use, after checking the tier, the update date and any maximum cap.
- Run [import-rehearsal-cases](assets/import-rehearsal-cases.csv) in a standard sandbox (Enterprise) or a small tagged batch, with workflows that could enrol imported records turned off.
- Merges cannot be undone. Never bulk merge as the first response to a matching problem.
- Detail: [import-and-dedupe](references/import-and-dedupe.md).
- Gate: created + updated + rejected equals the file's rows, each reject with a reason; re-importing the same file creates zero records; IDs, associations, owners, lifecycle, opt-outs and marketing status match the expected results.

### 8. Forms and tracking code

- One tracking code per page; install it on every external domain and add those domains in settings.
- Hidden fields capture only what is on the form page's URL. Preserve UTMs across the journey or accept that they are lost.
- Decide each form's marketing-contact switch. It is on by default and also converts existing non-marketing contacts who submit; the non-HubSpot forms setting does the same. Compare marketing contact counts before and after each form goes live.
- Detail: [forms-and-tracking](references/forms-and-tracking.md).

### 9. Connect integrations one direction at a time

- For each integration: match key, create versus update, direction, writer per field, blank and clear semantics, freshness fields, failure queue, deletion policy.
- Salesforce: one org per portal, Smart Transfer off first, Salesforce value as first-sync baseline, inclusion segment not a security boundary. Records already in Salesforce enter through the integration's import or resync; CSV is only for records with no Salesforce counterpart.
- Stripe: payment processing, data sync and subscription migration are different jobs. Write which system owns billing before connecting. Saving a data sync restarts its initial sync, so pause workflows on mapped fields first.
- Product data: sync a small set of account summaries with a freshness field such as `product_refreshed_at`, through a unique-property upsert.
- Detail: [integrations](references/integrations.md).
- Gate: one controlled change traced from source to the HubSpot record to the view or workflow that uses it, and a replayed delivery creates nothing new.

### 10. Enable workflows only after their inputs pass

- Write routing and follow-up policy in plain language first, with precedence, fallback owner and reason fields.
- When turning a workflow on, choose "only future records" unless a backfill is intended and tested. A scheduled workflow can still enrol existing matching records on its next run; add an exclusion if they must not. Re-enrolment is off unless designed.
- Exclude a running import batch by its batch tag, never by Record Source. Record Source never changes, so that exclusion drops every later request from an imported contact.
- Every essential handoff has a fallback that does not consume HubSpot Credits.
- Detail: [workflows-and-reporting](references/workflows-and-reporting.md).

### 11. Build reports that reconcile

- State the counting unit and timestamp for each metric. Use the lifecycle "Date entered" properties for stage entry.
- Deal value is summed once per deal ID, never after a join to contacts.
- Keep an explicit unknown group for source and owner. Exclude test and internal submissions by one documented rule in HubSpot and in analytics, and write the restatement rule for a reopened closed-won deal.

### 12. Propose the files and hand off

Show the user the brief, both registers, the rehearsal results and [launch-checklist](assets/launch-checklist.md), plus proposed additions to `data-dictionary.md` and `decisions.md`. Write nothing until approved. Changes in HubSpot go to the tools in Boundaries as reviewed drafts.

## Common failure modes

- Integration creates a second company per sync. Detect: companies sharing a domain, created by an integration.
- Automatic company association puts contacts on the wrong shared-domain company. Detect: companies with no source ID; contacts on the wrong account.
- Import or form turns contacts into marketing contacts. Detect: marketing contact count against tier before and after each import and form launch.
- Migration drops earlier opt-outs. Detect: opted-out count in the source differs from HubSpot.
- Salesforce first sync overwrites newer HubSpot values. Detect: property history shows the integration writing an older value on first pairing.
- Imported history enrols in live workflows. Detect: enrolments of records in the batch (tag, or a segment of the file's Record IDs) within minutes of it.
- Integration overwrite found after the restore window. Per-record history restore excludes integrations; Restore CRM changes covers them for 14 days only.

Full catalogue with causes and repairs: [failure-modes](references/failure-modes.md).

## Worked example

Acme Analytics, a fictional B2B SaaS on Sales Hub Professional and Marketing Hub Starter, plans "demo request to accepted follow-up" and "billing state visible on the company". The filled brief is [example-acme-brief](assets/example-acme-brief.yaml). Points to copy:

- Workspaces stay in the warehouse as company summaries such as `active_workspace_count`; no one acts on single workspaces and custom objects are not entitled.
- Companies match on `acme_account_id` because the warehouse sync creates companies through the API. Automatic company association is off, since two accounts share example.org.
- Companies import first. 4,200 historical contacts follow in a multi-file import keyed on `acme_account_id`, so they arrive non-marketing and on the right account. 1,100 with a recorded opt-in are then set to marketing.
- The newsletter form's switch is on, so imported contacts who submit become marketing; 200 contacts of headroom remain under the 1,950 cap.

## Acceptance checks

- Scope: two or three workflows, each with owner, trigger, failure path and a must-not-happen case. Pass: no template text remains.
- Capabilities: every dependency shows confirmed or fallback, with the date and where it was checked. Pass: zero unconfirmed entries in the first release.
- Settings: time zone, currency, seat map, permission tests, company auto-association and owners recorded. Pass: dates precede the first import.
- Properties: each property has one writer, a type, allowed values, blank meaning and a source. Pass: no property has two writers without a written conflict rule.
- Stages: lifecycle, lead status and deal stages each have transition evidence and a correction path. Pass: a reviewer can say which field answers "is this a customer" and "is this being worked".
- Import: the rehearsal file has expected and actual results per row. Pass: all rows match, counts add up to the file, a replay creates nothing, opt-out counts match the source, marketing contacts stay within the tier.
- Integrations: one traced change and one replayed delivery per integration. Pass: correct record, no new record on replay.
- Workflows: tested with controlled records, outbound limited to test recipients. Pass: no unexpected enrolment; an imported contact's new request routes normally.
- Reports: totals reconcile to a list of underlying record IDs. Pass: equal counts and sums.
- Approval: nothing in HubSpot or `martech-context/` changed without a recorded approval.

## Boundaries

- This skill plans. It does not create properties, pipelines, workflows or records, run imports, merge, or change settings. Each change is a draft (CSV, register row, change list) that a human approves.
- Merges, deletes, marketing status changes, opt-out changes and Salesforce field rules are irreversible or billable: they always need explicit approval from the HubSpot admin.
- Consent and lawful basis belong to the privacy owner; billing ownership to finance.
- Hand-offs, read-only first. Step-to-tool map and safe settings: [agent-handoffs](references/agent-handoffs.md).
  - HubSpot remote MCP server (`https://mcp.hubspot.com`, acting as the signed-in user): `get_user_details` first, then read tools only. Only `manage_crm_objects` and `manage_segment` document a confirmation step; `manage_custom_properties`, `manage_custom_pipelines` and other write tools do not, so never call them from this skill. In assistant connectors, set write tools to "Needs Approval".
  - HubSpot Agent CLI (beta) and `hubspot/agent-cli-skills`: approved record operations only, starting with `bulk-operations`, `--dry-run` on every write, personal OAuth login. Schema commands need Admin mode (a service key), so custom object schema changes go to a human admin in the UI. `hubspot history` logs only destructive operations, locally; save the output of create and update runs.
  - Salesforce settings and permissions belong to the Salesforce admin.

## Live docs

Platform settings, limits and menu paths change. Before stating any parameter name, limit, quota or UI path:

- Fetch the current page from the vendor docs MCP server or llms.txt listed in `sources.yaml`, or open the canonical URL.
- If the live page disagrees with this skill, follow the live page and tell the user what changed.
- Cite the URL you used.

The entries that matter most: lifecycle stages, deduplication, company auto-association, Restore CRM changes, default marketing statuses, CRM limits, the Salesforce import and inclusion pages, data sync, the remote MCP server reference and the Agent CLI guide. Every platform fact in this skill was checked on 2026-10-17.
