To migrate agency client data from HubSpot to Salesforce without losing history, export all objects (contacts, companies, deals, activities, notes) with their original timestamps and owner IDs, map fields between the two CRMs, then import in dependency order using a tool like the Salesforce Data Loader or a managed migration service. The key is preserving createdAt dates and engagement records, which HubSpot stores separately from core records.
Why HubSpot-to-Salesforce migrations lose history
Most teams get this wrong because they treat the migration like a simple CSV dump. HubSpot and Salesforce model data differently. HubSpot uses a flat object model with contacts, companies, deals, and tickets, plus a unified engagements API for emails, calls, notes, and meetings. Salesforce splits these into Leads, Contacts, Accounts, Opportunities, and a polymorphic Activity (Task/Event) model.
The history you risk losing falls into three buckets:
- Timestamps —
createdateandlastmodifieddateget reset to import time unless you explicitly map them. - Activity/engagement logs — emails, calls, and notes live in HubSpot's engagement objects and are often skipped entirely.
- Ownership and associations — the link between a deal and its contacts, or a contact and its owner, breaks if IDs aren't mapped first.
If you're still deciding between platforms, compare HubSpot Sales Hub vs Salesforce Sales Cloud before committing to the move.

Step-by-step migration that preserves history
1. Audit and clean data in HubSpot first
Deduplicate contacts and companies before you touch Salesforce. Migrating dirty data just moves the mess. Export a full property list from HubSpot Settings > Properties so you know every custom field that needs a Salesforce equivalent.
2. Build a field mapping document
Create a spreadsheet mapping each HubSpot property to a Salesforce field. Flag fields with no destination — you'll either create custom fields in Salesforce or drop them. Pay attention to:
- HubSpot
record ID→ store in a custom external ID field on Salesforce (e.g.,HubSpot_ID__c). This is critical for re-linking associations. - Deal stages → Opportunity stages (the picklist values rarely match).
- Owner emails → Salesforce User IDs.
3. Create an external ID field in Salesforce
Add a custom field like HubSpot_ID__c marked as External ID and Unique on every object. This lets you upsert records and rebuild relationships without duplicates. It's the single most important step for keeping associations intact.
4. Export from HubSpot in dependency order
Use the HubSpot CRM exports or the HubSpot API for objects with more than 10,000 records. Pull engagement data through the engagements endpoint — the standard UI export won't include call and email logs. Export in this order:
- Companies
- Contacts
- Deals
- Engagements (notes, emails, calls, meetings, tasks)
5. Import into Salesforce in the right sequence
Load records so parent objects exist before children. Use the Salesforce Data Loader for bulk operations and upsert keyed on HubSpot_ID__c.
| Order | HubSpot object | Salesforce target | Operation |
|---|---|---|---|
| 1 | Companies | Accounts | Insert |
| 2 | Contacts | Contacts | Upsert |
| 3 | Deals | Opportunities | Upsert |
| 4 | Engagements | Tasks / Events | Insert |
6. Preserve original timestamps
Salesforce normally sets CreatedDate to the import time. To keep the real dates, enable the Create Audit Fields permission (Setup > User Interface > enable "Set Audit Fields upon Record Creation"). Then map HubSpot's createdate to CreatedDate in your import file. Without this, every record looks like it was created on migration day.
Generate Proposals with AI in seconds.
Try now
Tools and approaches compared
You've got three realistic paths:
- Native Salesforce Data Loader + manual mapping — free, full control, but slow and error-prone for engagement history. Best for under 50,000 records.
- Migration platforms (Trujay, Import2, Coupler.io) — handle field mapping and associations automatically, preserve timestamps, and migrate activities. Costs scale with record volume.
- Custom ETL via APIs — maximum control for complex agency hierarchies, but requires developer time.
For agencies juggling many client accounts, the association integrity matters more than raw speed. A botched parent-child link between Accounts and Contacts can take longer to fix than the original migration. Teams that have run a Qvidian to Responsive migration know how much cleanup unmapped fields create downstream.

Validation after migration
Don't trust a green import log. Run these checks:
- Record counts — match Salesforce totals against HubSpot exports per object.