Skip to main content
Insyrge - Zoho CRM & Business Automation Consulting
← Back to All ArticlesAI & Business Automation

Salesforce to Zoho CRM Migration: Keep Your Data

How to map objects, preserve notes and activity history, and validate every module before you switch from Salesforce to Zoho CRM.

•Manav Sharma
Salesforce to Zoho CRM Migration: Keep Your Data

Moving off Salesforce? Map objects, keep notes, activities and record links intact, and validate every module before cutover. Plan your migration today.

Switching CRMs is rarely hard because of the records themselves. It is hard because of everything attached to them: the notes a rep wrote two years ago, the call logged against a deal, the file a customer signed, and the owner who should still see all of it. A Salesforce to Zoho CRM migration succeeds when that history arrives intact and linked to the right records. This guide covers how we plan the move, the order we import data in, a field-mapping table you can start from, and a scripted approach for the cases the built-in tool does not cover.

Decide what "history" means for your team

Before anyone exports a file, agree on what must survive the move. In our experience, teams mean different things by "keep the history":

  • Notes on accounts, contacts, leads and opportunities
  • Activities: tasks, events and logged calls, with their dates and owners
  • Attachments and files
  • Opportunity stage history and closed-lost reasons
  • Emails logged in Salesforce
  • Record ownership and creation dates

Write this list down and get sign-off. Each item has a different migration path, and some may not have a one-to-one home in Zoho CRM. For example, check how logged emails will be stored before you promise they will appear on the record exactly as they did in Salesforce.

Option 1: Zoho's built-in Salesforce migration

Zoho CRM includes a migration path designed for Salesforce exports. According to Zoho's help article on migrating data from Salesforce, you upload your exported files under Setup > Data Administration > Import, choose Salesforce on the Data Migration page, and Zoho maps the files to modules and fields. The supported modules listed there include users, leads, accounts, contacts, deals, campaigns, notes, activities (tasks, events and calls), attachments, cases, products, quotes and invoices.

For many small and mid-sized orgs this is the right starting point. It handles relationships between standard objects and lets you review the import history afterwards. Zoho's article also notes that a migration pauses if more than 5,000 records in a module are skipped, which is a useful safety net.

The built-in tool is less suitable when you have heavily customised objects, complex record types, data that needs cleaning or transforming on the way in, or a requirement to run the migration repeatedly during a parallel-run period.

Option 2: A scripted, API-based migration

For those cases we script the migration against the Zoho CRM API. This gives full control over transformation, ordering and retries, and it can be re-run safely if you design it around a stable external ID.

The Salesforce to Zoho CRM migration sequence

Whichever option you choose, import parent records before the records that point to them. If a note is imported before its contact exists, the link has nothing to attach to.

  1. Users and roles, so ownership can be assigned
  2. Accounts
  3. Contacts, linked to accounts
  4. Leads
  5. Deals (Salesforce opportunities), linked to accounts and contacts
  6. Products and price books, if you use them
  7. Activities: tasks, events and calls
  8. Notes
  9. Attachments and files

After each stage, check counts and spot-check a sample before moving on.

Field-mapping table: a starting point

The table below shows a typical starting map. Your org's custom fields and picklists will add rows.

Salesforce object / fieldZoho CRM module / fieldNotesAccountAccountsDirect equivalentAccount.NameAccount_NameContactContactsMap AccountId to the Account_Name lookupLeadLeadsCheck lead status picklist valuesOpportunityDealsOpportunity.StageNameStageRebuild stages first, then map values one by oneOpportunity.Amount / CloseDateAmount / Closing_DateTaskTasksTask subtype "Call" may belong in CallsEventMeetings (Events)Map attendees and times; confirm time zonesNote / ContentNoteNotesEnhanced notes are exported as files; see belowAttachment / ContentVersionAttachmentsNeeds the parent record ID to linkOwnerIdOwnerMatch users by email addressId (18-character)Salesforce_ID (custom field)Keep for traceability and re-runsCustom objectCustom moduleCreate the module and fields before importing

Two details catch teams out. First, Salesforce's enhanced notes are stored as files (ContentNote, exported through ContentVersion), so exporting the Notes object alone can miss them. Zoho's community has a thread on Salesforce notes during migration that describes the export steps. Second, stage and status picklists rarely match one-to-one, so build the Zoho picklists first and agree a value map with sales leadership.

Worked example: an idempotent upsert keyed on the Salesforce ID

In scripted migrations we add a custom field called Salesforce_ID to each Zoho module and mark it as unique ("Do not allow duplicate values"). We then use Zoho's Upsert Records API with that field as the duplicate check. If the script is interrupted and re-run, existing records are updated rather than duplicated.

The illustrative Python below upserts contacts in batches of 100, which is the per-call maximum in Zoho's documentation.

import requests

ZOHO_API = "https://www.zohoapis.com/crm/v8"   # use your data-centre domain
HEADERS = {"Authorization": "Zoho-oauthtoken YOUR_ACCESS_TOKEN"}

def to_zoho_contact(sf, account_map, owner_map):
    return {
        "Salesforce_ID": sf["Id"],
        "First_Name": sf.get("FirstName"),
        "Last_Name": sf["LastName"],
        "Email": sf.get("Email"),
        "Phone": sf.get("Phone"),
        "Account_Name": {"id": account_map[sf["AccountId"]]} if sf.get("AccountId") else None,
        "Owner": {"id": owner_map[sf["OwnerId"]]},
    }

def upsert_contacts(sf_contacts, account_map, owner_map):
    for i in range(0, len(sf_contacts), 100):
        batch = [to_zoho_contact(c, account_map, owner_map) for c in sf_contacts[i:i + 100]]
        body = {
            "data": batch,
            "duplicate_check_fields": ["Salesforce_ID"],
            "trigger": [],   # skip workflows during migration
        }
        r = requests.post(f"{ZOHO_API}/Contacts/upsert", json=body, headers=HEADERS, timeout=60)
        r.raise_for_status()
        for sf_row, result in zip(sf_contacts[i:i + 100], r.json()["data"]):
            if result["status"] != "success":
                log_failure(sf_row["Id"], result)   # review and re-run later

account_map and owner_map translate Salesforce IDs into Zoho IDs, built from the earlier account and user stages. Passing an empty trigger list stops workflows from firing on historical records. Without that, a migration can send hundreds of "new contact" emails or create follow-up tasks that nobody wants.

Keep an eye on API credits. Zoho's API limits documentation explains how credits are counted and the concurrency limits per edition, so plan large migrations to run within them.

Validate before you cut over

We never sign off a migration based on record counts alone. Our validation checklist includes:

  • Counts per module and per owner match between the source export and Zoho
  • 20 to 30 sampled accounts open with the correct contacts, deals, notes and activities attached
  • Activity dates and owners preserved, not reset to the migration date
  • Attachments open and belong to the right record
  • Picklist values all map to valid Zoho values, with no blanks where data existed
  • Reports that sales leadership relies on produce comparable numbers in both systems

Run at least one full trial migration into a sandbox or test org before the production run. Fix mapping issues there, not in production.

Plan the cutover itself

  • Freeze changes in Salesforce for the final export window, or plan a delta migration for records changed after the main load.
  • Switch off Zoho workflows, assignment rules and email alerts during the load, then switch them on deliberately afterwards.
  • Keep Salesforce read-only for an agreed period so users can check anything that looks wrong.
  • Train users on where their history now lives before go-live day.

If you are also cleaning duplicates as part of the move, our guide to CRM database hygiene and deduplication covers matching rules worth applying before import. For the most common ways records go missing, see how to avoid data loss during a CRM migration.

Frequently Asked Questions

Can notes and activities be moved from Salesforce to Zoho CRM?

Yes. Zoho's Salesforce migration lists notes and activities (tasks, events and calls) among the supported modules, and a scripted migration can move them through the API. Import them after their parent records so the links resolve.

Will record owners and created dates be preserved?

Owners can be preserved by matching users by email before importing records. Original dates should be checked in a trial run; where a system date cannot be set directly, we store the original value in a custom field so it remains visible and reportable.

How long does a Salesforce to Zoho CRM migration take?

It depends far more on data quality and customisation than on record count. A standard org with clean data can move quickly with the built-in tool. Heavily customised orgs need time for mapping, trial runs and validation.

Should we clean data before or after migrating?

Before, wherever possible. Removing duplicates and dead records first means fewer records to map, validate and pay for, and users start in Zoho with data they trust.

Plan your migration with us

We plan and run migrations into Zoho CRM, from field mapping and trial runs to cutover and user training. Learn more about our Zoho CRM implementation services, or book a call with our team to scope your Salesforce migration.

About the Author

Manav Sharma is the founder of Insyrge and a CRM solutions architect. He works across Zoho, Salesforce, HubSpot, Odoo and more, designing the CRM setups, integrations and automations that keep sales and operations teams working from the same data.

Need Help Implementing This in Your Business?

Our certified Zoho consultants and automation experts can help you design and deploy custom workflows tailored to your operations.

Book Free Consultation