CRM migration
Field-level mapping, validation, and rollback between Customer.io and Freshsales. We move data and schema; workflows are rebuilt natively in Freshsales.
Customer.io
Source
Freshsales
Destination
Compatibility
5 of 11
objects map 1:1 between Customer.io and Freshsales.
Complexity
BStandard
Timeline
3-5 weeks
Overview
Moving from Customer.io to Freshsales is a structural migration from an event-driven messaging platform to a unified CRM. Customer.io's identity-first data model stores People profiles with event histories and custom object relationships under separate object_type_id namespaces; Freshsales uses a Lead-to-Contact-to-Account object hierarchy with native lead scoring and pipeline management. We resolve the profile-to-contact split using Customer.io trait data, preserve event timelines as Freshsales activity records (calls, emails, meetings, notes), and handle Custom Object migrations by mapping object_type_id namespaces to Freshsales's module structure. Campaigns, Journeys, Broadcasts, and transactional message templates do not migrate as automation code; we deliver a written inventory for the customer's admin to rebuild in Freshsales's workflow builder. The profile-based pricing model that inflated Customer.io bills is replaced by Freshsales's per-seat model, which is more predictable for sales teams with large but low-engagement user databases.
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 Freshsales, 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)
Freshsales
Lead or Contact (split required)
1:manyCustomer.io People with defined traits map to Freshsales Lead or Contact based on qualification signals in trait data. We use email domain, lifecycle_stage trait, and any explicit status traits to determine whether a profile maps to Lead (unqualified) or Contact (qualified, tied to an Account). Trait fields that have no direct Freshsales equivalent become custom fields on both Lead and Contact. The original Customer.io userId is preserved in a custom field cio_user_id__c for reconciliation.
Customer.io
Anonymous Profile
Freshsales
Lead
1:1Customer.io profiles with anonymousId but no email or identifying trait map to Freshsales Lead in a pre-conversion state. These records are held in a separate import queue pending enrichment; Freshsales's lead scoring framework can assign a score to drive follow-up prioritization.
Customer.io
Custom Object (Companies / Accounts)
Freshsales
Account
1:1Customer.io Custom Objects of object_type_id type company map to Freshsales Account. We export the object record, its custom fields, and the relationship to the linked Person (via the relationship object). In Freshsales, we create the Account first, then resolve the relationship link on the Contact during the Contact import phase. Custom object types other than company are migrated as Freshsales custom modules with field mapping.
Customer.io
Custom Event
Freshsales
Note (with timestamp preserved)
lossyCustomer.io custom events have no native Freshsales equivalent. We reconstruct the behavioral timeline by creating Freshsales Notes with a preserved timestamp and event name in the Note title. Event properties are stored as Note body text in structured JSON format so they are searchable and auditable. For high-volume event migrations, we batch Notes with a maximum of 100 per Contact/Lead to avoid timeline performance degradation.
Customer.io
Trait
Freshsales
Custom Field (Lead/Contact/Account)
lossyCustomer.io trait key-value pairs migrate as Freshsales custom fields. We inspect the trait schema during discovery, map JSON-type traits to Freshsales-supported field types (text, number, date, dropdown), and create the custom fields in Freshsales before the profile import. Array and nested object traits are flattened to comma-separated text or stored as a JSON body field depending on complexity.
Customer.io
Segment
Freshsales
Static List or Dynamic List
lossyCustomer.io dynamic segments (defined by trait conditions and event triggers) are exported as structured rule sets. We cannot replicate dynamic segment evaluation in Freshsales without rebuilding equivalent filters. We create Freshsales Static Lists populated with the segment's current member roster at migration time and deliver a written filter definition for the admin to rebuild as a Freshsales Dynamic List or Workflow-triggered segmentation post-migration.
Customer.io
Campaign / Journey
Freshsales
Workflow (manual rebuild required)
lossyCustomer.io Campaign and Journey structures (entry triggers, wait steps, branching conditions, channel assignments) are exported as a written campaign map with trigger type, step sequence, and action inventory. We do not migrate Journeys as automation code because Customer.io's visual journey builder and Freshsales's Workflow builder have incompatible event models. The campaign map is delivered to the customer's admin for rebuild as Freshsales CRM Workflows.
Customer.io
Broadcast
Freshsales
Email Template + Workflow (manual rebuild required)
lossyCustomer.io Broadcast records (one-time sends to a segment) are exported with target segment, content, and send timestamp. Broadcast content migrates as Freshsales Email Templates. The broadcast send logic (trigger, timing, recipient filter) is documented and handed off for rebuild as a Freshsales Workflow or one-time campaign action.
Customer.io
Transactional Message
Freshsales
Email Template
1:1Customer.io transactional message templates migrate as Freshsales Email Templates. Message delivery logs (sent, delivered, undeliverable, bounced) migrate as Note records on the relevant Contact/Lead with status preserved. Transactional message send rules (trigger conditions) do not migrate; we document them for admin rebuild.
Customer.io
Engagement: Email
Freshsales
Activity: Email
1:1Customer.io email engagement records (sent, opened, clicked, bounced) migrate as Freshsales Activity records of type Email on the relevant Contact/Lead. Open and click events are stored as separate activity sub-entries with timestamps. Email body content migrates as Activity notes. Delivery status flags (bounce, unsubscribe) map to Freshsales's email_disposed field.
Customer.io
Engagement: SMS
Freshsales
Activity: Task (with notes)
1:1Customer.io SMS engagement records migrate as Freshsales Tasks with subject indicating SMS, body content in the Task description, and timestamps preserved. SMS delivery status (sent, delivered, failed) maps to Task status fields. Freshsales does not have a native SMS activity type; Tasks with a descriptive subject preserve the channel context.
| Customer.io | Freshsales | Compatibility | |
|---|---|---|---|
| Person (Profile) | Lead or Contact (split required)1:many | Fully supported | |
| Anonymous Profile | Lead1:1 | Fully supported | |
| Custom Object (Companies / Accounts) | Account1:1 | Fully supported | |
| Custom Event | Note (with timestamp preserved)lossy | Fully supported | |
| Trait | Custom Field (Lead/Contact/Account)lossy | Fully supported | |
| Segment | Static List or Dynamic Listlossy | Fully supported | |
| Campaign / Journey | Workflow (manual rebuild required)lossy | Fully supported | |
| Broadcast | Email Template + Workflow (manual rebuild required)lossy | Fully supported | |
| Transactional Message | Email Template1:1 | Fully supported | |
| Engagement: Email | Activity: Email1:1 | Fully supported | |
| Engagement: SMS | Activity: Task (with notes)1: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
Freshsales gotchas
Freddy AI is Pro-tier only despite heavy marketing
Post-migration emails and sequences are disabled
Bot session credits are a one-time 500-session allocation
Phone credits charged per minute with no cap
File storage limits scale with plan tier
Pair-specific challenges
Migration approach
Discovery and trait schema audit
We audit the Customer.io workspace to extract the full People profile schema, trait definitions (with JSON types), Custom Object type list, event name inventory, segment definitions, campaign structures, and engagement volume estimates. We pair this with a Freshsales module audit to identify existing standard and custom modules. The discovery output is a written migration scope with a trait-to-field mapping table and a profile split recommendation based on Customer.io trait signals.
Freshsales schema preparation and field creation
We create the custom fields in Freshsales corresponding to Customer.io traits that have no standard equivalent. We configure the Lead conversion settings based on the trait schema, mapping Customer.io lifecycle or status traits to Lead status and Contact stage. We create any custom modules for non-company Custom Object types and define the lookup relationships between custom modules and the Contact/Account objects. Schema work is validated in Freshsales before production migration begins.
Sandbox migration and reconciliation
We run a full migration into a Freshsales sandbox environment using production-like data volume. The customer's RevOps lead reconciles record counts (Leads in, Contacts in, Accounts in, Activities in), spot-checks 25-50 random records against the Customer.io source, and reviews the activity timeline reconstruction quality. Mapping corrections happen in the sandbox phase, not in production.
Profile split and dependency-ordered import
We run the profile import in dependency order: Accounts (from Customer.io company Custom Objects), then Contacts (with Account lookups resolved), then Leads (for unqualified or anonymous profiles). The split rule is applied during the import transform using the customer's agreed-upon criteria. Each phase emits a row-count reconciliation report. Deleted profiles in Customer.io that were re-added within the billing cycle are flagged and excluded from the import scope.
Event history reconstruction and engagement migration
We migrate email and SMS engagement records as Freshsales Activities on the relevant Contact or Lead. Custom events are stored as timestamped Note records with structured JSON content. We batch Note creation to a maximum of 100 per record to avoid timeline performance degradation. Transactional message templates migrate as Freshsales Email Templates with content intact.
Cutover, validation, and automation handoff
We freeze writes to Customer.io during the cutover window, run a final delta migration of any records modified since the last sync, then enable Freshsales as the system of record. We deliver the Campaign, Journey, and Segment map document to the customer's admin team for rebuild as Freshsales Workflows. We support a one-week hypercare window for reconciliation issues. We do not rebuild Customer.io Campaigns or Journeys as Freshsales Workflows inside the migration scope; that is a separate engagement or an internal admin task.
Platform deep dives
Customer.io
Source
Strengths
Weaknesses
Freshsales
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 Customer.io and Freshsales.
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
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 Freshsales migration scoping. Not seeing yours? Book a call.
Walk through your Customer.io to Freshsales 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 Freshsales
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.