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

    • Quotes - Freehand line items - zoho crm

      Hi, In the zoho crm quotes module is it possible to add line items that are freehand typed? We have a business need to use the quotes module but the product nams/description, quantity, price, etc. needs to be freely typed rather than from a defined list
    • TDS Payable report not Generating

      TDS Payable report for Last Quarter of FY 25-26 is not generating and giving error. Please get it rectified as soon as possble.
    • Remove Zoho Header from Portals

      I have a portal page with custom domain. But when I print directly from a webpage, the Zoho CRM header shows. It kind of kills the branding aspect. Is there a way to get rid of this?
    • Multi-column sorting

      Is multi-column sorting a planned feature for CRM? We are needing to sort by one column and then subsort by another column. I am just wondering if there is a planned feature that will allow this?
    • Clearing Fields using MACROS?

      How would I go about clearing a follow-up field date from my deals? Currently I cannot set the new value as an empty box.
    • Webinar Alert: Turn campaign leads into conversions with Zoho LandingPage and Zoho CRM

      Landing pages are great at capturing leads, but what happens after that is just as important. In this webinar, we’ll walk through how Zoho LandingPage and Zoho CRM work together to create a smooth flow from lead capture to follow-up and conversion. You’ll
    • Catch-All Address: A safety net for misdirected emails

      Email is often the first point of contact with an organization. In many cases, a simple typo in a recipient's address can quietly turn into a missed message—a customer query never reaches support, a partner’s reply goes unnoticed, and the sender has no
    • Need Assistance on Redirect URL or Button Based on Deal Stage

      Hello, I’ve developed a custom application and would like to achieve the following scenario: When a deal is moved to the Billing stage, an automatic trigger should execute and redirect to a URL that includes deal details such as Deal Name and Deal Owner.
    • Zoho IMAP Access to mail doesn't sync messages

      As stated in the topic - I have company account email address setup, and it has ( as in the picutre ) ActiveSync and Imap access enabled. However the messages does not show up while logged in in Zoho Mail however when I log in in thunderbird everything
    • 【無料/オンライン】5/21(木)開催|Zoho ワークアウト ― ユーザー同士で作業・議論するもくもく会

      ユーザーの皆さま、こんにちは。 コミュニティグループの中野です。 5月開催の「Zoho ワークアウト」のご案内です。 本イベントは、Zohoユーザーが各自のテーマを持ち寄り、 作業を進めながら参加者同士で意見交換する「もくもく会」形式のオンラインイベントです。 「設定を進めたいけれど、一人だと手が止まってしまう」 「他社がどう活用しているのか知りたい」 「同じ課題を抱える仲間と話したい」 そんな方にぴったりのイベントです。 ▶︎ 参加登録はこちら(無料 / 残り3枠) URL:https://us02web.zoom.us/meeting/register/6ojuA778RqqWPOWzCaCU5Q
    • i keep see there is a connetion issue connecting 3rd party api on zoho when using zia

      hi there , i have set up open ai api to zoho zia (copied and pasted to zoho zia) but I keep getting notificaiton "there is a connetion issue connecting 3rd party api on zoho" when using zia on top when click zia and try to type in word there
    • Can't access google from toppings menu

      So... When I click the manage button in toppings, nothing happens. it won't let me access the settings.
    • Marketer's Space: Bookmarks by Zoho Campaigns

      Hello Marketers, In this week's Marketer's Space, we'll look at a simple yet powerful feature that makes a big difference in your workflow: Bookmarks. Bookmarks is a built-in feature in Zoho Campaigns that enables you to create a personalized library
    • Introducing the revamped What's New page

      Hello everyone! We're happy to announce that Zoho Campaigns' What's New page has undergone a complete revamp. We've bid the old page adieu after a long time and have introduced a new, sleeker-looking page. Without further ado, let's dive into the main
    • Cliq iOS can't see shared screen

      Hello, I had this morning a video call with a colleague. She is using Cliq Desktop MacOS and wanted to share her screen with me. I'm on iPad. I noticed, while she shared her screen, I could only see her video, but not the shared screen... Does Cliq iOS is able to display shared screen, or is it somewhere else to be found ? Regards
    • Tip #71 - Exploring Technician Console: Send Clipboard Keystrokes - 'Insider Insights'

      Hello Zoho Assist Community! Say you are helping a customer remotely and need to log into a system on their machine. You have the password ready on your end, but the moment you try to paste it into the login field, nothing happens. The remote screen just
    • Tip #7: Customize the appointment confirmation page

      A confirmation page plays a crucial role in creating the first impression, as that's where customers land when booking with you. It shows your brand identity, engages your audience, and drives more conversions. Yet, this section is often overlooked when
    • Images not saved in notes

      Created noteboards and create a note, copy pasted the image, close the note and open again, image is not coming this same problem occurs in note on notebook I have attached the replication steps as video url to analyse it, and also attached the videos
    • New in Office Integrator: Apply conditional formatting to entire rows

      Hi users, We are pleased to introduce the ability to highlight entire rows based on a cell's value in Zoho Office Integrator's spreadsheet editor. For example, if your finance team tracks invoice payments in a spreadsheet, you can highlight overdue invoices
    • Zoho books - Project Module - Itemised expenses

      Hi All, I heavily use the projects function in Zoho books and can work for one client for successive weeks, providing labour and incurring the occasional general expenses.  As an example, during the one purchase, I purchase 10 widgets and of these 10, 
    • How to get REST API of extension function in CRM

      I create a an extension using ZOHO Sigma for integrate ZOHO CRM and XERO and established two way sync but when I public my extension it's standalone function are not provide any type of access so I can't get REST API Key of standalone functions without
    • A few Issues when using "Pay Bill via Check"

      We have quite a bit of issues with how paying for Bills via Check works. Would love some feedback from the Zoho team in case we are doing something incorrectly. 1. When we go from a vendor and select "Pay Bill via Check" option, we see ALL the outstanding
    • Show backordered items on packing slip

      Is it possible to show a column on the Packing Slip that shows number of backordered items when a PO is only partially filled? I would also like to see the Backordered column appear on POs after you receive items if you didn't get ALL of the items or partial amounts of items. And lastly, it would be nice to have the option of turning on the Backordered column for invoices if you only invoice for a partial order. -Tom
    • Elevate your Radar experience: Best practices part 1

      In the Spotlight: Zoho Desk's Radar app Think about RADAR (Radio Detection and Ranging)? The system used to track and identify aircraft, ships, and vehicles using electromagnetic waves. Imagine what a similar “Radar” experience looks like for customer
    • Mise à jour de Zoho Books – France

      Chers clients, Merci pour votre patience et votre soutien continu. Avec les évolutions réglementaires à venir en France nous introduisons de nouvelles fonctionnalités dans Zoho Books pour les clients français. Ces mises à jour ont été conçues pour répondre
    • Automation Series: Auto-update Budget When Time is Logged

      In Zoho Projects, Summary fields enable instant budget sync by capturing Actual Cost and showcases it at project-level when a time log is added. This allows real-time budget visibility and helps teams stay within financial thresholds. Consider an event
    • Preferred Name and Email Formats: Bring consistency to user identity

      A user's display name and email address are often the first identifiers that colleagues, partners, and customers see. Maintaining a consistent format across the organization helps reinforce a professional identity and avoids the confusion that comes from
    • [Webinar] Solving business challenges: Standardizing document operations across your organization

      Hi Writer users, Every organization struggles with document inconsistency due to issues like multiple templates, outdated content in client-facing docs, and the lack of a standard review process. Zoho Writer streamlines the entire lifecycle with capabilities
    • Auto-sync field of lookup value

      This feature has been requested many times in the discussion Field of Lookup Announcement and this post aims to track it separately. At the moment the value of a 'field of lookup' is a snapshot but once the parent lookup field is updated the values diverge.
    • Account name not populating when importing contacts

      When importing a csv file to add contacts the account name is blank? Every other filed gets mapped and imported correctly, i.e contact name, phone number. However not the account name which I have mapped to "company" field in my csv file
    • Requirements using Zoho Projects

      Is there a seperate Zoho application for Requirements (Requirements Repository) or a way to use Zoho Projects to store, track and organize software requirements
    • Control who sees Timeline and Interactions in Zoho CRM through Profiles

      The feature has been enabled for all DCs (except US, EU, and IN DCs). We will be rolling it out to the other DCs in the upcoming days. Dear All, In a CRM, not all users would require access to the history of a record. For instance, a Marketing Operations
    • Billing Management: #3 Billing Unbilled Charges Periodically

      We had a smooth sail into Prorated Billing, a practice that ensures fairness when customers join, upgrade, or downgrade a service at any point during the billing cycle. But what happens when a customer requests additional limits or features during the
    • Hide chart series by default (unchecked in legend)

      Hi, I’m working on a dashboard in Zoho Analytics and ran into a limitation I can’t figure out. Is there a way to have certain columns (series) in a chart hidden by default via the legend (i.e., unchecked), but still available so the user can enable them
    • Zoho CRM - Restrict Login based on work hours

      Hi there, I'm wondering if we can restrict users to login during works - For example the users would be able to login from 8am to 5pm. I have seen the IP address restriction - the only downfall is what if the customer has dynamic IP. thanks Jiri
    • ZDK.Client.showConfirmation() and showAlert() silently fail on Boolean/checkbox field onChange - anyone else?

      Hi community, I've been trying to show a message pop-up when a checkbox field is ticked. I'm using the onChange event on the Opporutnities create page. function onChange(value) { if (value === true) { ZDK.Client.showMessage( "Note: Message goes here.",
    • Tip #22 Three ways you can split your text into columns

      When you're working with large datasets, you often have the problem of messy, inconsistent formatting, which makes analysis difficult. This is especially true when the data is being collected elsewhere and then imported to the spreadsheet, which can result
    • CRM Timeline History Permissions ?

      Hello, I am curious about this. in Zoho CRM on the Timeline Tab everyone knows that it displays the history of edits and such for that particular Lead record. What if I wanted to Hide some of the History Events from CRM Users? For example, I have a workflow
    • Zia Emails Summary: Instant context from past emails

      Hello all, Reading all of the past emails associated with a specific record can be tedious, which in turn makes it difficult to understand the context quickly, as these messages often include irrelevant details that waste time. This is true for everyone
    • Custom Display Field for Lookup Dropdowns in Zoho CRM

      Could Zoho CRM support changing the display field in lookup dropdowns, like Zoho Creator does? This would make it much easier to select the right record by showing a more useful field instead of only the default one. It would improve speed, clarity, and
    • Next Page