Friday, December 4, 2015

Round robin lead assignment for API generated leads in Zoho CRM

Do you add leads to your CRM via the Zoho CRM API? If so, you'll note that lead assignment rules don't work. I have developed a CRM extension called Advanced Round Robin that you can buy on the Zoho Marketplace. If you'd prefer to do it yourself, the below code can allow you to add round robin lead assignment functionality (though it's missing many of the more powerful features of the Advanced Round Robin extension). You'll need to set a few config variables like your authtoken and the user role you want leads to be assigned to. You'll also need to create a reference lead that's assigned to one of the users who should receive leads. The script will use this to figure out who should get the next lead. Thanks to Prakash from Zoho for giving me the base code for this script.

Want more options? I have a paid version of this script that you can buy on the Zoho Marketplace.

Thursday, December 3, 2015

How to learn to write custom functions in Zoho CRM

Thomas posted a really interesting question on the Zoho CRM forums. He wants to know the best way to learn to write custom functions in Zoho CRM.

I recorded a video reply:

If you don't feel like watching the video, here's a summary of my tips:

1. Check out the Deluge Script eLearning course - Deluge is the language you'll use to write custom functions.

2. If you don't have a programming background, start off by learning Javascript at CodeAcademy as JS is pretty similar to Deluge and has a lot more learning resources.

3. Have a read through some of the articles on my blog, e.g.
 - how to quickly add call logs
 - forecasting subscription revenue in Zoho CRM
 - add related notes to a contact

4. Email me with any questions (jeremy.nagel [at] - I'm always happy to help people learn Deluge

Calculate financial year of a date field in Zoho CRM

I saw a question on the Zoho forums about calculating the financial year of a date using a formula. Decided to answer it because it's a little bit tricky. Here's a formula to do the job if you have the same requirement:

Saturday, October 10, 2015

Making Zoho CRM webforms responsive

I've had quite a few people ask me for help making Zoho CRM webforms responsive. My standard answer is "don't even try". The forms look bad anyway and are hard to work with. A better option is to use Ninja Forms (a wordpress plugin that makes nice looking forms that integrate with Zoho CRM).

If you do want to persist with using Zoho CRM's webforms, this video explains an approach to making them responsive. I've built a little utility that does some of the work for you. You'll still need design skills to make the forms look nice afterwards but it might save you some time.

Here's the video showing it in action:

Friday, September 18, 2015

Importing invoices into Zoho CRM

There's a bit of a trick to importing invoices into Zoho CRM. You have to use the API to achieve it. Most of the fields are pretty standard but when you're adding the product details, you have to do it like this:
product_map.put("Product Id",input.Zoho_CRM_Product_ID);
product_map.put("Unit Price",input.Renewal_Amount);
product_map.put("List Price",input.Renewal_Amount);
product_map.put("Net Total",input.Renewal_Amount);

Sunday, June 28, 2015

Forecasting subscription revenue in Zoho CRM

Zoho CRM is only set up to handle once off deals out of the box. What should you do if you want to be able to forecast subscription revenue months/years into the future? If your customers renew every month, wouldn't it be nice to know how much you're likely to make in quarter three so you can see whether your pipeline is short or not?

Here's a Deluge custom function that you can hook up with a workflow to automatically generate potentials for future months. It won't duplicate existing potentials so you can set it up to run once per month and make sure you always have the next 2 years worth of revenue forecast.

Ideally you'd also have a function to change the status of future potentials when the master potential is modified. (E.g. if a customer cancels their subscription, the future potentials should also be nullified). Let me know if you'd like that function and I can build it for you:)

Friday, June 26, 2015

Overcoming Application Fatigue

How many apps do you have on your phone right now? I have 178. Of these, I have used 45 in the last month - that's 25.2% of the total. What's happening here? Clearly I thought these apps had some merit or I wouldn't have installed them in the first place. But at some point (or several points), I reached app overwhelm and abandoned all but the tried and tested ones.
Not another app!

To give you an example, I must have tried out over 20 project management systems. I started with Evernote, graduated to Zoho Projects when I had to involve other people, then moved to Podio, then moved to JIRA, then started using Trello as well plus a bunch of Google Spreadsheets. Eventually it all became too much and I returned to the killer app: paper..

As a software developer, I feel like a bit of a traitor to the cause. If I can't handle lots of apps, then how can anyone else? I occasionally come across lists of '99 MUST USE APPS!!!' and feel almost nauseous. I'm barely coping with the apps I have right now, how am I meant to handle more?

Apparently I'm not the only one. A month or so ago, an industry connection told me that he'd abandoned a CRM rollout because his staff were suffering from application fatigue. They were already using three different apps and the thought of struggling up another steep learning curve was enough to have them ducking for cover back to a simple Google Spreadsheet.

So what are we to do about it? There's obviously utility in having lots of apps otherwise people wouldn't make them or buy them. I genuinely do prefer the user interface of Podio or Zoho Projects over paper (my handwriting is terrible, it's easy to lose bits of paper and it's hard to reorganise tasks without squiggling and crossing out everywhere).

Wah? What was I meant to buy from the shops again?

But I really don't like the overhead of having to wait for an app to load. It might only be a couple of seconds, but that's enough time to lose my train of thought.

Plus I'm likely to get distracted if I open another window whereas the only popup ads you'll see on paper are from those delightful children's books.

What's more paper allows me to have a 'multi screen' effect. I can have my code editor open on my laptop and my task list next to me on a piece of paper.

How might app developers draw lessons from paper?
Here are three ideas I have:
1. Explicitly encourage people to use your app in a multi-display environment: research backs up my preference for having a notepad next to me. According to Microsoft, NEC and Apple (no bias at all I'm sure!), people with multiple monitors are far more productive. To make things more objective, this 2014 study (not funded by monitor manufacturers this time) found that researchers could be 36.5% more productive when using two displays to conduct systematic reviews. Most apps have an introductory tutorial that explains how to use them. Why not say outright: "You'll find it much easier to use <insert-awesome-app-name-here> if you get a second monitor or set up your iPad next to you so you can glance across rather than having to switch windows on your laptop." I've never seen a piece of software that has explicitly suggested this.

2. Focus on interoperability: the great thing about paper is that you can slot it inside a notepad or punch holes in it and stick it in a 3 ring binder. Men may be their own islands but apps should not be. What annoys me is when I can't get my data out of an app to connect it to another tool. I like Google Spreadsheets because it's so easy to copy and paste data out.

3. Don't be unique: I get put off apps when they have unique user interfaces that I haven't seen before. Notepads come in all sizes and colours but the fundamental process of writing on them is exactly the same. All I need is a pen or pencil and I'm sorted. With apps though, it can be incredibly confusing if the developers haven't followed good UX practices. This is where trends like Google's material design standards are so useful. Even if the standard isn't optimal (e.g. material overlay buttons can be annoying), at least everyone is used to using it.

How might users avoid application fatigue?
1. Get a second display. As mentioned above, it's a lot easier to use multiple apps if you have more than one display. If you don't want to use a second monitor, take advantage of your phone or tablet. One example could be to have your task list open on your phone and your main activity on your computer. If you have an idea while you're working, don't switch tabs on your computer, just open up your phone and put it in there.

2. Slow down: just as you shouldn't try to master more than one habit at a time, nor should you try and learn several apps at the same time. I've done this on many occasions and what ends up happening is I get overwhelmed and ditch all of them. Better to choose one kind of app (e.g. book keeping), experiment with a few options, choose one you like and then focus on learning the traps.

3. Customise your apps: out of the box, most apps won't meet your needs. It's impossible for the developers to get everything perfect for every kind of user. You'll need to spend some time yourself (or engage a system integrator) tweaking the settings and integrate them with your other systems.

4. Connect the dots: the bane of anyone's existence is double entry. If you have to type something into two places, chances are you'll ditch the software in short order. Look at using services like Zapier or Cloutex to synchronise your apps so they play together nicely.

Interested in your thoughts. Have you experienced application fatigue? How do you avoid it?

Wednesday, June 3, 2015

Add related Notes to a Zoho CRM Contact from custom script

This post is a response to a question on the Zoho CRM forums:

Is it possible to relate additional notes to a Contact from a custom deluge script ? 

I guess it could be done by calling the external API postUrl() but I'm wondering if it can be done directly by something like zoho.crm.create()

It is indeed possible. Here's a code snippet:

And the outcome:

Zoho CRM Custom Commands for a list view

This post is in response to a question on the forums:
"Hi,Using Zoho CRM, I need to provide my users with some custom commands on the Contacts view list. These commands would invoke a custom deluge script."

I've faced this issue in the past. My solution is as follows:

1. Create a checkbox field for the Contacts module called "Run custom function"

2. Create a workflow that checks for field updates to the "Run custom function" field

3. Trigger a custom function from that workflow that does whatever you want and also resets the checkbox to false so that the user can trigger it again. For an example of a custom function, check out my post on quickly generating call logs.

In this way, a user can mass update the checkbox to run custom functions on all of the records.

searchRecords with multiple criteria in Zoho CRM API

NB: this blog post is no longer relevant as API v2 lets you use searchRecords with multiple criteria :)

I discovered something really cool tucked away in the Zoho CRM forums today. For the history, check out this thread. In summary, the searchRecords API task in Zoho CRM is impossible to use if you have multiple criteria and in general it's pretty annoying to get the single criterion right. In the forum thread, Zoho Support advised that you can actually use getRecords with a view name. This feature is not documented on the getRecords page at all but I can confirm it works:D

This is really, really cool. It's going to make my life as a Zoho dev much easier! Instead of having to do something really inefficient and ugly like:
leadRecords = zoho.crm.searchRecords("Leads","(Created Time|<|" + yesterday_date +")",fromIndex,toIndex);
for each ele in leadRecords
lead_source = ele.get("Lead Source");
createTime=(ele.get("Created Time")).toDate();
info "Found lead with create time: " + createTime;
if(dayDiff  <=  2 && lead_source == "")

I can just create a view called 'ClientWebsite leads in last 3 days' with relevant criteria and do:
leadRecords = zoho.crm.getRecords("ClientWebsite leads in last 3 days"); 

If you've struggled with cludgey searchRecords tasks in the past, you're going to love this trick:D

Sunday, May 31, 2015

Cohort analysis of CRM data using Zoho Reports

Cohort analyses are super handy if you're running a subscription business and want to see changes in ARR/MRR (annual/monthly recurring revenue). I've been thinking about how to achieve this for Zoho CRM data. A tip from Zoho Reports about using the color option in a chart gave me the answer.

To get this chart, I created a query table that combines the Invoice and Account modules and uses the quarter/year functions to group cohorts. The query is:
(year("Accounts"."Created Time") + '-' + quarter("Accounts"."Created Time")) as "Quarter joined",
"Accounts"."Account Name",
FROM  "Accounts" JOIN "Invoices" ON "Accounts"."ACCOUNTID"  = "Invoices"."Account Id" 

Tracking real sales conversion rates for cold leads using Zoho Reports + Zoho CRM

The Zoho Reports team helped me out with a tricky report to show the lead to won potential conversion rate. To explain the report, let's consider this scenario:
1. The business had 1000 leads entered into the CRM through telemarketing
2. Salespeople then qualified those leads and converted 50 of them to opportunities
3. The sales team then closed 10 of those leads

Based on those stats, we'd expect the lead to won potential win rate to be 1% (10/1000). In the default Zoho Reports conversion stats, you can only see potential to closed potential conversion rates. This stat is misleadingly high (10/50 = 20%) because it's only considering converted leads and ignoring junk/lost leads.

If the sales team really closed 20% of cold leads, you would probably see them usurping Brian Tracy on the speaking circuit. In reality, they're decent (1% conversion) but not world beating. I don't know about you, but I prefer to deal with reality.

How to generate true conversion rate stats using Zoho Reports
Courtesy of Anand and the amazing Zoho Reports CS team.

1. Set up a new query table using this query:
l."Lead Source",
l."Created Time",
s."Forecast Type"
FROM  "Leads" l LEFT JOIN "Sales" s ON l."LEADID"  = s."LEADID"  
2.  Set up a new report based on that table
I've used aggregate formulae as well:
e.g Won Potentials = countif("Sale Conversion"."s.Forecast Type"='Won')

How to quickly add call logs to Zoho CRM leads using workflows

Want a faster way to add call logs? Check out this video that shows you how to add call logs by ticking a box. (Warning: Enterprise Edition + deluge scripting skills needed).

Saturday, May 30, 2015

Calculating amount of Zoho CRM potential based on associated products

If you link products to your potentials in Zoho CRM, you can dynamically calculate the total amount of a potential by using a custom function + a workflow.

Here's the code:

Performing mass updates on thousands of Zoho CRM records using custom functions

Need to mass update thousands of Lead records in Zoho CRM and can't be bothered manually clicking through tens of pages and doing mass update? Here's an example of using a custom function to achieve this. In this case, I needed to merge several notes fields into one text area field as the multiple note fields were becoming unwieldy.

Wednesday, May 27, 2015

How to copy and paste form fields in Zoho Creator using Form Definition

I had to replicate a bunch of fields in a Zoho Creator form (i.e. I'd created them for client 1 and then needed to recreate them for client 2). I figured it would be faster to go into the form definition and copy and paste elements there rather than creating them via the UI. It ended up taking longer haha. For some reason the form definition seems to be very temperamental. I can't precisely tell you what ended up allowing it to work, but here are some things that you definitely can't do:

1. Have a field with the same ID as another field (display name can be duplicate though)

2. Have any comments in the form definition.

I was plagued with "Error: null" (gotta love ZC's highly descriptive error messages!)

Wednesday, May 20, 2015

Work around for annoying auto-indentation in Zoho Creator free flow scripting mode

If you're like me, you probably hate the auto-indentation feature in Zoho Creator. It always puts braces in the wrong positions and indents at the wrong level. I got sick of having to backspace 20 times to get indentation looking good so looked for another solution.

I found it in

You can chuck your Deluge script in there and it will indent it nicely for you:)

Getting Zoho CRM user details from Zoho Creator

Creator doesn't have a helper method for accessing Zoho CRM user details so you have to directly access the API. Here's a code snippet that might help:

Tuesday, May 19, 2015

Firefox webdriver not working properly? Try downgrading Firefox

I spent several hours trying to get my Selenium script working properly. FirefoxDriver flat out refused to work, ChromeDriver wasn't taking screenshots, complaining about not having the automation extension installed, and PhantomJS wasn't suitable because I needed to take screenshots of Flash-generated reports (*groan*). Eventually I realised that Firefox had auto-updated to v38 and broken Selenium as a result. I uninstalled v38, reinstalled v34 (and disabled auto updates) and it now works like a charm:) Hope this saves you some pain!

Sunday, May 17, 2015

Changing lead privacy settings in Zoho CRM

Need to make leads private so that salespeople can't see each other's leads? Here's a quick guide.

Go to Setup

Click on data sharing settings

Review the current settings

Edit the data sharing settings for Leads

Change Default Access to Private

Click on Save

Saturday, May 16, 2015

Deserialization in Ember Data (CLI edition May 2015)

I was working on a side project to learn Ember JS recently and hit a major roadblock with deserializing data from a REST API. I have a model that looks like this:

Ember therefore expects a JSON payload that looks like this:
However, the API (from Kimono) actually returns a payload with the people array embedded within a results array:
I spent hours trying to figure out how to use the deserialize methods to extract the people array from the results array. What frustrated me was that I couldn't really find any examples of how to use the deserialize methods. Maybe it's super basic for most people but I'm an Ember noob and couldn't figure it out for ages.
To help you avoid my teeth gnashing, here's the code I wrote for my serializer.
To explain what's going on here, we have to override a few methods: extractSingle (if there's only one person returned), extractArray (if you used findAll) and normalizeHash (used by both of the two previous methods).
extractSingle and extractArray are frustratingly simple. To look at them, you'd think it took me 5 minutes to write the code not 4 hours hahaha! Hopefully you'll find it super easy to write deserializers now.
The key things to note are that you can delete elements from the payload, e.g. delete payload.results; In this case, I completely overrode the payload as the only thing that I needed was the people array.
Something else to be mindful of is that if the API has different variable names to your model, you can add a new variable name to the hash (e.g. hash.fullName =;) and then delete the old variables.
It does seem to be relatively important to clean up unused variable names because otherwise Ember warns you about variables that aren't found in the model. It won't break your application but it does make your console messier than it needs to be.
Hope this little guide helps! Let me know if you have any questions.

Monday, May 11, 2015

How to mass update lookups in Zoho CRM

You'll notice that you can't mass update lookup fields in Zoho CRM via the UI. Here's a code snippet to show how to update lookup fields using Deluge custom functions.

You then have to set up a workflow to run that custom function on a certain trigger. Feel free to ping me if you can't figure it out.

Saturday, May 9, 2015

Accessing query params from a route in Ember CLI in May 2015

I just spent 90 minutes trying to figure this out so hopefully this will help other people avoid similar pain! If you want to access query params from a route in Ember it's actually really simple: just declare the query params in the controller first.

export default Ember.Controller.extend({

queryParams: ['city', 'company'],

And then in the route:
model: function(params) {
var city =;
var company =;

Friday, May 8, 2015

Trick to calling other custom functions from within Zoho CRM custom function

One thing that has bugged me about Zoho CRM custom functions is that they can quickly become very bloated because the programming interface steers you towards putting all the code in one method. I realised today that there is a way around that though. If you add the namespace 'workflowspace' before the custom function name, you can call it from another custom function.

E.g. workflowspace.round_robin_engagements(engagement_id.toLong());

Monday, May 4, 2015

Using PhantomJS with PHPUnit

I found it pretty hard to get PHPUnit working with PhantomJS so thought I'd put together a quick tutorial.

Step 1: Make sure you have the following dependencies in your composer.json and run composer update:
"require-dev": { 
      "facebook/webdriver": "dev-master",  
       "phpunit/phpunit": "4.0.*", 
       "phpunit/phpunit-selenium": ">=1.2" 
Step 2: Download PhantomJS and Selenium Server and put them in a new directory 'bin' in your tests folder. (Might not be the most optimum place to stash them but it works for now)

Step 3: Add the following code to your tests folder as TestScaffold.php. It will start the Selenium server if it's not already running and boot up PhantomJS for each test.
Step 4: Write a test that extends the scaffold

Saturday, February 28, 2015

Configuring webform URLs for Zoho CRM

Are you finding that your Zoho CRM web forms don't do anything? I've learned the hard way that it's generally because the form URL has not been set correctly. It seems like a throw-away setting, but it actually won't work unless you configure the form URL to be exactly where the form is on your website. Use this link to access the web form page, then click on the form name and finally click on "Next Step" to show this dialog.

Tuesday, February 17, 2015

Keeping your OnInput code DRY in Zoho Creator

DRY (don't repeat yourself) is one of the most important software development patterns to follow. If you copy and paste code, then if there's a bug, you'll have to go back and edit several code blocks which is likely to lead to even more bugs.

With Zoho Creator OnInput scripts, it can be challenging to apply DRY because you can't really use functions within an OnInput script. You can call a function at an app level, but this function won't be able to access any of the current form fields.

Here's an example I encountered recently when reviewing code from one of my devs.

As you'll read from the comments, this code isn't DRY. The same exact code block was used for several other OnInput functions. (The goal of this block is to update a subtotal field at the bottom of the form when the quantity or price is changed).

As mentioned, you can't use a custom function to achieve this, but you can put the code in one place. I typically create a new decision box field (e.g. Update_Sub_Totals) and put the code in there.

if (input.Update_Sub_Totals == true){
             //update sub-total code
             code block goes here
             //reset the check box so it can be used
             input.Update_Sub_Totals = false;

Monday, February 16, 2015

Configuring page breaks in Zoho Creator

I've had a helluva time trying to get page breaks to behave properly in Zoho Creator HTML pages when you export them as a PDF. Here's an example:
After trying absolutely everything, I finally realised that it just is not possible to properly configure page breaks in PDF mode.

However, there is a work-around. Use print mode and then use a print-to-pdf driver to save the output as a PDF.

Then all you have to do is add this CSS to the top of your page:

<style type="text/css">
   table { page-break-inside:auto }
   tr    { page-break-inside:avoid; page-break-after:auto }
   @media all {
.page-break  { display: none; }
   @media print {
.page-break  { display: block; page-break-before: always; }

This will prevent page breaks from occurring within tables. If you want to force a page break, you just have to add <div class="page-break"></div>.

Tuesday, January 27, 2015

How to email accounts from Zoho CRM

Bashing your head against a wall trying to figure out how to email your accounts from within Zoho CRM? This screencast explains how. If you need any further help with this or with anything related to Zoho CRM, give me a shout at or call me on 0414 885 787 I run a Zoho CRM consultancy ( with offices in Sydney and Melbourne.

Saturday, January 24, 2015

Auto populating custom field in Zoho CRM using criteria

I saw this question in the Zoho forums and thought I'd respond:
Is there way to auto-populate a field given a set of criteria?

For example, I'd like all Potentials that close between a set of dates (i.e. between 1/1/2015 and 5/1/2015) to automatically populate the same text in a custom field I've called "Group."

My Answer

  1. void   modify_group_for_jim_based_on_closing_date  ( int potential_id   )
  2. potential = zoho.crm.getRecordById("Potentials",input.potential_id);
  3. the_closing_date=(potential.get("Closing Date")).toDate();
  4. date_window_1=("1/1/2015").toDate();
  5. date_window_2=("1/5/2015").toDate();
  6. date_window_3=("1/6/2015").toDate();
  7. date_window_4=("1/11/2015").toDate();
  8. potential_map=map();
  9. if((the_closing_date  >=  date_window_1)  &&  (the_closing_date  <=  date_window_2))
  10. {
  11. potential_map.put("Group","Group 1");
  12. }
  13. else if((the_closing_date  >=  date_window_3)  &&  (the_closing_date  <=  date_window_4))
  14. {
  15. potential_map.put("Group","Group 2");
  16. }
  17. else
  18. {
  19. potential_map.put("Group","Unknown Group");
  20. }
  21. potential_id_str=input.potential_id.toString();
  22. updatedPotential = zoho.crm.updateRecord("Potentials",potential_id_str,potential_map);
  23. info "Response: " + updatedPotential;

Selecting multiple products and associating them with a Zoho CRM lead

I saw a question in the Zoho CRM forums that I thought I'd answer:
I created a custom field in the Lead form for Product and it is linked to our Product list in Zoho so when we click on the field to fill it in for a lead, it pulls up our Product list. However, once I click on one product, it automatically populates the field with that product without allowing me to select additional products. (Our leads and customers are often interested in multiple products.) Is there a way to keep the field linked to our Zoho Product list and make it multi-pick? 
My answer
I'd recommend using the Products related list for this purpose. Here's a screencast showing you how. You can report on which products are associated to which leads by choosing both modules when creating a report.


How do you use Price Books in Zoho CRM?

What is a price book and why would you use one? In this video, I walk you through the process of setting up price books so you can have volume discounts for your best clients.

Got more questions? Leave a comment or ping me at