RevOps HQ
← BACK TO BLOG
••
CRM Migration•HubSpot

Salesforce to HubSpot Migration: Object Mapping, Migration Paths, Load Order and Cutover

Salesforce to HubSpot migration explained: how each Salesforce object maps, the connector against a scripted load, the load order, and how to verify cutover.

P

Paul Maxwell, PhD

AUTHOR

GET WEEKLY REVOPS INSIGHTS

No spam. Unsubscribe anytime.

On the morning after a Salesforce to HubSpot migration, the first reconciliation compares HubSpot's contact count with Salesforce's leads plus contacts, finds it far lower, and starts a search for records that were never meant to arrive. The deals pass their count check, and their defect goes unexamined: a share arrive with a company and no contact, because Salesforce kept that link on a separate record that some opportunities never had. HubSpot's revenue attribution credits revenue only through a deal's contacts, so that revenue leaves the report and nothing marks its absence.

This article explains how the Salesforce data model maps onto HubSpot and how to move it with both gaps measured first. It starts with the object map and the association rule that decides whether a deal keeps its contacts, then recomputes both on a sample org. Migration paths, rebuilt configuration and the sharing model follow, then a checklist ending in reconciliation. Symptoms, costs and returns, and the reverse direction close it.

Four terms carry the argument. The connector is HubSpot's Salesforce integration, a continuous two-way sync that can also import existing Salesforce records. Smart Transfer is HubSpot's one-way transfer tool for moving another CRM's data into a portal. A scripted migration extracts from Salesforce and writes to HubSpot's APIs under the migrating team's control. An Opportunity Contact Role is the Salesforce record linking a contact to an opportunity; in HubSpot that link is an association, stored on neither record.

The Salesforce Object Model in HubSpot Terms

The third column names the condition that decides whether each move is faithful.

Where each Salesforce object and configuration type lands in HubSpot, and the condition that decides fidelity
SalesforceAccountHubSpot destinationCompanyCondition or lossCompany sync on, and accounts loaded, before opportunities
SalesforcePerson AccountHubSpot destinationContactCondition or lossMapped to a contact by Smart Transfer
SalesforceContactHubSpot destinationContactCondition or lossEmail is the deduplication key
SalesforceLeadHubSpot destinationContactCondition or lossUnconverted leads only; a converted lead is a read-only copy
SalesforceOpportunityHubSpot destinationDeal, in one pipeline per record typeCondition or lossThe connector carries currency amounts as numbers, unconverted
SalesforceOpportunity Contact RoleHubSpot destinationDeal-to-contact associationCondition or lossThe only documented source under the standard deal sync and Smart Transfer
SalesforceTask, Event, Email MessageHubSpot destinationTask, meeting, emailCondition or lossLoaded once: an import cannot update an existing activity
SalesforceCaseHubSpot destinationTicketCondition or lossCarried by the connector and by Smart Transfer
SalesforceCustom objectHubSpot destinationCustom objectCondition or lossEnterprise only, created in HubSpot first
SalesforceRecord typeHubSpot destinationPipeline or propertyCondition or lossPipeline count capped by subscription
SalesforceFormula fieldHubSpot destinationCalculation propertyCondition or lossNot transferred by Smart Transfer
SalesforceValidation ruleHubSpot destinationProperty rule, stage property or pipeline ruleCondition or lossOne property per rule; no cross-field formula
SalesforceApex trigger, flowHubSpot destinationWorkflow or custom code actionCondition or lossRebuilt by hand on every path
SalesforceOrg-wide defaults, role hierarchy, sharing rulesHubSpot destinationOwner-scoped and team-scoped permissionsCondition or lossNo compositional equivalent

Two rows collapse two Salesforce structures into one: the person, treated here, and a deal's link to its people, treated next. Lead conversion creates an account, a contact and optionally an opportunity, moves the lead's activities onto them, and leaves the lead as a read-only record. HubSpot holds one contact per person, matched on email by its import tool. Loading converted leads beside contacts writes each converted person twice onto one email address, and whichever file loads second overwrites the first. The extract should take only leads whose IsConverted field, documented on the lead, is false.

Opportunity Contact Roles and Association Coverage

Both documented native paths derive a deal's contacts from one Salesforce structure. The connector's standard deal sync associates a deal with a contact only where the contact is linked to the opportunity as an OpportunityContactRole, and Smart Transfer's Salesforce mapping names Opportunity Contact Roles as the source of its contact-to-deal associations. A contact held in a custom lookup field, or not recorded at all, yields a deal with a company and no contact.

Where each HubSpot association comes from under the standard deal sync or Smart TransferFour rows pair a Salesforce link with the HubSpot association it becomes under the connector's standard deal sync or Smart Transfer. The Account Name on a contact becomes a contact-to-company association, one company per contact. The Account Name on an opportunity becomes a deal-to-company association, which on the connector needs company sync switched on before deal sync. The Opportunity Contact Role, a junction record holding one row per contact, becomes the deal-to-contact association and is the only documented source of a deal's contacts. An opportunity with no contact role, or with its contact held in a custom lookup field, becomes a deal with a company and no contact, and HubSpot attributes the revenue on such a deal to no interaction.IN SALESFORCEIN HUBSPOTthe source linkafter the standard deal sync or Smart TransferAccount Name on a contactthe contact's account lookupContact-to-company associationone company per contact, from this fieldAccount Name on an opportunitythe opportunity's account lookupDeal-to-company associationconnector: company sync must be on firstOpportunity Contact Rolea junction record, one per contactDeal-to-contact associationthe only documented source of a deal's contactsOpportunity with no contact roleor its contact held in a custom lookupDeal with a company, no contactits revenue is attributed to no interaction
Under the connector's standard deal sync and Smart Transfer, each HubSpot association traces to one Salesforce link, and only the Opportunity Contact Role supplies a deal's contacts

The finding follows, and any org can check it before a record moves. On those two paths, the share of opportunities with at least one contact role is the ceiling on deal-to-contact coverage, and their closed-won amount is the ceiling on what revenue attribution can see. HubSpot's attribution documentation states that revenue on a deal without an associated contact is attributed to no interaction; the attribution reporting article covers the other exclusions.

One newer option is documented only in outline. The connector's updated deal sync, published as a beta on 17 September 2026, adds an association setting with a Primary association field selector, and its documentation does not list which opportunity fields that selector offers. Switching to it cannot be reversed. An org whose buying contacts sit in a custom lookup should test in a sandbox whether that lookup appears there before treating the contact-role ceiling as final.

One query measures the ceiling: SELECT COUNT() FROM Opportunity WHERE Id NOT IN (SELECT OpportunityId FROM OpportunityContactRole), run once for all opportunities, then with SUM(Amount) in place of COUNT() and the filter restricted to closed-won opportunities in the period. Where the buying contacts are known in Salesforce, the fix belongs there, because both documented paths will then carry the roles unaided. Otherwise contacts are associated in HubSpot by import after the load, under their own association label, which needs Professional or Enterprise, so that a contact attached by rule stays visible as an assertion about who bought.

Sample Org Arithmetic: Expected Counts and the Coverage Ceiling

The figures here are sample data for an invented org, chosen so that each can be recomputed; they describe no client. The org holds 14,000 accounts, 40,000 contacts, 50,000 leads and 12,000 opportunities. Of the contacts, 800 lack an email and 2,000 repeat another contact's email. Of the leads, 18,000 are converted; of the 32,000 unconverted, 1,500 lack an email, 3,000 share a contact's email and 500 repeat another lead's.

Sample org (sample data): Salesforce counts against the counts a HubSpot reconciliation should expect
MeasureAccounts to companiesSalesforce14,000Expected in HubSpot14,000
MeasureContacts with a distinct emailSalesforce40,000 contactsExpected in HubSpot37,200
MeasureUnconverted leads adding a new emailSalesforce50,000 leadsExpected in HubSpot27,000
MeasureLeads and contacts with no emailSalesforce2,300Expected in HubSpot0 or 2,300, by decision
MeasurePeople in totalSalesforce90,000 recordsExpected in HubSpot64,200, or 66,500 with the email-less
MeasureOpportunities to dealsSalesforce12,000Expected in HubSpot12,000
MeasureDeals with at least one contactSalesforce9,000 with a contact roleExpected in HubSpot9,000 at most, 75%
MeasureClosed-won, last four quartersSalesforce$14.4M on 2,400 opportunitiesExpected in HubSpot$10.2M attributable at most, 70.8%

The naive target of 90,000 people exceeds the email-keyed 64,200 by 25,800: the 18,000 converted leads, 3,000 leads matching a contact, 500 repeated leads, 2,000 repeated contacts and 2,300 records without email. Written down beforehand, that subtraction is a target; unwritten, it is 25,800 phantom losses.

The coverage ceiling is fixed before anything moves. Of 2,400 closed-won opportunities, the 1,700 with a contact role hold $10.2M and the 700 without hold $4.2M, so revenue attribution can describe no more than 70.8% of the period's closed-won revenue.

Volume is the last check. A connector contact sync can use up to four Salesforce API calls per record, so 72,000 unconverted leads and contacts can draw up to 288,000 calls from the org's allocation. A script sends 100 inputs per batch request, so the 90,200 people, companies and deals need 902 requests: under a minute at the 190 requests per ten seconds a private app receives on Professional.

Migration Paths: HubSpot's Salesforce Connector, Smart Transfer and a Scripted Load

The three migration paths, what each carries and what constrains it, as documented in September 2026
PathConnector importWhat it carriesLeads, contacts, accounts, opportunities, tasks, a campaign, cases, events and custom objectsWhat constrains itProfessional or Enterprise; a continuous sync; people outside an inclusion segment arrive with email only
PathSmart TransferWhat it carriesStandard objects, users and email templates, then attachments and campaign listsWhat constrains itSuper Admins only; lookup, formula and encrypted fields unsupported; custom field mappings need Data Hub
PathScripted loadWhat it carriesAnything the Salesforce API returnsWhat constrains itBuilt, tested and owned by the migrating team

The connector import suits an org that will run both systems for a period. Opportunity import creates no deals until deal sync is on, and deals lose their company unless company sync is on and accounts are imported first. The sync runs until switched off, which suits the side-by-side arrangement in the HubSpot Salesforce integration article and becomes a liability once Salesforce is retired.

Smart Transfer is one-way and can be reverted, but its Salesforce mapping lists no custom objects and skips reference, calculated and encrypted fields. Apart from the account, contact and contact-role links it converts into associations, every lookup and formula field in the org stays behind.

A scripted load carries what the native paths leave behind: formula values stored as numbers, custom lookups turned into labelled associations, and a deterministic key on every record. It is safe to rerun when built on a batch upsert keyed on a unique property holding the Salesforce record ID, so that a repeated run updates rather than duplicates.

Record Types, Validation Rules, Apex and Flows

Salesforce record types vary business processes, picklist values and page layouts by user. On opportunities they become pipelines. The connector's standard deal sync creates one per record type, named Salesforce - [record type ID], and the updated deal sync instead maps each record type to a pipeline that already exists. Custom pipelines are capped across all objects at 15 on Starter, 100 on Professional and 350 on Enterprise for seat-based portals. Record types elsewhere, or several sharing one sales process, fit a dropdown property better.

A Salesforce validation rule evaluates a formula across one or more fields and blocks the save when it returns true. HubSpot splits that job three ways, none of which reads a formula. Property validation rules constrain one property's format, range or uniqueness; conditional stage properties require values before a stage; pipeline rules limit the stages a record is created in, skips or leaves backwards. A rule requiring an amount at Closed Won becomes a required stage property, which HubSpot documents as applying when a user creates or moves a record by hand, where the Salesforce rule fired on every save. A comparison between two unrelated fields becomes a workflow that flags the record after saving.

Apex triggers and flows move by no path. They are rebuilt as workflows on Professional or Enterprise, or as custom code actions on Data Hub Professional or Enterprise, and formula fields become calculation or rollup properties. Which automations earn a rebuild is a usage question, answered by the move, rebuild and abandon test in HubSpot migration services.

This configuration waits for the data. HubSpot applies property validation rules to imports, enforces pipeline rules on integration and API writes that pass a user ID, and by default enrolls a record the first time the record meets a workflow's triggers. Rules switched on early reject history, and workflows switched on early treat years of closed deals as events happening today.

Sharing Model Differences

Salesforce sets a baseline per object through organisation-wide defaults of Private, Public Read Only or Public Read/Write, and the role hierarchy and sharing rules can only widen it. HubSpot scopes view and edit permissions to all records, the user's team's records or the user's own, with an optional allowance for unassigned records.

HubSpot visibility therefore derives from ownership and team membership, which makes owner mapping the permission migration. Under the same guide, owner access extends to any user named in a HubSpot user property as well as the record owner, and team scope covers every team a user is assigned to. A record whose Salesforce owner has no HubSpot user arrives unassigned, visible only to users granted all records or the unassigned allowance. An owner-based sharing rule can be approximated through team membership, and a grant to named individuals through a user property. A criteria-based rule opening one class of records to one group has no equivalent, a gap the HubSpot vs Salesforce comparison treats as a selection criterion.

Salesforce to HubSpot Migration Checklist and Load Order

Each step exists because a later one depends on it; the diagram states the constraint behind each position.

Salesforce to HubSpot migration load order, eleven stepsEleven steps run top to bottom, matching the article's checklist, each with the reason it comes where it does. One: measure in Salesforce, to set the expected counts and the contact-role coverage. Two: users, owners and teams, because HubSpot visibility derives from owner and team. Three: a unique Salesforce ID property, because uniqueness can be set only when a property is created. Four: pipelines per record type with rules off, because pipeline rules bind integration and API writes that pass a user ID. Five: accounts to companies, because deals need company sync and accounts first. Six: contacts and unconverted leads, because email is the key and converted leads are copies. Seven: opportunities and contact roles, with deal sync on first, the roles becoming deal-to-contact associations. Eight: tasks, events and emails, once, because an import cannot update an existing activity. Nine: freeze, delta load and connector off, to catch late edits and stop the sync writing back. Ten: rules and workflows on, because they bind imports and enroll records on first match. Eleven: reconcile against the targets, covering contact coverage, closed-won amount per pipeline and one traced deal.LOAD ORDERWHY IT COMES HERE1Measure in Salesforcetargets: expected counts, contact-role coverage2Users, owners and teamsHubSpot visibility derives from owner and team3Unique Salesforce ID propertyuniqueness can be set only when it is created4Pipelines per record type, rules offpipeline rules bind integration writes that pass a user5Accounts to companiesdeals need company sync and accounts first6Contacts and unconverted leadsemail is the key; converted leads are copies7Opportunities and contact rolesdeal sync first; roles become deal-to-contact links8Tasks, events and emails, oncean import cannot update an existing activity9Freeze, delta load, connector offcatches late edits; stops the sync writing back10Rules and workflows onthey bind imports and enroll records on first match11Reconcile against the targetscoverage, closed-won per pipeline, one traced deal
The eleven checklist steps in load order, each beside the constraint that places it before the next
  1. Measure in Salesforce and record the targets: accounts, contacts, unconverted leads, opportunities, opportunities without a contact role, and closed-won amount with and without contact roles.
  2. Create users under Settings > Users & Teams, recreate teams, and map every Salesforce owner, inactive ones included, to a HubSpot user.
  3. Under Settings > Properties, create a single-line text property for the Salesforce record ID on contacts, companies and deals, selecting Require unique values for this property on the Rules tab at creation, since uniqueness cannot be added later.
  4. Create one deal pipeline per opportunity record type in use under Settings > Data Management > Objects > Deals > Pipelines, unless the connector's standard deal sync will create its own, and leave pipeline rules off.
  5. Load accounts as companies. On the connector path, switch on company sync, then import through CRM > Contacts > Add contacts > Import > Import data > Objects from an app > Salesforce records.
  6. Load contacts and unconverted leads, and compare the result with the expected count from step 1, not the Salesforce total.
  7. On the connector path switch on deal sync, then load opportunities as deals, with deal-to-contact associations from Opportunity Contact Roles.
  8. Load tasks, events and email messages once, after every parent record exists.
  9. Freeze Salesforce edits, load records whose Last Modified Date follows the extract, switch off the connector sync, and repoint every integration that wrote to Salesforce.
  10. Switch on validation rules, pipeline rules and rebuilt workflows, one pipeline at a time.
  11. Verify: the count of deals whose Number of associated contacts is 0 or unknown equals step 1's opportunities without a contact role; closed-won amount per pipeline equals closed-won amount per record type; and one known opportunity traced field by field arrives with its owner and activities.

Salesforce to HubSpot Migration Challenges: Symptoms and Causes

The HubSpot contact count sits far below Salesforce leads plus contacts. The target was wrong, not the load: converted leads duplicate contacts and HubSpot keeps one contact per email, so the fix is the expected count from step 1.

Contacts arrived with an email address and nothing else. The connector imported them outside the inclusion segment, where every property but email stays blank; add them to the segment and resync, or reload properties by import keyed on the Salesforce ID.

Revenue attribution shows a fraction of closed-won revenue. The missing deals have no associated contact because their opportunities had no contact role; the repair is contact roles in Salesforce, or labelled associations in HubSpot.

Imported rows are rejected, closed deals cannot be created, or customers receive emails during the load. Rules and workflows were switched on before step 10: validation rules apply to imports, pipeline rules to integration writes that pass a user ID, and workflows to any record meeting their triggers for the first time. They go off for the load, and workflows return with triggers excluding records that carry a Salesforce ID.

Sales users cannot see records they worked in Salesforce. Owners were never mapped or teams never recreated, so the records sit unassigned or outside the users' team scope.

Deal amounts are wrong in a multi-currency org. The connector does not convert currencies and carries only the number, so amounts need correcting by import.

Salesforce emails are missing from HubSpot timelines. Emails captured by Einstein Activity Capture are not stored as task activities, so the connector never sees them, and they need a separate extract.

Costs and Returns of Leaving Salesforce

Where HubSpot already runs marketing, a migration buys one record per person instead of a lead and a contact, and removes the connector with the reconciliation it maintains. It costs a rebuild: every automation, validation rule and report is re-expressed rather than moved, and custom objects need Enterprise. The firm is a HubSpot Solutions Partner with an interest in migrations happening, which is reason to state plainly where Salesforce is stronger.

Two axes favour Salesforce on the documentation alone. Its sharing model composes defaults, hierarchy and rules into access patterns that owner and team scopes approximate at best, and criteria-based sharing not at all. Its validation rules evaluate formulas across fields on every save, where each HubSpot rule governs one property. The wider platform comparison is the white paper on Salesforce vs. HubSpot CRM in revenue operations.

The case is strongest where the org runs on standard objects, grants access by owner and team, and carries automation that a usage audit shows to be largely dormant. It is weakest where compartmentalised access is a regulatory obligation, where Apex must run synchronously on save, or where reproducing a custom-object model would need Enterprise across the portal. The Salesforce to HubSpot migration case study records one instance, including a capability that did not transfer.

HubSpot to Salesforce Migration: The Reverse Direction

A HubSpot to Salesforce migration runs the same map backwards, and its challenges are the collapses above reversed. Each HubSpot contact becomes a lead or a contact, and the connector's sync setting for that choice warns that leads combined with automatic company creation produce duplicate companies at conversion. Deal-to-contact associations become Opportunity Contact Roles, which the connector creates on sync, and a contact associated with several companies needs one chosen as its account.

Access is where the reverse direction gains: owner and team scopes are redesigned as organisation-wide defaults, roles and sharing rules, which is more work and more expressive. Converted leads and original creation dates can be inserted once Salesforce's Create Audit Fields setting exposes `IsConverted` and the conversion fields to Data Loader.

Scope and Limits of the Evidence

This covers Salesforce sales objects, cases, custom objects and their configuration, not Account Engagement or Marketing Cloud data, Salesforce CPQ, or files at volume. Behaviour, tier gates, limits and navigation paths are as documented in September 2026 by HubSpot and Salesforce, whose documentation governs wherever this text diverges. Salesforce's SOQL reference could not be retrieved for this article, so the coverage query should be tested in a sandbox first.

The coverage ceiling is structural, following from how the standard deal sync and Smart Transfer are documented to build associations. It is untested against the updated deal sync, whose association options were not documented when this was checked. The sample proportions are invented, and no published measurement of contact-role coverage across Salesforce orgs was located, so nothing here says how large the gap is in a typical org.

Frequently Asked Questions

Is there an official Salesforce to HubSpot data migration guide? HubSpot documents two paths rather than one guide, the connector's record import and Smart Transfer, so a Salesforce to HubSpot migration guide built on them still has to supply the load order and expected counts.

What does the Salesforce to HubSpot migration process consist of, and what belongs on its checklist? The eleven steps above. A Salesforce to HubSpot migration checklist that omits the expected contact count and the share of opportunities without a contact role has no targets to reconcile against.

What are the main Salesforce to HubSpot migration challenges? Converted leads, opportunities without contact roles, record types beyond the pipeline cap, cross-field validation rules, Apex and flows, and sharing rules with no HubSpot equivalent.

Can a Salesforce migration to HubSpot run through the connector alone? For standard objects on Professional or Enterprise, and custom objects on Enterprise, it can, although a lookup on a custom object travels only as an association and a change to a formula field does not itself trigger a sync.

What are the HubSpot to Salesforce migration challenges, and can a HubSpot migration to Salesforce use the same connector? The connector syncs both ways, so it can. The challenges are choosing lead or contact for each person, reducing multi-company associations to one account per contact, and designing a sharing model HubSpot never needed.

In Summary

Accounts become companies, unconverted leads and contacts become contacts, opportunities become deals in one pipeline per record type, and Opportunity Contact Roles become deal-to-contact associations. Validation rules, Apex, flows and formula fields are rebuilt, and the sharing model reduces to owners and teams.

Two numbers decide whether the result can be trusted, and Salesforce holds both before anything moves. The expected contact count is unconverted leads and contacts after email deduplication, not their raw total. The share of opportunities with a contact role caps deal-to-contact coverage under the standard deal sync and Smart Transfer, and their closed-won amount caps what revenue attribution can report. Compute both, load in dependency order with every rule off, and reconcile against the computed figures rather than the Salesforce totals.

HubSpot services

Onboarding, implementation, integration, migration, administration and training, each scoped and priced before the work begins

WEEKLY PROGRAM

RevOps Office Hours

A recurring weekly RevOps operating program. Live support plus hands-on HubSpot implementation work.

$1,500/mo
Monthly Operating Program
  • →1 live Office Hours session per week
  • →4 hours of hands-on implementation work per month
  • →Hours allocated against priorities agreed at the start of each period
  • →Recurring monthly cadence