Dynamics to HubSpot: Domain Deduplication
/ 9 min read
Table of Contents
Fifteen percent of our company records had duplicate domains. Not duplicates in the traditional sense — HubSpot saw them as unique — but semantically identical because Dynamics used domain + country as the unique key and HubSpot just uses domain.
I didn’t discover this until day three of the migration. It was not my finest moment.
The Architectural Mismatch
Microsoft Dynamics and HubSpot handle company deduplication fundamentally differently, and understanding this gap is critical before you start moving data.
Dynamics CRM allows composite keys. In this client’s setup, they used domain + country as their unique identifier. This meant acme.com could exist as three separate records:
acme.com— United Kingdomacme.com— United Statesacme.com— Germany
Each was a distinct company with its own contacts, deals, and activity history. The domain field linked to a one-to-many table where country was the differentiator.
HubSpot treats Company Domain Name as the sole unique identifier for companies. Full stop. There’s no native support for composite keys, and the platform uses this field for:
- Automatic deduplication on import
- Matching new contacts to existing companies
- Merging data during bulk updates
- Powering the “Companies” data enrichment features
When HubSpot sees acme.com on three import rows, it doesn’t create three companies. It creates one and merges the rest. Silently. Without asking. This is efficient behaviour unless you specifically needed those three separate records, in which case it’s chaos.
What Actually Happens During Import
Let’s walk through the exact behaviour when you import company records with duplicate domains.
Scenario: Three Dynamics Records with Shared Domain
Your import file contains:
| Company Name | Domain | Country | Annual Revenue |
|---|---|---|---|
| Acme UK | acme.com | UK | £2,000,000 |
| Acme US | acme.com | US | $5,000,000 |
| Acme DE | acme.com | DE | €1,500,000 |
HubSpot’s Behaviour
Row 1 (Acme UK): HubSpot creates a new company record with domain acme.com. All properties populate normally.
Row 2 (Acme US): HubSpot finds an existing company with domain acme.com. Instead of creating a new record, it updates the existing company with the new property values. Last-write-wins logic applies — so Country becomes US and Annual Revenue becomes $5,000,000.
Row 3 (Acme DE): Same behaviour. The existing record gets updated again. Final state: Country = DE, Annual Revenue = €1,500,000.
The Result
You now have one company instead of three, with German data overwriting everything else. The UK and US records effectively no longer exist as separate entities.
Critically, HubSpot doesn’t reject the duplicate rows. It silently merges them. Your import will show as “successful” with no errors, but you’ve lost two-thirds of your company data structure. The word “successful” is doing a lot of heavy lifting here.
What About Contacts?
The restriction applies only to companies. If domain is simply a field on Contact records, HubSpot will accept all contacts regardless of duplicate domains. No rejection, no merging.
This means your contact data survives intact — but the company associations become problematic when multiple contacts should belong to different regional entities that HubSpot has collapsed into one.
Four Solutions for Regional Company Structures
When business logic requires separate companies per country despite shared domains, you need an alternative approach. Here are the options I’ve used on enterprise migrations, with trade-offs for each. None of them are perfect. Such is life.
Option A: Composite Domain Values
Create synthetic unique domains by combining the original domain with a differentiator.
Implementation:
acme.com-ukacme.com-usacme.com-deOr using a cleaner format:
uk.acme.comus.acme.comde.acme.comAdvantages:
- Simple to implement in your migration scripts
- Preserves HubSpot’s automatic features (contact association, enrichment)
- Works with standard import tools
Disadvantages:
- Looks unnatural in the UI
- May confuse users searching by domain
- Third-party enrichment tools (ZoomInfo, Clearbit) won’t recognise the modified domains
Best for: Quick migrations where enrichment isn’t a priority and users understand the naming convention.
Option B: Custom Unique Value Property (Native HubSpot Feature)
As of late 2023, HubSpot natively supports custom properties that require unique values as import deduplication keys. This is now a first-class feature, not a workaround.
Implementation:
- Create a custom property with “Require unique values” enabled (Settings → Properties → Create property → Rules)
- Name it something clear:
dynamics_company_idorregional_company_key - Populate with your Dynamics composite key:
acme.com|UK - During import, select this property as your unique identifier instead of domain
- Leave
Company Domain Nameblank for regional subsidiaries, or populate all with the same domain — HubSpot will use your custom property for matching
You can create up to 10 unique value properties per object (Pro/Enterprise required).
Advantages:
- Native HubSpot feature — fully supported
- Maintains data integrity from source system
- Clear audit trail back to Dynamics
- Import deduplication works correctly
- Can have duplicate domains across companies
Disadvantages:
- No automatic contact-to-company association (domain-based)
- No domain-based workflow triggers
- Does not work for form submissions — forms still use email/domain only
- HubSpot enrichment won’t function without domain
- Manual processes needed for ongoing contact routing
Best for: Complex enterprise migrations where you need exact source system parity. Particularly strong when your source system has a robust unique identifier you want to preserve.
Option C: Parent-Child Company Hierarchy
Use HubSpot’s native parent-child relationships to represent the structure.
Implementation:
- Import the global entity first with the actual domain:
Acme Global—acme.com
- Import regional entities as children with modified or blank domains:
Acme UK— parent:Acme GlobalAcme US— parent:Acme GlobalAcme DE— parent:Acme Global
Advantages:
- Semantically correct representation of corporate structure
- Built-in HubSpot reporting on parent/child relationships
- One entity retains the true domain for enrichment
Disadvantages:
- Parent companies must exist before importing children
- Child companies still can’t share the parent’s domain
- Requires two-phase import process
- Association rules become complex
Best for: True corporate hierarchies where the parent/subsidiary relationship is meaningful to the business.
Option D: Consolidate to Single Global Company
Accept HubSpot’s model and merge regional entities into one global company, using custom properties to track regional attributes.
Implementation:
- Create multi-select or JSON properties for regional data:
operating_countries(multi-checkbox)regional_revenue(JSON or separate properties per region)
- Migrate all contacts and deals to the single company
- Use custom properties to filter and segment by region
Advantages:
- Cleanest HubSpot-native approach
- Full enrichment and automation capabilities
- Simplest ongoing maintenance
Disadvantages:
- Loses regional company-level reporting
- May not align with organisational structure
- Requires business process changes
Best for: Organisations willing to adapt their data model to HubSpot’s architecture, particularly if regional separation isn’t critical for sales or marketing operations.
The API Workaround (And Why It Matters)
Here’s something the documentation doesn’t make obvious: companies created via the HubSpot API bypass domain deduplication entirely. I wish I’d known this three days earlier.
If you create companies programmatically using the CRM API’s POST /crm/v3/objects/companies endpoint, HubSpot will create separate records even with identical domains. The deduplication logic only applies to UI imports. This also applies to third-party integrations and sync apps — they use the API under the hood.
// This creates a new company even if acme.com already existsconst response = await hubspotClient.crm.companies.basicApi.create({ properties: { name: 'Acme US', domain: 'acme.com', country: 'United States' }});Best Practice: Search Before Create
If you’re using the API and want to avoid duplicates, use the Search for companies by domain endpoint first:
// Check if company exists before creatingconst searchResponse = await hubspotClient.crm.companies.searchApi.doSearch({ filterGroups: [{ filters: [{ propertyName: 'domain', operator: 'EQ', value: 'acme.com' }] }]});
if (searchResponse.results.length === 0) { // Safe to create new company} else { // Update existing or handle as needed}When API Bypass is Useful
For complex migrations, you might intentionally use the API to create your regional company structure (preserving “duplicates”), then use standard imports for contacts and deals that associate to the pre-created companies by Record ID rather than domain.
Caution: This creates a data state that HubSpot’s UI doesn’t expect. Running deduplication tools later will flag these as duplicates. Document your architecture clearly and train users to understand why multiple companies share domains.
Implementation Checklist
Before you start your migration, work through these decisions:
1. Audit Your Source Data
-- Find domains with multiple country associationsSELECT domain, COUNT(DISTINCT country) as country_countFROM companiesGROUP BY domainHAVING COUNT(DISTINCT country) > 1ORDER BY country_count DESC;For our client, this revealed 341 companies with shared domains across multiple regions — roughly 15% of their company base.
2. Check Your HubSpot Subscription
Custom unique value properties require Professional or Enterprise. If you’re on Starter/Free, your options are limited to composite domains (Option A) or parent-child structures (Option C).
3. Define Your Target State
Answer these questions with your stakeholders:
- Do sales teams need separate pipeline reporting by region?
- Are there different owners or teams per regional entity?
- Does finance require revenue tracking at the regional company level?
- Will regional entities have different lifecycle stages or qualification criteria?
If the answer to most of these is “yes,” you need Options A, B, or C. If regional separation is mainly historical and not operationally critical, Option D may simplify your life.
4. Plan Your Association Strategy
Whichever option you choose, map out:
- How new contacts will associate to the correct regional entity
- How form submissions will route to the right company
- What happens when a contact’s company changes
- How deals will track against regional vs global entities
5. Test with a Representative Sample
Never trust theory. Run a 500-record test import covering:
- Companies with unique domains (control group)
- Companies with shared domains (your problem cases)
- Contacts that should associate to specific regional entities
- Deals with multi-company relationships
Validate the results before committing to full migration.
Lessons from the Field
That migration I mentioned at the start? We went with Option B — custom unique identifiers with blank HubSpot domains for regional subsidiaries.
The deciding factors:
- ZoomInfo integration was planned for post-migration. We couldn’t use composite domains that ZoomInfo wouldn’t recognise.
- Sales teams needed distinct company records for territory management and regional revenue reporting.
- Data lineage was critical for the client’s compliance requirements. They needed to trace every HubSpot record back to its Dynamics source.
The trade-off was accepting manual contact association for form submissions and building custom workflows for lead routing. For this client’s volume and team structure, that was manageable.
For a different client with less strict data governance needs, Option A (composite domains) would have been faster and simpler.
There’s no universally correct answer — only the right answer for your specific constraints. I realise that’s frustratingly nuanced, but it has the advantage of being honest.
Key Takeaways
- HubSpot uses domain as a unique identifier — duplicate domains merge silently on import, not reject
- Dynamics composite keys don’t translate directly — plan your strategy before migration
- Custom unique value properties are now native — HubSpot supports up to 10 per object for import deduplication (Pro/Enterprise)
- API and integrations bypass deduplication — useful for complex scenarios but creates non-standard data states
- Forms still use email/domain only — custom unique properties don’t work for form submissions
- Test before committing — a 500-record sample will reveal issues that documentation won’t
If you’re planning a Dynamics to HubSpot migration and this scenario applies, reach out. Happy to share more details from our implementation or review your approach.
Have you hit this issue on a migration? What approach did you take? I’d be interested to hear other solutions — find me on LinkedIn.