CRM migration
Field-level mapping, validation, and rollback between Dynamics 365 Marketing and Odoo CRM. We move data and schema; workflows are rebuilt natively in Odoo CRM.
Dynamics 365 Marketing
Source
Odoo CRM
Destination
Compatibility
9 of 14
objects map 1:1 between Dynamics 365 Marketing and Odoo CRM.
Complexity
BStandard
Timeline
4-8 weeks
Overview
Moving from Dynamics 365 Marketing to Odoo CRM is a dual-layer migration. Dynamics 365 Marketing sits on Dataverse with CRM data in standard tables (msdyn_contact, Account, msdyn_opportunity) and marketing assets in separate msdynmkt_* tables (email templates, Customer Journeys, Segments). Odoo CRM has no native marketing automation layer, so email templates, Journey definitions, and segment memberships must be preserved as documentation for rebuild rather than migrated as live assets. We extract CRM data from Dataverse via the REST API, extract marketing-layer assets separately from msdynmkt_* tables, map Dynamics Leads to Odoo Contacts using lifecycle stage as a tag, and preserve the full activity timeline (calls, emails, meetings, tasks) as Odoo Mail Activity records. Marketing contact billing flags, journey trigger conditions, and consent records are stored as custom Odoo fields for future segmentation. Power Automate flows, Customer Insights segments, and Journey logic do not migrate; we deliver a written inventory of every marketing asset requiring rebuild in your chosen replacement marketing platform.
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.
Why teams make this switch
Leaving
What's pushing teams away
Choosing
What's pulling them in
Object mapping
Each row shows how a Dynamics 365 Marketing object lands in Odoo CRM, including any object-level transformations, lookup resolution, or schema-design dependencies.
Typical mapping — final map is confirmed during the sample migration step.
Dynamics 365 Marketing
Contact (msdyn_contact)
Odoo CRM
Contact (res.partner)
1:1Dynamics 365 Contact records (msdyn_contact) map directly to Odoo res.partner. Standard fields (name, email, phone, address) use straightforward field-to-field mapping. We preserve the original lifecycle stage (subscriber, lead, MQL, SQL, customer) as an Odoo tag on the res.partner record for segmentation reference. The Contact-to-Account relationship resolves via the parent_id lookup at migration time after Account records are loaded first.
Dynamics 365 Marketing
Lead
Odoo CRM
Contact (res.partner)
1:manyDynamics 365 Leads (unqualified prospects that have not been converted to Contacts) merge into Odoo res.partner because Odoo CRM does not have a separate Lead object at the Contact layer. The original Lead_Status and lead score from Dynamics migrate as tags on the res.partner record. If the customer requires a separate unqualified-pipeline view, we configure Odoo's CRM pipeline with an initial stage named Unqualified/Legal to which these records are assigned at import time.
Dynamics 365 Marketing
Account
Odoo CRM
Company (res.partner, type=company)
1:1Dynamics 365 Account records map to Odoo res.partner with type=company. The Account name becomes the company name, and the domain becomes the website field. Account hierarchies (parent-account structures) map to Odoo's contact hierarchy via the parent_id field on res.partner. Industry, address, and custom account fields migrate as Odoo custom fields or tags depending on field cardinality.
Dynamics 365 Marketing
Opportunity (msdyn_opportunity)
Odoo CRM
Opportunity (crm.lead)
1:1Dynamics 365 Opportunities from the underlying Dataverse CRM layer (msdyn_opportunity) map to Odoo crm.lead. Pipeline stage from Dynamics maps to Odoo's stage_id within the CRM pipeline view. Estimated close date, amount, probability, and owner assignment migrate directly. The opportunity-to-contact and opportunity-to-account lookups resolve via the Account and Contact records already imported. We configure Odoo's CRM stages to match the Dynamics pipeline stages before import.
Dynamics 365 Marketing
Marketing Email (msdynmkt_email)
Odoo CRM
Email Template (mail.template)
lossyDynamics 365 Marketing email templates (msdynmkt_email) contain HTML body, subject line, sender details, and preheader text. Odoo CRM does not have a native marketing email template store separate from its transactional email templates (mail.template). We preserve the email subject, HTML body, and sender address as a custom field on Odoo's mail.template model so that the customer's marketing team has the content documented for rebuild in their chosen marketing automation platform. The automated send logic (Journey triggers) does not migrate and is documented separately.
Dynamics 365 Marketing
Customer Journey (msdynmkt_journey)
Odoo CRM
CRM Pipeline Stage (crm.lead)
lossyCustomer Journey definitions in Dynamics 365 Marketing (msdynmkt_journey) include trigger conditions, branch logic, wait delays, and action steps. Odoo CRM has no Journey or marketing automation equivalent. We extract the Journey configuration (trigger type, conditions, steps, and step order) and preserve it as a document in the customer's migration handoff package. The customer's marketing team uses this as a specification to rebuild Journey logic in Marketo, Mailchimp, HubSpot Marketing, or another marketing automation platform. We do not migrate Journey logic as executable code.
Dynamics 365 Marketing
Segment (Customer Insights - Data)
Odoo CRM
Contact Group (crm.lead.group)
1:1Customer Insights segments are stored in the Customer Insights - Data service, which is separate from the core Dataverse CRM database. We execute a separate export pass for segment definitions and membership data. Static segments (explicit member lists) map to Odoo crm.lead.group records with members linked to the corresponding res.partner records. Dynamic segments (criteria-based) cannot be replicated in Odoo CRM and are documented with their full criteria expression for rebuild in a marketing automation platform. Segment memberships are imported after all contact records are present in Odoo to avoid orphaned references.
Dynamics 365 Marketing
Custom Entity (Dataverse managed solution)
Odoo CRM
Custom Field or Studio Model
1:1Custom entities created within a Dataverse managed solution require the customer to provide the managed solution ZIP or schema export from the Configuration Migration Tool before we can map them. We do not infer custom entity structure from UI exports because UI exports do not capture relationship metadata, field security profiles, or managed property settings. Custom entities map to Odoo custom fields on res.partner, crm.lead, or as separate Odoo Studio models depending on the entity's structure and lookup relationships.
Dynamics 365 Marketing
Activity: Email, Call, Meeting, Task
Odoo CRM
Mail Activity (mail.activity)
1:1Dynamics 365 ActivityPointer records (Email, Task, PhoneCall, Appointment) map to Odoo mail.activity with the activity_type field set to email, call, meeting, or pending. The activity subject, note, and date migrate directly. The regarding object lookup (objectid and objecttypecode) resolves to the migrated res.partner or crm.lead record. Activity owner assignments migrate as Odoo user assignments. We process activities in a separate pass after all parent contact and opportunity records are present.
Dynamics 365 Marketing
Annotation (Attachments)
Odoo CRM
Attachment (ir.attachment)
1:1Dynamics 365 Annotations (notes with file attachments) are exported individually with the objectid and objecttypecode preserved. We re-associate attachments with their parent record in Odoo via ir.attachment with res_model=res.partner or crm.lead and res_id pointing to the migrated record. We handle annotations in a separate pass after the parent records are loaded. The original filename and any inline note body migrate as Odoo attachment name and description.
Dynamics 365 Marketing
Marketing List
Odoo CRM
Group (crm.lead.group)
lossyDynamics 365 Marketing Lists contain member records with list-type (static or dynamic) and are associated with Campaigns. Odoo CRM does not have a native Marketing List equivalent. Static Marketing List membership is preserved as Odoo crm.lead.group records with member links to the corresponding res.partner records. Dynamic Marketing Lists (query-based) are documented with their original query criteria for rebuild as a segment in the customer's chosen marketing automation platform.
Dynamics 365 Marketing
Campaign and Campaign Activity
Odoo CRM
Campaign (utm.campaign)
1:1Dynamics 365 Campaigns and Campaign Activities (the legacy marketing model) map to Odoo utm.campaign with the campaign name, status, budget, and dates preserved. Campaign Activities are documented as campaign milestones or tasks within the Odoo Campaign because Odoo does not have a separate Campaign Activity object. The association between Campaign and Marketing List members is preserved in the Group migration. Microsoft Dynamics campaign response records are documented as campaign tags in Odoo.
Dynamics 365 Marketing
User and Owner
Odoo CRM
User (res.users)
1:1Dynamics 365 systemuser records and owner assignments on CRM records map to Odoo res.users. We resolve owners by email match against the destination Odoo user list. Any Dynamics Owner without a matching Odoo user is held in a reconciliation queue for the customer's admin to provision before record import resumes. The Dynamics user role (salesperson, marketing manager, administrator) migrates as a tag on the res.users record for access-control planning in Odoo.
Dynamics 365 Marketing
Marketing Contact Billing Flag
Odoo CRM
Custom Field on Contact
lossyDynamics 365 Marketing Contact billing is triggered at the tenant level based on contact record properties. The marketing contact flag has no Odoo CRM analog because Odoo does not have a native marketing automation billing model. We preserve the original billing eligibility status as a custom field on res.partner so that if the customer later integrates a marketing automation tool (Marketo, Mailchimp, HubSpot), the segmentation data is already present and does not require a second export from Dynamics 365.
| Dynamics 365 Marketing | Odoo CRM | Compatibility | |
|---|---|---|---|
| Contact (msdyn_contact) | Contact (res.partner)1:1 | Fully supported | |
| Lead | Contact (res.partner)1:many | Fully supported | |
| Account | Company (res.partner, type=company)1:1 | Fully supported | |
| Opportunity (msdyn_opportunity) | Opportunity (crm.lead)1:1 | Fully supported | |
| Marketing Email (msdynmkt_email) | Email Template (mail.template)lossy | Fully supported | |
| Customer Journey (msdynmkt_journey) | CRM Pipeline Stage (crm.lead)lossy | Fully supported | |
| Segment (Customer Insights - Data) | Contact Group (crm.lead.group)1:1 | Fully supported | |
| Custom Entity (Dataverse managed solution) | Custom Field or Studio Model1:1 | Fully supported | |
| Activity: Email, Call, Meeting, Task | Mail Activity (mail.activity)1:1 | Fully supported | |
| Annotation (Attachments) | Attachment (ir.attachment)1:1 | Fully supported | |
| Marketing List | Group (crm.lead.group)lossy | Fully supported | |
| Campaign and Campaign Activity | Campaign (utm.campaign)1:1 | Fully supported | |
| User and Owner | User (res.users)1:1 | Fully supported | |
| Marketing Contact Billing Flag | Custom Field on Contactlossy | 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.
Dynamics 365 Marketing gotchas
Marketing Contact billing triggers on record import
Configuration Migration Tool does not migrate high-volume transactional data
Customer Insights segments are stored separately from Dataverse CRM records
Marketing Lists and Campaign Activities have legacy schema dependencies
Custom entities require a managed solution schema, not a UI export
Odoo CRM gotchas
Odoo.sh version gating blocks assisted migrations from trial
Enterprise modules fail to install on Community after database restore
Custom module view inheritance breaks between Odoo major versions
Custom fields risk losing their application context on Community
API access for Community is gated behind the Custom Plan
Pair-specific challenges
Migration approach
Discovery and environment audit
We audit the customer's Dynamics 365 Marketing environment across the Dataverse CRM layer (Contacts, Accounts, Opportunities, Leads, Activities, Custom Entities via managed solution), the marketing layer (msdynmkt_email, msdynmkt_journey, Customer Insights segments), and the Power Automate flows in use. We extract record counts, schema definitions, active user count, and engagement volume. The discovery output is a written migration scope that separates CRM data (which migrates fully) from marketing automation assets (which we document for rebuild) and identifies any Odoo-edition or hosting requirement implications.
Odoo staging setup and schema design
We provision an Odoo staging environment (Odoo.sh or self-hosted per the customer's preference) and install the CRM app. We configure the CRM pipeline stages to match the Dynamics pipeline stages, create custom fields on res.partner for lifecycle stage, lead score, and marketing billing flag preservation, and define the crm.lead.group records that will receive Marketing List and Segment data. We work with the customer's Odoo admin to define access rights and sales team structures before any data is loaded.
Marketing asset documentation pass
Before any CRM data moves, we execute a separate documentation pass for marketing assets that cannot migrate as live records: email templates (HTML body, subject, sender), Customer Journey definitions (trigger type, conditions, step sequences), segment criteria, and consent records. We deliver these as a structured handoff document that the customer's marketing team uses to rebuild the marketing automation layer in their chosen replacement platform. This pass ensures that the marketing team has a complete specification before Odoo goes live, rather than discovering the gap at cutover.
CRM data extraction from Dataverse
We extract CRM records from the Dataverse REST API in dependency order: Accounts first (for the parent lookup), then Contacts (with AccountId resolved), then Leads (mapped to Contacts with a lifecycle tag), then Opportunities (with AccountId and OwnerId resolved), then Activity history (Email, Task, PhoneCall, Appointment as mail.activity records), then Attachments (as ir.attachment with res_model and res_id set to the parent record). We use batch chunking and exponential backoff on Dataverse API rate limit responses. Custom entity data is extracted after the standard entity pass, using the schema from the managed solution ZIP provided by the customer.
Data transformation and Odoo import
We transform extracted records using field-type mapping (Dynamics Dataverse types to Odoo field types), resolve all lookup references to parent records already loaded in Odoo, apply the Lead-to-Contact merge rule using lifecycle stage as the classification tag, and load records into Odoo via the XML-RPC API with batch sizes appropriate to Odoo's import throttle settings. Owner assignments are resolved by email match against Odoo res.users; any unmatched owners are held in a reconciliation queue for the customer to provision before the next phase begins.
Validation and cutover
The customer reconciles record counts in Odoo against the Dataverse source (Accounts in, Contacts in, Opportunities in, Activities in) and spot-checks 25-50 records for data accuracy. We run a final delta migration to capture any records modified in Dynamics during the migration window. We enable Odoo as the system of record, deliver the marketing asset handoff document, and open a one-week hypercare window for reconciliation issues. Power Automate flows, Customer Insights segments, and Journey logic are handed off separately; we do not rebuild these inside the migration scope.
Platform deep dives
Dynamics 365 Marketing
Source
Strengths
Weaknesses
Odoo CRM
Destination
Strengths
Weaknesses
Complexity grading
Standard CRM migration. All 8 core objects map 1:1 between Dynamics 365 Marketing and Odoo CRM.
Overall complexity
Standard migration
Derived from compatibility, mapping clarity, API constraints, and data volume across Dynamics 365 Marketing and Odoo CRM.
Object compatibility
All 8 core objects map 1:1 between Dynamics 365 Marketing and Odoo CRM.
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
Dynamics 365 Marketing: Dataverse Web API enforces organization-level throttling; specific limits vary by workload and are not publicly documented at fixed thresholds.
Data volume sensitivity
Dynamics 365 Marketing 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 Dynamics 365 Marketing to Odoo CRM migration scoping. Not seeing yours? Book a call.
Walk through your Dynamics 365 Marketing to Odoo CRM migration with a real engineer — 30 minutes, free, written quote within 24 hours.
Book a free 30 minute consultationAdjacent paths
Other ways to leave Dynamics 365 Marketing
Other ways to arrive at Odoo CRM
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.