# Import rehearsal, dedupe keys and marketing status

Facts checked against HubSpot's live docs on 2026-10-17.

## Before the first row

- Export the current values of every record and property the import can touch.
- Know the recovery window. Restore CRM changes rolls records back to a point in the last 14 days. It filters by source: manual CRM changes, Import (pick the import by name), Integration (pick the installed app) or Workflow, and can send records a workflow created to the recycle bin. It needs Super Admin and a Starter or higher hub subscription (Smart CRM: Professional or Enterprise). One restore handles one change type (created records or modified properties). Before-exports remain the evidence after 14 days and for writers the tool cannot name, such as a custom API script.
- Per-record restore from property history is narrower: it appears only when the source is a CRM UI edit, an import or a workflow.
- Turn off every workflow whose trigger an imported record could meet, or exclude the running batch by its batch tag. A historical import meets the same trigger as a fresh request. Never exclude on Record Source (see Source and acquisition evidence).
- Confirm owners exist as users, the stage internal IDs are known, and the unique-value properties exist.
- Decide the account boundary. Several subsidiaries can share a domain; domain matching is not an account decision.
- Check the company setting "Create and associate companies with contacts" (Settings > Data Management > Objects > Companies > Automation). It matches a contact's email domain to Company domain name, creates a company per unknown domain, and on a shared domain attaches the contact to one company you cannot choose. HubSpot advises against it with the Salesforce integration because it creates duplicate companies. It does not override associations from a multiple-object import; for other creation paths, assume it applies and test. Turn it off, or exclude shared domains (up to 1,000), when companies are keyed on a source account ID.

## Matching rules HubSpot applies

Contacts:

- Email is the matching key. An import row whose email matches updates that contact; only mapped properties change.
- A row with no unique identifier is created as a new contact.
- A row that matches several records errors and is not imported.
- Using secondary email as the identifier with a Record ID column replaces the existing primary email. Avoid unless that is the intent.
- Form submissions with an existing email update that contact.

Companies:

- Manual creation and automatic deduplication use the primary Company domain name. Imports use the primary and secondary values unless a custom unique-value property is the identifier, in which case the file can hold duplicate domains.
- The Company domain name property only accepts values up to the top-level domain (no paths).
- Companies created through the API are not deduplicated by domain. That includes third-party sync apps. This is the most common source of duplicate companies in production.

All objects:

- Record ID, when included as an identifier, supersedes every other identifier in the file. Rows without a Record ID create new records.
- Custom unique-value properties (up to ten per object) can be the identifier for contacts, companies, deals, tickets and custom objects.
- Unique-value properties are not supported in forms, and visitor values that violate them are cleared on conversion.

Choose per file:

- Updates to existing records: Record ID.
- New and existing contacts from a source system: email plus the internal person ID as a unique-value property for later syncs.
- Companies from any system that also syncs through the API: the source account ID as the unique-value identifier, not domain.
- Deals: Record ID for updates; a source opportunity ID property for new deals from another CRM.
- Records that exist in a connected Salesforce org: through the integration, not CSV (see [integrations.md](integrations.md#salesforce)).

## Associations in imports

- Load companies before the contacts that point at them. Then import contacts in a multi-file import whose common column is the company's source ID, so association does not depend on email domain.
- The mode is chosen per object. Under "Update existing" only, an unknown company key is ignored. Under "Create and update", the live page says unmatched rows create new records, so an unknown key can become a stub company. Reject unknown keys in the pre-import check.
- In a single-file multi-object import with no identifier, identical data across rows is treated as one record and associated with several related records. Check that this grouping is what you want.
- In a multi-file import, choose the common column and the object it is the key for.
- Association labels in imports need Professional or Enterprise.
- Reconcile associations, not just counts. An import can produce the right number of companies attached to the wrong contacts.

## Marketing contact status

Billing rules on 2026-10-17:

- Exceeding the marketing contact tier by one contact upgrades the account to the next tier, billed at that tier until renewal.
- Setting contacts to non-marketing takes effect on the next update date (the renewal day for monthly plans, the first of each month for annual plans), not immediately.
- HubSpot does not downgrade tiers mid-term. Deleting marketing contacts frees capacity but does not lower the tier.
- A maximum marketing contacts cap can be set by Super Admins or users with Modify billing permission. Contacts from imports and automated features that would exceed it are created as non-marketing. The cap is separate from the tier.
- On flexible seats-and-credits pricing, marketing contacts count inside the shared record-capacity pool.

Default status by creation path:

- Single-object import: non-marketing unless "Set this contact as a marketing contact" is chosen (needs Marketing Hub Starter or above).
- Multiple-object import: always non-marketing.
- HubSpot forms: "Set new contacts as marketing contacts" is on by default, per form. With it on, an existing non-marketing contact who submits is also set to marketing, however it was created.
- Non-HubSpot forms: an account-wide setting, on by default, with the same effect on existing non-marketing contacts.
- Integrations and the API: non-marketing by default, configurable per integration.
- Chatflows, mobile app, one-to-one email logging, connected team email, meetings links, sales extensions, document opens: non-marketing.
- A merge keeps the most marketable status of the two records.

The form rule is how a deliberately non-marketing import becomes billable later. Count marketing contacts before and after each form goes live, and turn a form's switch off when its submitters do not need marketing email.

Worked check with fictional numbers: tier 2,000, current marketing contacts 1,850, import sets 300 as marketing, result 2,150 and an automatic upgrade. Scheduling 300 others to non-marketing does not help until the update date. Either import fewer as marketing, wait for the update date, or accept the higher tier in writing.

Marketing status is billing classification, not permission. Consent and subscription preferences are separate properties owned by the privacy owner.

## Opt-outs, bounces and subscription types

- Before any form launch or marketing import, the privacy owner defines the subscription types and the consent fields.
- Export opt-outs, unsubscribes and hard bounces from the old system. Load them before, or in the same load as, any marketing-status change, and confirm them in HubSpot before anyone is set to marketing.
- Verify the current import option for opt-outs and subscription status on the live import pages at run time. Do not state a method from memory.
- Keep the old system's evidence in clearly named fields (`legacy_email_status`, `legacy_unsubscribed_at`) when HubSpot has no matching status to set.
- Never clear an opt-out or a delivery restriction because a new source or enrichment tool has the address.
- An empty "Email hard bounce reason" does not prove an address can be emailed. HubSpot documents that a globally bounced address has no value there when your own sends have not hard-bounced.
- Gate: opted-out count in the source equals the count in HubSpot, and none of them is a marketing contact unless the privacy owner approved it in writing.

## Source and acquisition evidence

- Record Source and its detail properties say which tool created a record (Import with the import name, Forms with the form name, Workflow with its name). HubSpot sets them and they cannot be edited, except that an integration can set details 2 and 3.
- Record Source was introduced in February 2024 and backfilled about four years; the Detail properties date from March 2024. Older records may have no value.
- Record Source describes creation. A contact that an import only updated keeps its original value, so "Record Source is Import" misses updated records. To find or exclude everything a batch touched, use an import tag property or a static segment built from the file's Record IDs.
- Original and Latest Traffic Source describe web interactions, not record creation. Their drill-downs are set by HubSpot and are cleared if the source is changed manually.
- "Imported" says how a record entered the CRM, not how the person found the company. If the old system holds reliable acquisition evidence, import it into a clearly named field (`legacy_acquisition_channel`, `legacy_acquisition_observed_at`). Leave unknown as unknown; never stamp an inferred channel on thousands of rows to fill a dashboard.

## Rehearsal

Use [../assets/import-rehearsal-cases.csv](../assets/import-rehearsal-cases.csv). Minimum cases:

- New contact, existing contact, changed email, contact without email.
- Company with several contacts; two companies sharing a domain that are separate accounts; a contact on the shared domain that must land on the second account.
- Account with several workspaces (summary fields only).
- Deal with a stage internal ID and an owner; deal with an unknown owner; deal imported into a stage without its required stage property.
- Missing identifier; unknown company key, with the company import mode stated.
- Contact that must not become marketing; contact that should; previously unsubscribed contact; hard-bounced contact.
- Record whose lifecycle in the file is earlier than in HubSpot.
- The same approved file imported twice.
- Salesforce portals: an account loaded by CSV and then synced; a contact present in both systems with different values.

For each, write the expected result before importing. After the rehearsal compare:

- Arithmetic: created + updated + rejected equals the rows in the file, and each reject is listed with its reason.
- Replay: re-importing the same approved file creates zero records.
- Source IDs and returned Record IDs; associations; owner, lifecycle, opt-outs, consent fields and marketing status; fields that must stay unchanged.

Rehearse in a standard sandbox when the account has Enterprise (record IDs differ from production; integrations are not connected there). Otherwise use a small tagged batch in production with automation off, and keep the tag for cleanup review.

## Merges

- Merges cannot be undone. The Merged record IDs property keeps the history, and a contact or company can only be partly recreated.
- The primary record's values win; blanks on the primary take the secondary's value. You can choose values during a manual merge.
- Lifecycle keeps the stage furthest down the funnel. Marketing status keeps the most marketable. All associations and timeline activities move to the surviving record, which gets a new Record ID unless the account is in the primary-ID preservation beta.
- Records already in a combined 250 merges cannot be merged again. Merges can fail when the result would exceed association limits, and some Salesforce integration versions block company merges.

HubSpot's duplicate tools, as documented on 2026-10-17 (verify live before quoting):

- The duplicates manager needs Professional or Enterprise and shows up to 10,000 pairs. Bulk management and larger limits need Data Hub.
- Custom duplicate rules and the duplicate audit log need Data Hub Professional or Enterprise. The audit log does not include manual merges, so keep your own merge log: pair, survivor, approver, date, source IDs.

Before any merge:

- Confirm identity with source IDs and history, not name similarity.
- If the two records carry different source IDs, fix the duplicate in the source first, or the next upsert recreates it.
- Pick the survivor, list external systems holding the losing ID, and get approval.
- After the merge, update the crosswalk to the surviving Record ID.
- Never bulk merge to suppress a matching problem; fix the key and the writer first.
