Kaizen 228 - Process Large-Scale Migrated Data Using Catalyst Solutions

Kaizen 228 - Process Large-Scale Migrated Data Using Catalyst Solutions



Howdy, tech wizards!

This week’s Kaizen explores how Catalyst Solutions in the Zoho CRM Developer Hub help import large volumes of data into Zoho CRM while improving data quality and simplifying the migration process.

Why Catalyst Solutions?

Catalyst Solutions provide a library of independent, ready-to-use backend solutions called CodeLibs. The CRM Bulk Data Processor CodeLib helps handle complex data operations on large datasets. Following are the key benefits:
  1. Highly Scalable: Processes large datasets efficiently, supporting up to 200,000 records per API call.
  2. Automation Made Simple: Automate complex tasks like segmentation, data cleansing and lead scoring with minimal effort.  
  3. Effortless Integration: Comes with pre-configured Catalyst resources such as serverless functions and data stores that integrate directly with Zoho CRM.

Business Scenario

Zylker, a manufacturing company, migrated over 3 lakh Lead records into Zoho CRM from spreadsheets. 



Post-migration, the Lead data showed the following inconsistencies and challenges:
  1. Phone number field did not include country codes, or contained incorrect country codes. This inconsistency made it difficult for sales teams to contact Leads reliably.
  2. Identifying potential Leads for follow-up required manual effort and marketing team has to run generic campaigns without lead segmentation. 
Using workflows before record creation to fix phone numbers for this volume would result in 3 lakh individual workflow executions, which can slow imports and cause partial failures.

Solution Overview

Zylker can use the CRM Bulk Data Processor available in Catalyst Solutions to address these challenges at scale.

The solution works as follows:
  1. Lead records are fetched in bulk from Zoho CRM using the Bulk Read API.
  2. The fetched data is temporarily stored to evaluate the priority and quality of each record. Based on this evaluation, the records are also segmented accordingly.
  3. The Country field value is used to identify and append the correct country code to the phone number.
  4. The processed records are updated back into Zoho CRM using Bulk Write API.
All operations are executed using pre-configured Catalyst resources provided by the CodeLib. You can explore the Bulk Data Flow in Catalyst help page to understand how each resource participates in the processing pipeline.

Prerequisites

Before you begin, ensure the following:

1. Log into your Zoho CRM and navigate to Setup > Customization > Modules and Fields > Leads.

Create the following custom Single Line fields to map existing record data in Zoho CRM. 
  1. Last Activity Days
  2. Web Engagement Score
Refer to the Working with Custom Fields help page for detailed guide. 


2. Create the following custom Single Line fields to store the calculated values during bulk processing:
  1. Lead Score Value
  2. Lead Segment
  3. Sales Priority
  4. Data Quality Status
3. Go to Setup > Developer Hub > Catalyst Solutions > Zoho CRM Bulk Data Processor

4. Click Go to Catalyst and create a Catalyst account if required.



5. Refer to the Catalyst CLI Installation Guide and install it on your local system.

6. Create a new folder on your local system, which will act as a local project directory. Use the following command:

mkdir -p <folder_name>


7. Navigate to the project folder in your terminal and execute the following command: 

catalyst init

8. Follow the prompts to select and initialize your desired project from the Catalyst console. 

When prompted to choose a feature, press Enter and proceed without choosing any feature.


9. Run the following command to install the CRM Bulk Data Processor CodeLib.



Step 1: Create a Cron Job

1. Open the Catalyst Console and navigate to the same project in which you have installed the CRM Bulk Data Processor CodeLib.

2. Go to Cloud Scale > Triggers > Cron and click Create Cron.

3. Fill in the following details:
  1. Provide a Name and Description for the cron job. 
  2. Select Function and choose BulkJobScheduler from the dropdown in the Target Function field.
  3. Enter the following parameters and values:

    MODULES -> Leads
    FIELDS_TO_BE_PROCESSED -> Last_Name, Company, Mobile, Country, Designation, No_of_Employees, Web_Engagement_Score, Lead_Score_Value, Lead_Segment, Sales_Priority, Data_Quality_Status

    Use GET Modules Metadata API and GET Fields Metadata API to get the API names of the required module and fields.
     
  4. Choose the Schedule Type as One Time for our use case.
Refer to the Implementing Cron Jobs Help Guide for more details.

Step 2: Configure Zoho CRM API Credentials 

1. Create a self-client application in Zoho's API Console.

2. Generate a Grant Token with the following scopes:
  1. ZohoFiles.files.ALL
  2. ZohoCRM.bulk.ALL
  3. ZohoCRM.modules.ALL
  4. ZohoCRM.settings.ALL
  5. ZohoCRM.org.ALL


3. Follow the OAuth Help Section for a step-by-step guide to generate Access and Refresh tokens for your Zoho CRM organization.


Store all the API credentials securely for later use.

4. To allow Catalyst to access Zoho CRM data, configure the stored API credentials as environment variables in the catalyst-config.json file within the BulkDataProcessor function.

For detailed guidance, refer to the Configure Function Components help guide in CRM Bulk Data Processor. 



Notes
These environment variables are used by Catalyst Connectors to create access tokens for establishing secure connection between Zoho CRM and Catalyst.

Step 3: Add Business Logic

1. Go to com.processor.record.ZCRMRecordsProcessorImpl.java file of the BulkDataProcessor in the functions directory.

2. Override the ZCRMRecordsProcessor method with the business logic.


The complete code sample for this use case is available on GitHub for reference.

Following is the major custom logic used here:

Notes
Use the GET Fields Metadata API to fetch the API names of the fields required throughout the custom logic.

Phone Number Normalization:

This can be implemented in two stages, Country standardization and Phone Number formatting

For country standardization, CountryStandardizerUtil maps different variations of the Country field in records to a single standardized country identifier. These variations may include, 
  1. Country Names (India, Unites States, United Kingdom)
  2. Abbreviations (Ind, IN, USA, US, UK)
  3. Calling Codes (+91, +1, +44)
With this, we can ensure different interpretations of the same country are interpreted consistently during the process. 


Once the country is standardized, Phone Numbers are formatted to E.164 format in the PhoneNormalizerUtil

It removes all non-numeric characters and converts the Phone input to E.164 format with the respective country codes. 

public class PhoneNormalizerUtil {
    private static final Pattern NON_DIGIT = Pattern.compile("[^0-9]");
    public static Optional<String> normalizeToE164(String rawPhone, String countryCode) {
        if (rawPhone == null || rawPhone.trim().isEmpty()) {
            return Optional.empty();
        }
        String digits = NON_DIGIT.matcher(rawPhone).replaceAll("");
        if (rawPhone.startsWith("+") && digits.length() >= 10) {
            return Optional.of("+" + digits);
        }
        switch (countryCode) {
            case "IN":
                return normalizeIndia(digits);
            case "US":
                return normalizeUS(digits);
            case "UK":
                return normalizeUK(digits);
            default:
                return Optional.empty();
        }
    }
    private static Optional<String> normalizeIndia(String digits) {
        if (digits.length() == 10) {
            return Optional.of("+91" + digits);
        }
        if (digits.startsWith("91") && digits.length() == 12) {
            return Optional.of("+" + digits);
        }
        return Optional.empty();
    }
    private static Optional<String> normalizeUS(String digits) {
        if (digits.length() == 10) {
            return Optional.of("+1" + digits);
        }
        if (digits.startsWith("1") && digits.length() == 11) {
            return Optional.of("+" + digits);
        }
        return Optional.empty();
    }
    private static Optional<String> normalizeUK(String digits) {
        if (digits.startsWith("44") && digits.length() == 12) {
            return Optional.of("+" + digits);
        }
        if (digits.length() == 10) {
            return Optional.of("+44" + digits);
        }
        return Optional.empty();
    }

}

Lead Priority and Segmentation

The lead priority is calculated using the Title, No of employees, Last Activity Days and Web Engagement Score fields in the record.  

Each field value contributes a predefined number of points:
  1. If the job title indicates a senior role such as CEO, CTO, Director, or VP, 25 points are added.
  2. If the company size is 200 employees or more, 20 points are added.
  3. If the Lead has been active within the last 7 days, 15 points are added.
  4. If the web engagement score is 70 or higher, 10 points are added.
The sum of all applicable factors is returned as an integer and based on this score the lead's priority and segmentation is assigned as follows:
  1. High (Hot): score ≥ 70
  2. Medium (Warm): score ≥ 40
  3. Low (Cold): score < 40
public static int calculateLeadScore(
            String jobTitle,
            Integer companySize,
            Integer lastActivityDays,
            Integer webEngagementScore) {
        int score = 0;
        // Decision Maker
        if (jobTitle != null) {
            String title = jobTitle.toLowerCase();
            if (title.contains("ceo") || title.contains("cto")
                    || title.contains("director") || title.contains("vp")) {
                score += 25;
            }
        }
        // Company Size
        if (companySize != null && companySize >= 200) {
            score += 20;
        }
        // Recency
        if (lastActivityDays != null && lastActivityDays <= 7) {
            score += 15;
        }
        // Engagement
        if (webEngagementScore != null && webEngagementScore >= 70) {
            score += 10;
        }
        return score;
    }
    public static String deriveSegment(int score) {
        if (score >= 70) return "Hot";
        if (score >= 40) return "Warm";
        return "Cold";
    }
    public static String derivePriority(String segment) {
        switch (segment) {
            case "Hot":
                return "High";
            case "Warm":
                return "Medium";
            default:
                return "Low";
        }
    }

Lead Quality:

Lead quality is evaluated based on the validity of the Mobile and Country fields in the records.
  1. Clean: Both field values are valid.
  2. Critical: Both field values are invalid.
  3. Needs Review: Only one of the field values is invalid.

Write Back to Records:

The processed data is written back to Zoho CRM as follows:
  1. Mobile: Formatted phone numbers.
  2. Lead Score: Total score calculated from all applicable fields.
  3. Lead Segment: Segment derived from the lead score.
  4. Sales Priority: Priority assigned based on the lead segment.
  5. Data Quality Status: Overall quality of the Lead record.
if (normalizedMobile.isPresent()) {
data.put("Mobile", normalizedMobile.get());
}
data.put("Lead_Score", leadScore);
data.put("Lead_Segment", leadSegment);
data.put("Sales_Priority", salesPriority);
data.put("Data_Quality_Status", dataQualityStatus);
}

Step 4: Deploy to Development

Run the following command to deploy your local customizations to the Development Environment of Catalyst.

catalyst deploy

Info
You can find the complete code sample on GitHub for reference.

Try it Out!

With the changes deployed to the Development environment, let us now test the solution.



We hope this Kaizen helps you import large volumes of data into Zoho CRM while improving data quality and lead intelligence using the CRM Bulk Data Processor.

Have questions or suggestions? Drop them in the comments or write to us at  support@zohocrm.com

We will circle back to you next Friday with another interesting topic. 

On to Better Building!

--------------------------------------------------------------------------------------------------------------------------

Idea
Previous Kaizen: Client Script Support for List Page (Canvas) | Kaizen Collection: Directory

--------------------------------------------------------------------------------------------------------------------------
    • Sticky Posts

    • Kaizen #198: Using Client Script for Custom Validation in Blueprint

      Nearing 200th Kaizen Post – 1 More to the Big Two-Oh-Oh! Do you have any questions, suggestions, or topics you would like us to cover in future posts? Your insights and suggestions help us shape future content and make this series better for everyone.
    • Kaizen #226: Using ZRC in Client Script

      Hello everyone! Welcome to another week of Kaizen. In today's post, lets see what is ZRC (Zoho Request Client) and how we can use ZRC methods in Client Script to get inputs from a Salesperson and update the Lead status with a single button click. In this
    • Kaizen #222 - Client Script Support for Notes Related List

      Hello everyone! Welcome to another week of Kaizen. The final Kaizen post of the year 2025 is here! With the new Client Script support for the Notes Related List, you can validate, enrich, and manage notes across modules. In this post, we’ll explore how
    • Kaizen #217 - Actions APIs : Tasks

      Welcome to another week of Kaizen! In last week's post we discussed Email Notifications APIs which act as the link between your Workflow automations and you. We have discussed how Zylker Cloud Services uses Email Notifications API in their custom dashboard.
    • Kaizen #216 - Actions APIs : Email Notifications

      Welcome to another week of Kaizen! For the last three weeks, we have been discussing Zylker's workflows. We successfully updated a dormant workflow, built a new one from the ground up and more. But our work is not finished—these automated processes are
    • Recent Topics

    • Zoho Projects Android and iOS app update: Timesheet module is now renamed as 'Time Logs', delete option has been renamed to 'Trash'.

      Hello everyone! We have now renamed the Timesheet module as Time Logs and the delete option as 'Trash' on the Zoho Projects Android and iOS app. Time Logs Android: Time Logs iOS: Trash option Android: Trash option iOS: Please update the app to the latest
    • Zoho Mail app update: Manage profile picture, Chinese (Traditional) language support

      Hello everyone! In the latest version (v3.1.9) of the Zoho Mail app update, we have brought in support to manage profile picture. You can now set/ modify the profile picture within the app. To add a new profile picture, please follow the below steps:
    • Reminders for Article Approval

      Is there a way to send reminders for approvers to review articles and approve/deny them? I'm not seeing that option anywhere.
    • Add Full-Screen Viewing for Quartz Recordings in the Client Interface

      Hi Zoho Team, We would like to request an enhancement to the Zoho Quartz client interface when viewing submitted recordings. Current Limitation: When viewing a Quartz recording from the client (user) interface, there is currently no option to switch the
    • 2025 Recap: A Year to Remember | Zoho Inventory

    • Important Update : Pipedrive deprecated fields no longer supported in Zoho Analytics

      Dear Pipedrive users, We would like to inform you about a recent update related to your Pipedrive integration with Zoho Analytics. The Pipedrive team has deprecated certain fields from their application. You can find more details in the official Pipedrive
    • Product Updates in Zoho Workplace applications | November 2025

      Hello Workplace Community, Let’s take a look at the new features and enhancements that went live across all Workplace applications this November. Zoho Mail Format comments easily using Slash Commands With Slash commands, you can easily format text, insert
    • Right-Click Pipeline to Open in New Tab

      Please add the ability to right-click on a pipeline to open it in a new tab
    • Adjusting Physical Inventory

      Not getting very far with support on this one, they say they are going to fix it but nothings happened since November. Please give this a thumbs up if you would like to see this feature or comment if you have some insight. Use Case: Inventory set to be
    • I need to Record Vatable amount and non vatable amount separately in zoho books in a single line

      I need to Record Vatable amount and non vatable amount separately in zoho books in a single line give me the customisation option and in invoice copy to customer the total amount should be inclusive 5%vat and no need to show the vatable and non vatable
    • sync views to sheet

      Im looking to sync my views aka reports in analytics to zoho sheets, when data is updated in analytics it also should be updated in sheets, till now zoho sheets only offer raw data connection and it is not enough as these reports are difficult to re-do
    • How to update the Status in a custom module?

      Hi, I have a custom module "cm_payment_registry" in Billing, I am trying to change the status which is "Draft" with: array = {"custom_status":"Approved"}; zoho.billing.update("cm_payment_registry",organization.get("organization_id"), XXXXXXXXXXXXXX, array,"connectionname");
    • Opening balances - Accounts Receivable and Payable

      Our accounting year starts on 1st August 2013 and I have a Trial Balance as at that date, including Accounts Receivableand Accounts Payable balances, broken down by each customer and supplier. Q1 - do I show my opening balance date as 31st July 2013 or
    • Replace Zoho Invoice with QuickBooks

      We are implementing Zoho FSM for a cleaning business in the US with 50+ field workers. This business has been using Quickbooks for accounting for decades and will not migrate to Zoho Books. A major issue in the integration is the US sales tax calculation.
    • 2025 Highlights: A Year of Steady Progress and Significant Developments

      As we come to the end of 2025, let's take a moment to reflect on the significant progress and developments we've made to improve your travel and expense management. In the Spotlight Introducing Online Booking (US edition only - Early access) Enable online
    • Function #42: Show the actual rate of items on invoices

      Hello everyone, and welcome back to our series! In Zoho Books, you have the ability to create Price Lists, wherein you can mark up and mark down the item rates by a specific percentage or set custom rates. Generally, when you apply a price list to an
    • Ability to Set Text Direction for Individual Cells in Zoho Sheet

      Dear Zoho Sheet Team, We hope you are doing well. We would like to request an enhancement in Zoho Sheet that allows users to set the text direction (right-to-left or left-to-right) for individual cells, similar to what is available in Google Sheets. Use
    • Warehouse fast processing

      Hey guys, would anyone be interested in something like the attached image ? If there's any interest I'd be willing to develop it further for others to use, it's much faster than using Zohos native solutions, it can part pack, pack in full, part ship,
    • Can I create a CODE 128 custom field for my items in Zoho Inventory and then use it for generating Sales Orders?

      Can anyone helps me, I don't want to use the SKU code for scanning my products.  ​Because all my products have a CODE-128 label attached.
    • Start/Stop Timmer in Chrome Extension

      The chrome extension is great and allows you to do allot however one of the most common things employees working on projects need to do is track their time. Having an easy start/stop timer to track time would be great.
    • Invalid collection string

      I haven't changed anything in one of my functions. I'm trying to run it manually and suddenly "Invalid collection string" appears. My code has 6 lines and the error says that the error is on 7th line. Why? What does this error mean? Nothing has been changed
    • Zoho Directory 2025: New Features | Security Enhancements | Enriched UI

      Hello everyone, Greetings from the Zoho Directory team! 2025 has been a highly successful year for Zoho Directory. We are delighted to introduce a fresh set of features, an enriched UI, and major product enhancements. These updates aim to deliver a smoother
    • zoho people 5 report

      How do I customize my report in Zoho People Report? I understand that I can get the results of multi-table queries through SQL join statements, but I don't know the relationship between each table. I tried to create a report using Attendance User Report
    • Leave Report Emailed Weekly

      I am wondering if someone knows how to have a report generated either weekly or monthly or both for department heads and ownership of upcoming employee leave. For instance, it would be nice to get an emailed report on Friday for the upcoming week of who
    • Zoho Flow Decision Continuing Despite Not Meeting Conditions

      I have a picklist field called Lead Status in the leads module, with the following lead Statuses: New Lead Attempted Contact - 1 Attempted Contact - 2 Attempted Contact - 3 Attempted Contact - 4 Attempted Contact - 5 Attempted Contact - 6 Attempted Contact
    • Tip #55- Accessibility Controls in Zoho Assist: Exploring Vision Settings- 'Insider Insights'

      As we approach the end of the year, it’s a good moment to reflect on how we can make our tools more inclusive and easier to use for everyone. Remote support often involves long hours in front of screens, varied lighting conditions, and users with different
    • Zoho Recruit Slow and Freezing on all screens

      We have had an issue with Zoho Recruit for weeks being extremely slow and at times freezing.  We have 100 mega internet, and I went into each computer and updated the virtual memory so there is more available.  Also restarted all computers daily.  Still having the issues.  Almost unable to work.
    • Credit Management: #2 Configuring Right Payment Terms for Credit Control

      Think about the last time you ordered something online and saw that little note at the checkout, "Pay on Delivery" or "Pay later". It's simple, but it actually sets the tone. As a business owner, you know exactly when payment is expected. Now, imagine
    • Dependent (Conditional) Fields in Zoho Bookings Forms

      Hello Zoho Bookings Team, Greetings, We would like to request the ability to create dependent (conditional) fields in Zoho Bookings registration forms. Current Limitation: There is currently no way to make one field’s available options depend on the value
    • Bug Report: Search fails to find existing notes after Evernote import

      Hello, I recently migrated from Evernote (~2600 notes across 23 notebooks), but the search functionality is currently broken. The Issue: I can manually browse to a specific note and see it exists. However, when I type the exact or partial title of that
    • Marketing Tip #13: Win repeat customers with post-purchase emails

      The relationship with your customer doesn’t end after the sale; that’s when it begins. A thoughtful post-purchase message shows customers you appreciate them, keeps your brand top of mind, and can even lead to another sale. You can thank them, ask for
    • Zoho Form

      I have problem with Zoho Form. One of form i don't received the PDF version. Others okay except this one. W904533
    • Create & Update Zoho Vault Passwords via Zoho Flow

      Hi Zoho Flow / Zoho Vault Team, We’d like to request an enhancement to the Zoho Vault integration in Zoho Flow. Current Limitation: At the moment, Zoho Flow supports only the following selected Zoho Vault actions, such as: Fetch passwords, Share passwords
    • Custom Related List Inside Zoho Books

      Hello, We can create the Related list inside the zoho books by the deluge code, I am sharing the reference code Please have a look may be it will help you. //..........Get Org Details organizationID = organization.get("organization_id"); Recordid = cm_g_a_data.get("module_record_id");
    • Migrate different zoho subscription to zoho one

      Dear We have different zoho subscription we need to migrate it to zoho one. Currently we are paying for zoho email, zoho expense, zoho payroll etc under different admin We need to move it too zoho one flexlible plan for all my employees
    • Features, Feedback and Votes

      We’re launching the Feedback Forum for our customers. This is 'THE' place where you can add everything you’d like to see in Zoho Books. If you don't find the specific feature you need, simply add it so others can also vote for it. While we cannot promise
    • Payment system for donations management

      I manage an organization where we receive donations from payers. Hence, there is no need to first create invoices and then create payments received against the invoices. What are the recommended best practices to do this in ZohoBooks?
    • There Might Be A Glitch in Determining If A String Represents A URL

      I suspect there might be a glitch in determining if a string represents a URL or not. For example, I cannot embed the following URL. Perhaps the exclamation mark or parentheses are the culprit? https://en.wikipedia.org/wiki/How_the_Grinch_Stole_Chri
    • Customer Management: #4 Enhance Customer Journey

      When Neha started DefineOps, a growing IT support and consulting firm, most of her work was straightforward. A client would sign up for a free version, decide whether the service works for them, and then either continue or discontinue. Billing was simple,
    • Android app sync problem - multiple devices have same problem

      Hello, I am having a problem with synchronization in the Android app. When I create a drawing, the data does not sync correctly—only a blank note is created without the drawing. I tested this on multiple devices, including phones and tablets, and the
    • Next Page