CRM migration
Field-level mapping, validation, and rollback between Customer.io and Odoo CRM. We move data and schema; workflows are rebuilt natively in Odoo CRM.
Customer.io
Source
Odoo CRM
Destination
Compatibility
7 of 12
objects map 1:1 between Customer.io and Odoo CRM.
Complexity
BStandard
Timeline
3-5 weeks
Overview
Customer.io is an event-driven behavioral messaging platform built around People profiles, custom events, and Campaign-driven audience segmentation. Odoo CRM is an ERP-integrated sales CRM built around Contacts, Leads, Opportunities, and pipeline stages. These are different data models by design, and the migration requires a deliberate translation layer rather than a direct record copy. We export People, their traits, and their full event timeline from Customer.io, map profile attributes to Odoo Contact fields, represent event history as Odoo activity log entries (calls, emails, meetings, notes), and translate segment membership into Contact tags and Lead scoring fields. Campaign structures and Journey workflows do not migrate to Odoo because Odoo has no equivalent Campaign or Journey object. We deliver a written audit of every active Campaign and Segment with a recommended Odoo CRM configuration so your admin can rebuild the audience logic post-migration. Push notification setup requires a separate mobile SDK integration and 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.
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 Odoo CRM, including any object-level transformations, lookup resolution, or schema-design dependencies.
Typical mapping — final map is confirmed during the sample migration step.
Customer.io
People (Profiles)
Odoo CRM
Contact (res.partner)
1:1Customer.io People profiles map to Odoo res.partner records. The userId becomes partner_ref or the external ID field; email maps to email; name maps to name. Anonymous traits (city, country, plan tier) map to custom fields on res.partner that we create via Odoo Studio or XML data migration. The full trait JSON is preserved as a serialized field for compliance auditing. Active-to-inactive ratio is calculated during scoping and inactive profiles can be flagged as archived partners rather than imported as active records to keep the Odoo partner table clean.
Customer.io
Custom Events
Odoo CRM
CRM Activity Log (mail.activity)
1:manyCustomer.io event history has no direct Odoo equivalent, so we represent each event as a mail.activity record linked to the migrated Contact. Event name becomes activity.activity_type_id (or a custom activity type); event properties become the activity.note field in structured JSON; sentAt/receivedAt becomes activity.date_deadline and activity.create_date. This preserves the timeline and properties but loses the event-as-first-class-object granularity. Customers who rely heavily on event segmentation in Customer.io should rebuild that logic using Odoo Lead Automation rules and contact tags post-migration.
Customer.io
Segments
Odoo CRM
Tags (ir.exports.line) + Lead Scoring Fields
lossyCustomer.io dynamic Segments are rebuilt in Odoo as a combination of contact tags and custom Lead scoring fields. During migration we export each segment's rule criteria as a structured JSON object, then create equivalent Odoo tags (using the contacts_base module or res.partner.category). Segment criteria that rely on event conditions are translated into Odoo Lead Automation rules referencing the activity log entries created during event migration. Customers receive a Segment-to-Tag mapping document as part of the handoff.
Customer.io
Campaigns
Odoo CRM
CRM Pipeline Stage + Tag
lossyCustomer.io Campaigns do not have a native Odoo CRM equivalent because Odoo has no multi-step journey or campaign automation object. We export campaign structure (name, trigger type, entry conditions, channel assignments, wait steps) as a structured JSON document and map campaign entry to Odoo pipeline stage assignment or a Contact tag identifying the campaign source. The customer's Odoo admin rebuilds multi-step campaign logic using Odoo Lead Automation (crm.lead.automation) or Odoo Marketing (if licensed) post-migration.
Customer.io
Broadcasts
Odoo CRM
CRM Lead / Contact with Tag
1:1Historical Broadcast sends are represented in Odoo as Contact records tagged with the broadcast name, with a mail.message note recording the send timestamp and approximate audience size. Broadcast content and targeting criteria are exported as structured records in the broadcast audit document. API-triggered broadcast rate limits (1 request per 10 seconds on Customer.io) do not apply in Odoo; any automated send logic rebuilds as Odoo Lead Automation or a custom mail.mass_mailing configuration.
Customer.io
Custom Objects (Companies, Accounts)
Odoo CRM
res.partner (Company type)
1:1Customer.io Custom Objects with object_type_id = company or account map to Odoo res.partner records where is_company = True. The custom object ID becomes the external ID; custom fields on the object map to custom fields on the res.partner record. If the customer uses multiple Custom Object types, each maps to a separate res.partner category or a custom res.partner.subtype field. Relationships between People and Companies in Customer.io are preserved as parent_id links on the res.partner record in Odoo.
Customer.io
Transactional Messages
Odoo CRM
mail.template + mail.mail
1:1Customer.io transactional message templates (receipts, password resets, shipping notifications) map to Odoo mail.template records. We export template content, trigger conditions, and the unsubscribe bypass flag. Delivery logs (sent, delivered, undeliverable, bounced) map to mail.mail records with mail.mail.state preserved. Note that Customer.io's message retention setting may redact some transactional content; we flag any redacted payloads before export and mark those mail.mail records as content_redacted in Odoo.
Customer.io
Message Delivery Logs
Odoo CRM
mail.mail records
1:1Delivery status for emails sent from Customer.io maps to Odoo mail.mail records. Sent, delivered, bounced, and undeliverable statuses migrate with the status code preserved. Open and click tracking data does not have a native Odoo equivalent and is exported as structured metadata on the mail.mail record rather than a tracked engagement event.
Customer.io
Traits and Attributes
Odoo CRM
res.partner custom fields
lossyCustomer.io trait key-value pairs (strings, numbers, booleans, arrays, nested objects) map to Odoo res.partner custom fields created via Odoo Studio or a data migration CSV. Flat traits map directly; nested objects are flattened using a dot-notation convention (e.g., subscription.plan_name becomes x_subscription_plan_name). Arrays (e.g., enabled_channels) become Odoo char or many2many fields depending on the customer's use case, decided during scoping.
Customer.io
Engagement: Email
Odoo CRM
mail.message on Contact
1:1Customer.io email engagement records map to Odoo mail.message records linked to the res.partner. Body, subject, send timestamp, and delivery status migrate. Open and click tracking are exported as structured metadata on the message. Email threads that span multiple Customer.io sends are represented as a sequence of mail.message records ordered by timestamp.
Customer.io
Engagement: SMS
Odoo CRM
mail.message on Contact
1:1Customer.io SMS engagement records map to Odoo mail.message records with a custom sms_channel field identifying them as SMS rather than email. Body, recipient phone number, send timestamp, and delivery status migrate. Odoo SMS delivery receipts are not natively supported in the Community edition; SMS migration is scoped for Odoo Enterprise or Online with iap_sms configured.
Customer.io
Engagement: Push Notification
Odoo CRM
mail.message (flagged, not sent)
lossyPush notification history migrates as mail.message records flagged as x_push_notification = True, recording the message body and send timestamp. We do not re-send push notifications in Odoo because Odoo CRM has no native push notification capability and device tokens from Customer.io cannot be transferred to any other provider. Customers requiring push notifications post-migration must implement a separate push service (Firebase, OneSignal, etc.) and do not migrate device tokens as part of the CRM data migration scope.
| Customer.io | Odoo CRM | Compatibility | |
|---|---|---|---|
| People (Profiles) | Contact (res.partner)1:1 | Fully supported | |
| Custom Events | CRM Activity Log (mail.activity)1:many | Fully supported | |
| Segments | Tags (ir.exports.line) + Lead Scoring Fieldslossy | Mapping required | |
| Campaigns | CRM Pipeline Stage + Taglossy | Fully supported | |
| Broadcasts | CRM Lead / Contact with Tag1:1 | Mapping required | |
| Custom Objects (Companies, Accounts) | res.partner (Company type)1:1 | Fully supported | |
| Transactional Messages | mail.template + mail.mail1:1 | Mapping required | |
| Message Delivery Logs | mail.mail records1:1 | Mapping required | |
| Traits and Attributes | res.partner custom fieldslossy | Fully supported | |
| Engagement: Email | mail.message on Contact1:1 | Fully supported | |
| Engagement: SMS | mail.message on Contact1:1 | Fully supported | |
| Engagement: Push Notification | mail.message (flagged, not sent)lossy | 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
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 Odoo edition selection
We audit the Customer.io workspace: profile count, trait schema, active event names and property types, Custom Object types and record counts, active Segments and their rule criteria, active Campaigns and Journeys, broadcast history, and transactional message templates. We pair this with an Odoo edition review (Community, Online, or Enterprise) based on the customer's data volume, custom field requirements, and SMS or push needs. The discovery output is a written migration scope document covering what migrates, what is exported as an audit document, and what requires post-migration rebuild.
Schema design and Odoo custom field provisioning
We design the destination Odoo schema before any data moves. For Community edition this means creating custom fields via Odoo Studio on res.partner and crm.lead. For Enterprise this may include custom models via module development. We create all fields needed to receive migrated traits, event history types, and Custom Object attributes. Segment rule criteria are translated into a Tag naming convention and a Lead Automation plan. Schema is validated in an Odoo test database before production migration begins.
Data cleansing and trait flattening
We run a data quality pass on the Customer.io export. Duplicate profiles (same email or userId) are flagged and deduplicated. Inactive profiles are identified and marked for optional exclusion based on the customer's preference. Nested trait objects are flattened to dot-notation field names compatible with Odoo's character field naming convention. Event properties exceeding Odoo's field type constraints are stored as serialized JSON in a dedicated field rather than individual columns.
Segment and campaign audit export
We export every active Customer.io Segment as a structured JSON object containing its name, rule criteria, event conditions, and membership count at export time. We export Campaign and Journey structure including trigger, conditions, actions, wait steps, and channel assignments. This audit document is the primary handoff artifact for the customer's Odoo admin to rebuild audience logic in Odoo using Lead Automation rules, contact tags, and pipeline stage assignments.
Production migration in record order
We run production migration in dependency order: res.partner records (Company partners first, then individual Contact partners with parent_id resolved to the Company partner), crm.lead records for any lead-scoped profiles, mail.activity records representing event history linked to the resolved Contact, mail.message records for engagement history, mail.template records for transactional messages, and mail.mail records for delivery log history. Each phase emits a row-count reconciliation report before the next phase begins. Push notification device tokens are excluded from migration scope and flagged for separate handling.
Cutover, validation, and rebuild handoff
We freeze Customer.io writes during cutover, run a final delta migration of any records modified during the migration window, then enable Odoo CRM as the system of record. We deliver the Segment, Campaign, and Journey audit document to the customer's admin team with a recommended Odoo Lead Automation configuration for each migrated campaign. We support a one-week hypercare window for reconciliation issues. Workflow rebuild, Odoo Lead Automation setup, and push SDK re-enrollment are outside the standard migration scope and are handled as separate engagements.
Platform deep dives
Customer.io
Source
Strengths
Weaknesses
Odoo CRM
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 Odoo CRM.
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 Odoo CRM migration scoping. Not seeing yours? Book a call.
Walk through your Customer.io 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 Customer.io
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.