CRM migration
Field-level mapping, validation, and rollback between Freshmarketer and Odoo CRM. We move data and schema; workflows are rebuilt natively in Odoo CRM.
Freshmarketer
Source
Odoo CRM
Destination
Compatibility
12 of 15
objects map 1:1 between Freshmarketer and Odoo CRM.
Complexity
BStandard
Timeline
8-12 weeks
Overview
Moving from Freshmarketer to Odoo CRM restructures the contact model and introduces a fundamentally different automation paradigm. Freshmarketer keeps Contacts and Companies as separate linked objects; Odoo uses res.partner as a unified record that holds both individual and organizational data. We create a partner record per Freshmarketer contact, map the org_contact_id to pull in company-level data, and preserve the original Lifecycle Stage in a custom field on the res.partner record. Deals map to crm.lead with pipeline stage names and team assignments pre-configured. Email and call activity history migrates into Odoo's mail.message and crm.activity tables. Journeys (marketing automation workflows) cannot migrate as executable logic; we deliver a written automation inventory with rebuild recommendations for Odoo's crm_lead_plan or Studio automations. We do not migrate Forms, Landing Pages, or Reports as these require rebuild in Odoo Studio or a third-party form builder.
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 Freshmarketer 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.
Freshmarketer
Contact
Odoo CRM
res.partner
1:1Freshmarketer Contact maps to Odoo res.partner. The contact's individual fields (name, email, phone, address) transfer directly. The linked Freshmarketer Company is preserved in a custom field parent_partner_name__c and merged by looking up org_contact_id. Lifecycle Stage from Freshmarketer migrates as a custom char field lifecycle_stage__c on the partner record for audit continuity. Email address is the dedupe key; Odoo will merge on email match, which must be anticipated during scoping.
Freshmarketer
Company
Odoo CRM
res.partner (organization)
1:1Freshmarketer Company maps to a separate res.partner record with partner_type set to company. The org_contact_id from Freshmarketer contacts links individual partner records to the organization partner via parent_id. We create organization partners first so that the parent_id lookup is satisfied at the time of individual partner import. Company domain, industry, size, and address fields map to equivalent res.partner fields.
Freshmarketer
Deal
Odoo CRM
crm.lead
1:1Freshmarketer Deal maps to Odoo crm.lead. Pipeline name and stage name map to Odoo's crm.stage sequence; stage order must be configured in Odoo before Deals are imported. Deal amount maps to expected_revenue on the lead; close date maps to date_deadline. Owner from Freshmarketer resolves to Odoo user_id via email match. Custom deal fields migrate as custom_char, custom_date, or custom_selection fields on crm.lead.
Freshmarketer
Activity: Email
Odoo CRM
mail.message
1:1Freshmarketer email engagement logs migrate to Odoo mail.message records linked via res.model = crm.lead and res_id = lead_id to the target lead. Email body, subject, timestamp, and sender-recipient details transfer to mail.message body, subject, date, and author_id. Odoo does not support a separate activity timeline object for emails the way Freshmarketer does; all email history consolidates into the lead's chatter thread via mail.message.
Freshmarketer
Activity: Call
Odoo CRM
crm.activity
1:1Freshmarketer call engagement logs migrate to Odoo crm.activity records with activity_type_id set to the Call activity type. Call duration, disposition notes, and timestamp transfer to crm.activity duration, note, and date fields. Activity is linked to the target crm.lead via res_id. We pre-create the Call activity type in Odoo if it does not exist in the target database.
Freshmarketer
Activity: Meeting
Odoo CRM
calendar.event
1:1Freshmarketer meeting engagements migrate to Odoo calendar.event records with linked crm.lead via calendar.event.res_id and res_model = crm.lead. Meeting title, start datetime, end datetime, location, and description transfer to equivalent calendar.event fields. Attendee mapping links to res.partner records via event.partner_ids.
Freshmarketer
Activity: Note
Odoo CRM
mail.message
1:1Freshmarketer note engagements migrate to Odoo mail.message records with message_type = notification and subtype = note. Note body transfers to mail.message body. Notes are linked to the target res.partner (for individual contacts) or crm.lead (for deal-linked notes) via res_model and res_id. The original Freshmarketer engagement timestamp is preserved in a custom field original_date__c on the message.
Freshmarketer
Activity: Task
Odoo CRM
crm.activity
1:1Freshmarketer task engagements map to Odoo crm.activity records with activity_type_id = Task. Task title, description, due date, status, and priority transfer to crm.activity name, note, date_deadline, state, and priority. Owner assignment migrates by resolving the Freshmarketer owner email to an Odoo user_id. Completed tasks set state = done.
Freshmarketer
Tag
Odoo CRM
crm.tag
1:1Freshmarketer tags migrate as crm.tag records in Odoo. Tags are applied to crm.lead records via the crm.lead.tag_ids many2many relationship. Tags stored as multi-checkbox custom properties on Freshmarketer contacts migrate as individual tag records and are re-applied via tag_ids on the mapped res.partner. No tag hierarchy exists in either platform, so no structural transformation is required.
Freshmarketer
Custom Field
Odoo CRM
Custom field on res.partner or crm.lead
1:1Custom fields on Freshmarketer contacts, companies, and deals require explicit per-field mapping against Odoo custom field definitions. Field type differences (dropdown vs. text, date formats, multi-select arrays) must be resolved during the transform phase before import. We pre-create all custom fields in Odoo via XML data or the Settings UI before any data loads. Multi-select values from Freshmarketer arrays flatten to a comma-separated string in Odoo char fields unless a custom many2many field is configured.
Freshmarketer
Marketing Contacts
Odoo CRM
Custom field on res.partner
lossyFreshmarketer's Marketing Contacts billing concept has no Odoo equivalent. We flag every contact that was enrolled in an active email, SMS, or WhatsApp campaign at cutover time and write the enrollment state to a custom boolean field is_marketing_contact__c on the res.partner record. This preserves the billing-flag data for any downstream marketing re-implementation without incurring Odoo licensing costs. We do not migrate Marketing Contacts as a separate object because Odoo does not have a billing-tier concept for contacts.
Freshmarketer
Segment
Odoo CRM
Static crm.tag group or custom many2many
lossyFreshmarketer Segments (audience filtering rules) have no direct Odoo equivalent. We map segment criteria to Odoo static tag groups or create a custom many2many field segment_ids on res.partner to hold segment membership. Dynamic audience logic (segment rules that auto-update) cannot be reproduced in Odoo's standard CRM without custom development; we document the segment rules in a written reference and the customer decides whether to rebuild as tags, static lists, or a custom module.
Freshmarketer
Pipeline
Odoo CRM
crm.stage + crm.team
lossyFreshmarketer pipeline and stage names map to an ordered crm.stage sequence in Odoo CRM. Stages are created in the sequence matching Freshmarketer's stage order before any Deal data is imported. Each stage is assigned to the relevant crm.team. Stage probability percentages from Freshmarketer are stored in a custom float field stage_probability__c on crm.stage if the customer wants to preserve probability modeling. Pipeline-level reporting groups in Freshmarketer map to Odoo crm.team groupings.
Freshmarketer
User
Odoo CRM
res.users
1:1Freshmarketer Users (owners assigned to contacts, companies, and deals) map to Odoo res.users by email address lookup. We extract all distinct owner emails from Freshmarketer records and match against the destination Odoo user directory. Any owner without a matching Odoo user is held in a reconciliation queue for the customer's admin to provision before the Deals import phase. Active vs. inactive status on the Freshmarketer owner does not block import; we map to an active Odoo user regardless of status source.
Freshmarketer
Attachment
Odoo CRM
ir.attachment
1:1File attachments on Freshmarketer contacts, deals, and activities are exported to a file store (S3 or local) and loaded into Odoo ir.attachment records. Each ir.attachment is linked via res_model and res_id to the target res.partner or crm.lead record. Attachment filename, MIME type, and binary content transfer directly. Odoo stores attachments in the database by default; large attachment volumes may require Odoo file storage configuration to avoid database bloat.
| Freshmarketer | Odoo CRM | Compatibility | |
|---|---|---|---|
| Contact | res.partner1:1 | Fully supported | |
| Company | res.partner (organization)1:1 | Fully supported | |
| Deal | crm.lead1:1 | Fully supported | |
| Activity: Email | mail.message1:1 | Fully supported | |
| Activity: Call | crm.activity1:1 | Fully supported | |
| Activity: Meeting | calendar.event1:1 | Fully supported | |
| Activity: Note | mail.message1:1 | Fully supported | |
| Activity: Task | crm.activity1:1 | Fully supported | |
| Tag | crm.tag1:1 | Fully supported | |
| Custom Field | Custom field on res.partner or crm.lead1:1 | Fully supported | |
| Marketing Contacts | Custom field on res.partnerlossy | Mapping required | |
| Segment | Static crm.tag group or custom many2manylossy | Fully supported | |
| Pipeline | crm.stage + crm.teamlossy | Fully supported | |
| User | res.users1:1 | Fully supported | |
| Attachment | ir.attachment1: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.
Freshmarketer gotchas
Marketing Contacts billing model affects migration scoping
Email-based contact merging during Freshsales Suite migration
Journeys stop executing post-migration with no auto-resume
API rate limit of 1000 requests per hour caps migration throughput
Outgoing emails disabled after migration require manual re-enablement
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 scoping
We audit the source Freshmarketer portal across plan tier, marketing contact count, custom contact and deal fields, active pipeline and stage count, active Journeys, engagement volume per type (emails, calls, meetings, tasks), and tag usage. We pair this with a destination Odoo edition review: Community (free, self-hosted or cloud) covers most CRM migrations; Standard plan ($30/user/mo) adds extra features and support SLAs. The discovery output is a written migration scope with object counts, custom field inventory, Journey list, and Odoo edition recommendation.
Schema design and stage configuration
We design the destination Odoo CRM schema. This includes creating custom fields on res.partner (lifecycle_stage__c, original_freshmarketer_id__c, is_marketing_contact__c) and crm.lead (custom deal fields from Freshmarketer), ordering the crm.stage pipeline sequence to match Freshmarketer stage order, assigning stages to crm.team records, and configuring crm.tag entries for tag migration. Schema is deployed into a sandbox Odoo database first for validation before production migration begins.
Sandbox migration and reconciliation
We run a full migration into the Odoo sandbox environment using production-like data volumes. The customer's Odoo admin reconciles record counts (partners in, leads in, activity records in), spot-checks 25-50 records against the Freshmarketer source for field accuracy, and verifies that the pipeline stage ordering matches the expected deal progression. Any field mapping corrections, stage ordering issues, or custom field type conflicts are resolved here. Admin sign-off is required before the production migration date is confirmed.
Owner and user provisioning
We extract every distinct Freshmarketer owner email referenced on contacts, companies, and deals and match against the Odoo destination res.users table by email. Any owner without a matching Odoo user is held in a reconciliation queue. The customer's Odoo admin provisions missing users (active or inactive based on whether the original Freshmarketer user is still active) before production migration resumes. User provisioning must complete before any record import because OwnerId references on crm.lead are required fields.
Production migration in dependency order
We run production migration in dependency order: organization res.partner records (from Freshmarketer Companies) first, then individual res.partner records (from Freshmarketer Contacts with parent_id resolved to the organization partner), then crm.lead records (from Freshmarketer Deals with user_id resolved via the owner lookup), then mail.message records (email activity), then crm.activity records (call and task activity), then calendar.event records (meeting activity). Custom fields, tags, and segment membership load as final phases. Each phase emits a row-count reconciliation report before the next phase begins.
Cutover, validation, and Journey rebuild handoff
We freeze Freshmarketer writes during cutover, run a final delta migration of records modified during the migration window, then enable Odoo as the system of record. We deliver the Journeys automation inventory document with trigger, conditions, enrolled-contact counts, and rebuild recommendation per Journey. We support a one-week hypercare window where we resolve any data reconciliation issues raised by the customer's team. We do not rebuild Freshmarketer Journeys as Odoo automations inside the migration scope; that is a separate engagement or an internal admin task.
Platform deep dives
Freshmarketer
Source
Strengths
Weaknesses
Odoo CRM
Destination
Strengths
Weaknesses
Complexity grading
Standard CRM migration. 2 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 Freshmarketer and Odoo CRM.
Object compatibility
2 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
Freshmarketer: 1000 requests per hour per account.
Data volume sensitivity
Freshmarketer doesn't expose a bulk API — REST + parallelization used for high-volume runs.
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 Freshmarketer to Odoo CRM migration scoping. Not seeing yours? Book a call.
Walk through your Freshmarketer 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 Freshmarketer
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.