CRM migration
Field-level mapping, validation, and rollback between Customer.io and Microsoft Dynamics 365 Sales . We move data and schema; workflows are rebuilt natively in Microsoft Dynamics 365 Sales .
Customer.io
Source
Microsoft Dynamics 365 Sales
Destination
Compatibility
6 of 10
objects map 1:1 between Customer.io and Microsoft Dynamics 365 Sales .
Complexity
BStandard
Timeline
3-5 weeks
Overview
Moving from Customer.io to Microsoft Microsoft Dynamics 365 Sales is a platform-type migration: Customer.io is an event-driven behavioral messaging platform, while Microsoft Dynamics 365 Sales is a relational CRM. The two systems use fundamentally different data models — Customer.io stores identity-first Profiles with a full event timeline and nested traits; Dynamics 365 separates Leads, Contacts, and Accounts into a normalized relational schema. We resolve this structural gap during scoping by designing the Lead-versus-Contact split rule, pre-creating Dataverse custom entities for event history and behavioral traits, and mapping the Customer.io userId to the appropriate Dynamics 365 primary key. We migrate active People records as Contacts or Leads, Customer.io Companies as Accounts, Custom Objects as Dataverse custom entities, and the full event timeline as a custom event entity linked to the Contact. We do not migrate Campaigns, Journeys, Workflows, Segments, or Broadcasts as code; we deliver a written inventory of every active workflow and segment for the customer to rebuild in Microsoft Dynamics 365 Sales or Power Automate. Push notification migration is not applicable to this destination pair because Microsoft Dynamics 365 Sales has no native push channel and device tokens cannot be imported from Customer.io.
Every standard and custom field arrives verified.
AI proposes the map; you confirm before any record moves.
Parent–child, lookups, and ownership stay linked.
Calls, emails, meetings — with original timestamps.
Documents, uploads, and inline notes move with the record.
Source platform
Customer.io platform overview
Scorecard, SWOT, gotchas, and pricing for Customer.io.
Destination platform
Microsoft Dynamics 365 Sales platform overview
Scorecard, SWOT, gotchas, and pricing for Microsoft Dynamics 365 Sales .
Data migration guide
The complete Microsoft Dynamics 365 Sales migration guide
Data model, import mechanisms, field mapping strategy, pitfalls, and cutover — by the engineers running it.
Destination checklist
Microsoft Dynamics 365 Sales migration checklist
Pre- and post-cutover tasks for moving onto Microsoft Dynamics 365 Sales .
Why teams make this switch
Leaving
What's pushing teams away
Choosing
What's pulling them in
Object mapping
Each row shows how a Customer.io object lands in Microsoft Dynamics 365 Sales , including any object-level transformations, lookup resolution, or schema-design dependencies.
Typical mapping — final map is confirmed during the sample migration step.
Customer.io
Person (Profile)
Microsoft Dynamics 365 Sales
Contact or Lead (split required)
1:manyCustomer.io Profiles with a clear email address and business identity map to Dynamics 365 Contact. Anonymous Profiles (identified by anonymousId only with no email) map to Dynamics 365 Lead or are flagged for manual review. We compute the split using the presence of a valid email property in the Customer.io identify() payload and apply a minimum trait count threshold (e.g., more than two traits) as a secondary qualification signal. The original Customer.io userId is stored in a custom field cio_user_id__c on both Lead and Contact for cross-system reconciliation.
Customer.io
Company (Custom Object)
Microsoft Dynamics 365 Sales
Account
1:1Customer.io Companies stored as object_type_id namespaces map to Dynamics 365 Account. The company name maps to Account Name; domain maps to Website; city and country map to Address fields. If the Customer.io Company has a relationship to a Person via the group() call, we create the Account first, then resolve the AccountId lookup when importing the Contact. If multiple Customer.io Persons reference the same Company object, we deduplicate on Company ID to create one Account.
Customer.io
Custom Event
Microsoft Dynamics 365 Sales
Custom Event Entity (Dataverse)
1:1Customer.io events created via track() have no direct Dynamics 365 equivalent because Sales does not have a native event store. We pre-create a Dataverse custom entity (e.g., cio_event) with fields for event_name, event_timestamp, user_id (lookup to Contact), and a properties JSON column or individual attribute fields for the most common event property keys. We export the full event schema during scoping, map property keys that appear in more than 10 percent of events to named columns, and store the remainder in a JSON properties field. Events are the highest-volume object in a Customer.io migration and are batched in chunks of 5,000 records during import.
Customer.io
Trait (attribute)
Microsoft Dynamics 365 Sales
Contact Field or Custom Field
1:1Customer.io traits set via identify() migrate to typed Dynamics 365 Contact fields. String traits map to Single Line of Text, boolean traits to Two Options, date traits to Date and Time, numeric traits to Decimal or Whole Number, and array traits to Multiple Lines of Text (JSON serialized) or a custom multi-select field depending on the customer's preference. Traits with more than 10 unique values across the dataset map to Option Set fields. We flag any trait with a null rate above 80 percent so the customer can decide whether the field is worth migrating.
Customer.io
Segment
Microsoft Dynamics 365 Sales
Static View or Dynamic List
lossyCustomer.io Segments are dynamic audience definitions with rule-based inclusion criteria (trait conditions, event conditions, membership time). We export the full segment rule set as a structured JSON document and translate it into a Dynamics 365 Advanced Find fetchXML query or a Power Automate flow that rebuilds the segment membership on a schedule. Segments do not migrate as active audience data; they migrate as rule documentation for the customer's admin to implement in Dynamics 365.
Customer.io
Campaign / Journey
Microsoft Dynamics 365 Sales
Campaign (documentation only)
lossyCustomer.io Journeys and Campaigns contain entry triggers, branching conditions, wait steps, and multi-channel message actions that have no direct Microsoft Dynamics 365 Sales equivalent. Sales Cloud has a Campaign object for tracking marketing campaign membership but no native Journey builder. We export the Journey structure as a written document including trigger type, step sequence, channel per step, and condition branches. The customer's admin rebuilds the campaign logic in Dynamics 365 Customer Insights - Journeys, Power Automate, or a third-party marketing tool.
Customer.io
Broadcast
Microsoft Dynamics 365 Sales
Campaign
1:1Customer.io one-time Broadcasts map to Dynamics 365 Campaign records for tracking purposes. Broadcast name becomes Campaign Name; target segment is documented as Campaign Type and intended audience in a custom field. Active broadcast history (send timestamp, recipient count) migrates as Campaign Member records with Member Status set to Responder or Sent. Broadcast content does not migrate as a reusable template.
Customer.io
Custom Object (arbitrary type)
Microsoft Dynamics 365 Sales
Custom Entity (Dataverse)
1:1Customer.io arbitrary Custom Objects stored under object_type_id namespaces map to Dataverse custom entities. We pre-create the destination schema including all custom fields, attribute types, and lookup relationships to standard entities (Contact, Account, Opportunity) before data import. Custom object naming in Dynamics 365 uses the New_ prefix for custom entities; we preserve the original Customer.io object name in a custom field for reference. Lookup relationships between custom objects are resolved in dependency order during import.
Customer.io
Transactional Message
Microsoft Dynamics 365 Sales
Email Template (documentation)
lossyCustomer.io transactional message templates (receipts, password resets, order confirmations) migrate as documented email content rather than active templates because Dynamics 365 does not have a transactional messaging channel. We export template name, subject line, body content (HTML), and liquid variable mappings. The customer's admin uses this documentation to rebuild templates in Dynamics 365 Email Templates, Power Automate email actions, or the destination transactional email provider.
Customer.io
Message Delivery Log
Microsoft Dynamics 365 Sales
Campaign Member Status
1:1Customer.io delivery status data (sent, delivered, bounced, undeliverable) migrates to Dynamics 365 Campaign Member records with the corresponding Member Status value. Undeliverable statuses are stored in a custom field cio_delivery_status__c on the Campaign Member to preserve the full delivery state without overwriting the standard status field. Compliance and audit records from Customer.io message logs are flagged for the customer's legal team to review against their data retention policy.
| Customer.io | Microsoft Dynamics 365 Sales | Compatibility | |
|---|---|---|---|
| Person (Profile) | Contact or Lead (split required)1:many | Fully supported | |
| Company (Custom Object) | Account1:1 | Fully supported | |
| Custom Event | Custom Event Entity (Dataverse)1:1 | Fully supported | |
| Trait (attribute) | Contact Field or Custom Field1:1 | Fully supported | |
| Segment | Static View or Dynamic Listlossy | Fully supported | |
| Campaign / Journey | Campaign (documentation only)lossy | Fully supported | |
| Broadcast | Campaign1:1 | Fully supported | |
| Custom Object (arbitrary type) | Custom Entity (Dataverse)1:1 | Fully supported | |
| Transactional Message | Email Template (documentation)lossy | Fully supported | |
| Message Delivery Log | Campaign Member Status1:1 | Fully supported |
Gotchas + challenges
Platform-specific issues from each side, plus the pair-specific challenges that don't show up on either platform's page on its own.
Customer.io gotchas
Deleted profiles still count toward billing for the remainder of the cycle
Push migration requires a new app version with the Customer.io SDK
Broadcast API rate limit constrains high-volume re-imports
Inactive user profiles inflate monthly billing with no campaign benefit
Transactional message content may be redacted in stored logs
Microsoft Dynamics 365 Sales gotchas
Professional tier 15-table custom table limit blocks migrations
October 2024 pricing increase applies at renewal for all customers
Custom fields must be created in the UI before API writes
Power Platform request limits apply to bulk migrations
Activity records orphaned to inactive owners fail silently
Pair-specific challenges
Migration approach
Discovery and source audit
We audit the Customer.io workspace across object types (People, Companies, Custom Objects), event schemas (all track() call names and top property keys), active Journeys and Workflows, Broadcast history, and delivery log scope. We pair this with a Dynamics 365 environment audit: existing entities, custom fields, security roles, and whether Customer Insights - Journeys is licensed. The discovery output is a written migration scope covering record counts per object, event history volume, a preliminary object mapping, and a Lead-Contact split rule proposal based on the customer's email capture rate.
Schema design and custom entity provisioning
We design the destination Dynamics 365 schema on Dataverse. This includes pre-creating custom entities for Customer.io event history (cio_event), anonymous event records (cio_anonymous_event), and any Custom Object namespaces that have no standard Dynamics 365 equivalent. We define custom fields on Contact and Account to carry Customer.io identifiers (cio_user_id__c, cio_company_id__c) and to preserve original Lifecycle Stage values. Schema is deployed into a Dynamics 365 Sandbox environment first for validation before any data moves.
Sandbox migration and reconciliation
We run a full migration into the Dynamics 365 Sandbox using representative data volume. The customer's RevOps or IT lead reconciles record counts (Contacts in, Leads in, Accounts in, event records in), spot-checks 25-50 records against the Customer.io source, and reviews the anonymous-profile handling decision. Schema corrections, field type adjustments, and split rule refinements happen here. No production data moves until the sandbox sign-off is received from the customer's project owner.
Event schema profiling and audience mapping
We analyze the full Customer.io event schema to identify the most common property keys across all track() events. Properties appearing in more than 10 percent of events are mapped to named columns on the custom event entity; less common properties are serialized into a JSON properties column. We also export segment rule sets as structured JSON documents for the customer's admin to implement as Power Automate flows or Advanced Find views post-migration.
Production migration in dependency order
We run production migration in record-dependency order: Accounts (from Customer.io Companies), Contacts and Leads (with the anonymous split applied and AccountId resolved), custom entities (event history, Custom Objects), then message delivery history as Campaign Member records. Each phase emits a row-count reconciliation report. We use Dataverse bulk import with batch chunking and exponential backoff on throttling responses. During cutover we freeze Customer.io writes, run a final delta migration of any records modified during the migration window, then hand off Dynamics 365 as the system of record.
Cutover, validation, and rebuild handoff
We freeze the Customer.io integration during cutover, validate record counts in Dynamics 365 against the source, and confirm the anonymous-profile handling matches the signed-off split rule. We deliver the Journey and Workflow inventory document, the segment rule documentation, and the transactional template content export. We support a one-week hypercare window for reconciliation issues raised by the customer's team. We do not rebuild Customer.io Workflows or Journeys as Power Automate flows inside the migration scope; that work is documented and handed off as a separate rebuild task.
Platform deep dives
Customer.io
Source
Strengths
Weaknesses
Microsoft Dynamics 365 Sales
Destination
Strengths
Weaknesses
Complexity grading
Standard CRM migration. 1 of 8 objects need a mapping; the rest are 1:1.
Overall complexity
Standard migration
Derived from compatibility, mapping clarity, API constraints, and data volume across Customer.io and Microsoft Dynamics 365 Sales .
Object compatibility
1 of 8 objects need a mapping; the rest are 1:1.
Field mapping clarity
Field mapping is derived from defaults — final spec confirmed during the sample migration.
Timeline complexity
8-object category — typical timelines run 2–7 days end-to-end.
API constraints
Customer.io: Not publicly documented for general API; transactional broadcast endpoint capped at 1 request per 10 seconds.
Data volume sensitivity
Customer.io exposes a bulk API — large-volume migrations stream efficiently.
Estimator
Rule-based pricing — no per-record fees, no manual quotes. Migrations over 2M records are scoped individually.
Step 1
Pick a category, then your source and destination platforms.
Category
FAQ
Answers to the questions buyers ask most during Customer.io to Microsoft Dynamics 365 Sales migration scoping. Not seeing yours? Book a call.
Walk through your Customer.io to Microsoft Dynamics 365 Sales migration with a real engineer — 30 minutes, free, written quote within 24 hours.
Book a free 30 minute consultationAdjacent paths
Other ways to leave Customer.io
Other ways to arrive at Microsoft Dynamics 365 Sales
Ready when you are
Tell us record counts and timeline. We'll come back with a written quote inside 1 business day — no commitment, no sales pitch.