Connect HubSpot to Salesforce
Why teams connect HubSpot and Salesforce
Marketing runs in HubSpot, sales runs in Salesforce, and the two need the same picture of a contact, a company, and a deal. HubSpot's own Salesforce sync covers the basics, but many teams outgrow it: they need field-level control over who wins, dedup logic that matches their data, custom object coverage, and a record of what the sync did.
- Each field has a defined source of truth, so a rep editing a title in Salesforce is not overwritten by a stale HubSpot value, and vice versa
- New contacts are matched, not duplicated: email first, then the stored cross-system IDs, then an optional name-and-company check
- Custom objects and custom fields on both sides are in scope, not just the standard object set
- Every record sync is a run you can inspect, so a contact that looks wrong can be traced to the sync that wrote it
Worked example
The lead handoff flow most teams turn on first.
HubSpot SQL to a Salesforce Lead, and Salesforce status back to HubSpot
Started when a HubSpot contact reaches Sales Qualified Lead, with dedup against existing Salesforce records and a field-level merge on the way back.
- Trigger: HubSpot
New or updated contact, polled on the schedule you set, with a Filter that continues only whenlifecyclestageissalesqualifiedlead. - Fetch: the trigger delivers the contact record;
Get associationand a batch read add its company. - Dedup: search Salesforce for a
ContactbyEmail, then aLeadbyEmail, then aLeadmatchingLastNameplusCompany. Use the first match. - Resolve owner: a data table maps the HubSpot owner's email to a Salesforce
User.Id. If the contact has no owner, assign by territory rules. - Write: upsert the Salesforce
Lead, keyed on the storedHubspot_Contact_Id__c, mapping the fields below. Company defaults to[Self-sourced]if the HubSpot company is blank, because Lead requires it. - Stamp both sides: write the Salesforce
Lead.Idto the HubSpot propertysalesforce_lead_id, and the HubSpoths_object_idtoLead.Hubspot_Contact_Id__c. - Reverse: a second flow polls Salesforce
LeadandContactchanges and updates HubSpot, but only the fields where Salesforce is the source of truth (lead status, owner, opportunity stage).
Field mapping
The starting map for the HubSpot contact to Salesforce Lead step. The source-of-truth column is the rule the reverse flow reads.
| HubSpot property | Salesforce field | Source of truth / notes |
|---|---|---|
email | Email | Primary match key. Lowercased on write. Not unique in HubSpot, so cross-IDs back it up. |
hs_object_id | Hubspot_Contact_Id__c | Reverse match key. Custom field on Lead and Contact. |
salesforce_lead_id | Id | Idempotency key. Written back to HubSpot after the first create. |
firstname, lastname | FirstName, LastName | HubSpot source. Reverse only if blank in HubSpot. |
company | Company | Override. Lead requires a value; default to [Self-sourced] when blank. |
jobtitle | Title | Salesforce source once a rep owns the lead. HubSpot source before that. |
hubspot_owner_id | OwnerId | Resolved through an owner-map table. IDs do not match across systems. |
hs_analytics_source | LeadSource | Enum, mapped through a lookup. HubSpot source, never overwritten. |
lifecyclestage | Status (derived) | Drives the object choice and the initial status, not a direct field copy. |
createdate | (not written) | Epoch milliseconds in HubSpot. Not written to Salesforce, which sets its own CreatedDate. |
What syncs, each direction
- Qualified people and companies. Contacts at a chosen lifecycle stage become Leads or Contacts. Associated companies become Accounts, matched on domain. (HubSpot to Salesforce)
- Marketing context. Original source, first and last touch campaign, and email engagement land as fields or campaign members for attribution in Salesforce. (HubSpot to Salesforce)
- Pipeline and ownership. Lead status, opportunity stage and amount, owner changes, and closed-won flow back and set the HubSpot lifecycle stage and deal. (Salesforce to HubSpot)
- Consent and do-not-contact. An email opt-out or a do-not-contact flag set on either side reaches the other on the next poll, whichever system it originated in. (Either direction)
Governance and audit
The same controls apply to this sync as to every other Neblex workload.
- Run history. Every record sync is a run with each step's input and output. A failed run can be replayed from the step that failed, and the stored cross-system IDs stop a second create.
- Approval steps. Add a Wait for form step wherever a person should check a change first, such as a bulk change or a merge that would collapse two Salesforce records into one.
- Scoped access. HubSpot uses a private app token with only the needed scopes. Salesforce uses a connected app and a permission set limited to the synced objects.
- Environments. Build against a HubSpot test account and a Salesforce sandbox, then promote the same flow and mapping to production.
Frequently asked questions
How quickly do changes sync?
Within minutes. Changes on either side are picked up by the polled change triggers on the schedule you set, from every minute upward, and a scheduled reconcile catches anything a poll missed.
How are conflicts resolved when both sides change a field?
By a source-of-truth rule per field, which you set in the mapping. Where both sides can legitimately edit a field, the flow compares the modified times and the later change wins, with the run showing which side wrote it.
How are duplicates prevented?
Matching runs email first, then the stored cross-system IDs on both records, then an optional name-and-company check. The write is keyed on the stored ID, so a retry updates rather than creates.
Does this replace HubSpot's native Salesforce sync?
It can. HubSpot's native sync is a reasonable choice for a simple standard-object sync. Teams move to this for field-level control, custom objects, dedup they define, and one run history across every integration, not just this one.
Are custom objects supported?
Yes. Salesforce custom objects, and HubSpot custom objects on Enterprise tiers, are mapped the same way as standard objects.
Does anything get installed in Salesforce?
No. The connector uses the Salesforce REST and Bulk APIs through your connected app. No managed package or Apex is deployed.
Connectors used
HubSpot
CRM & Sales
- Operations
- 336
- Operations with typed output
- 81.5%
- Change triggers
- 46 (poll)
- Signs in with
- API token
Salesforce
CRM & Sales
- Operations
- 1,296
- Operations with typed output
- 57.9%
- Change triggers
- 31 (poll)
- Signs in with
- OAuth 2.0 sign-in
Bring one real integration
We will build it with you against your own systems, with the run log open.