For Zoho Services only:

I'm actually part of something bigger at Ascent Business Solutions recognized as the top Zoho Premium Solutions Partner in the United Kingdom.

Ascent Business Solutions offer support for smaller technical fixes and projects for larger developments, such as migrating to a ZohoCRM.  A team rather than a one-man-band is always available to ensure seamless progress and address any concerns. You'll find our competitive support rates with flexible, no-expiration bundles at  For larger projects, check our bespoke pricing structure and receive dedicated support from our hands-on project consultants and developers at

The team I manage specializes in coding API integrations between Zoho and third-party finance/commerce suites such as Xero, Shopify, WooCommerce, and eBay; to name but a few.  Our passion lies in creating innovative solutions where others have fallen short as well as working with new businesses, new sectors, and new ideas.  Our success is measured by the growth and ROI we deliver for clients, such as transforming a garden shed hobby into a 250k monthly turnover operation or generating a +60% return in just three days after launch through online payments and a streamlined e-commerce solution, replacing a paper-based system.

If you're looking for a partner who can help you drive growth and success, we'd love to work with you.  You can reach out to us on 0121 392 8140 (UK) or  You can also visit our website at

ZohoCreator: Basic Widget with Zoho Data

A follow on from my article Zoho Creator: Create a Widget which uses JavaScript back from 2020 with a few adjustments now in 2024.

This widget will only work within Zoho Creator. If you want a solution which sits on an external website and which talks to Zoho, then setup an externally hosted web app with the usual JavaScript frameworks and have it send AJAX commands to a server which reads/writes information to your Zoho instance via API. No need for the Zoho Widget SDK.
At time of print, I felt the documentation was a little sparse on how to connect a JS widget to the data held in Zoho Creator. Having this example for future use might save me some time. The following is the early version of a JS widget used for a customer and before I added all the layers of complexity, I want to have here an example that demonstrates a basic search on a table of data and returns one record as a result.

The use-case here is that we are enhancing a quote builder form in Zoho Creator. The JS widget (aka the Quote Builder) will need to post a new quote to the system as well as show previous orders.

We're going to use the Zoho Extension SDK. You should refer to my previous linked article but the revised instructions here should also help. Then lastly, I'll post the snippet of code using in the widget to connect to Zoho based on a parameter passed in the URL that a Zoho Creator Page can receive and pass to the JS widget.

the HTML
You may note that I have additional CSS and JS files. I like to keep the copies local (especially if the hosting is included) so the app doesn't suddenly stop working when a third-party CDN / API gets upgraded. Add these to the widget as you see fit but I'm including jQuery and Bootstrap:
<!doctype html>
<html lang="en">
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Company Name - Quote Builder</title>
    <link rel="stylesheet" href="/./css/main.css" />
    <link rel="stylesheet" href="/./css/bootstrap.min.css">
    <div class="container py-3 my-4">
      <h1>Hi <span id="greeting-name"></span></h1>

    <div class="b-example-divider"></div>

    <div class="col-lg-8 px-0 mx-auto">
      <div class="container px-4">
        <div class="row gx-5">
          <div class="col">
            <div class="p-3 border bg-light">You have <span id="ab-pending-quote-count">0</span> Pending Quote<span id="ab-pending-quote-count-grammar">s</span></div>
          <div class="col">
            <div class="p-3 border bg-light">You have <span id="ab-previous-quote-count">0</span> Previous Quote<span id="ab-pending-quote-count-grammar">s</span></div>

    <div class="b-example-divider"></div>

    <div class="d-grid gap-2 col-6 mx-auto">
      <button class="btn btn-primary" type="button">Get a New Quote!</button>

    <div class="b-example-divider"></div>

    <div class="invisible" id="debug"></div>

    <div class="container">
      <footer class="py-3 my-4">
        <p class="text-center text-muted">© <span class="year">1999</span> Joel Lipman Ltd.  All Rights Reserved</p>

    <script src="/./js/jquery-3.3.1.slim.min.js" crossorigin="anonymous"></script>
    <script src="/./js/bootstrap.bundle.min.js" crossorigin="anonymous"></script>
    <script src="/./js/widgetsdk-min.js" crossorigin="anonymous"></script>
    <script src="/./js/main.js" crossorigin="anonymous"></script>

  1.  <!doctype html> 
  2.  <html lang="en"> 
  3.    <head> 
  4.      <meta charset="utf-8"> 
  5.      <meta name="viewport" content="width=device-width, initial-scale=1"> 
  6.      <title>Company Name - Quote Builder</title> 
  7.      <link rel="stylesheet" href="./css/main.css" /> 
  8.      <link rel="stylesheet" href="./css/bootstrap.min.css"> 
  9.    </head> 
  10.    <body> 
  11.      <div class="container py-3 my-4"> 
  12.        <h1>Hi <span id="greeting-name"></span></h1> 
  13.      </div> 
  15.      <div class="b-example-divider"></div> 
  17.      <div class="col-lg-8 px-0 mx-auto"> 
  18.        <div class="container px-4"> 
  19.          <div class="row gx-5"> 
  20.            <div class="col"> 
  21.              <div class="p-3 border bg-light">You have <span id="ab-pending-quote-count">0</span> Pending Quote<span id="ab-pending-quote-count-grammar">s</span></div> 
  22.            </div> 
  23.            <div class="col"> 
  24.              <div class="p-3 border bg-light">You have <span id="ab-previous-quote-count">0</span> Previous Quote<span id="ab-pending-quote-count-grammar">s</span></div> 
  25.            </div> 
  26.          </div> 
  27.        </div> 
  28.      </div> 
  30.      <div class="b-example-divider"></div> 
  32.      <div class="d-grid gap-2 col-6 mx-auto"> 
  33.        <button class="btn btn-primary" type="button">Get a New Quote!</button> 
  34.      </div> 
  36.      <div class="b-example-divider"></div> 
  38.      <div class="invisible" id="debug"></div> 
  40.      <div class="container"> 
  41.        <footer class="py-3 my-4"> 
  42.          <p class="text-center text-muted">© <span class="year">1999</span> Joel Lipman Ltd.  All Rights Reserved</p> 
  43.        </footer> 
  44.      </div> 
  46.      <script src="./js/jquery-3.3.1.slim.min.js" crossorigin="anonymous"></script> 
  47.      <script src="./js/bootstrap.bundle.min.js" crossorigin="anonymous"></script> 
  48.      <script src="./js/widgetsdk-min.js" crossorigin="anonymous"></script> 
  49.      <script src="./js/main.js" crossorigin="anonymous"></script> 
  50.    </body> 
  52.  </html> 

the JavaScript
These are the contents of main.js and is working at time of print:
// Start with Zoho SDK stuff 
    .then(function(data) {

        // Initialize 
        var v_ShopifyID = "";
        var v_ShopifyEmail = "";
        var v_GreetingName = "";

        // Try and catch

            // Get Creator Parameters Passed in URL - Cannot use window.location URL 
            var queryParams = ZOHO.CREATOR.UTIL.getQueryParams();

            // Check parameters were even specified 
            if (queryParams.p_ShopifyEmail !== undefined) {
                v_ShopifyEmail = queryParams.p_ShopifyEmail;
            if (queryParams.p_ShopifyID !== undefined) {
                v_ShopifyID = queryParams.p_ShopifyID;
            // Setup a config to find this record (use a custom report that only has the 2 searchable fields)
            var config = {
                appName : "joes_quote_builder",
                reportName : "Contacts_Report_SearchableByWidget", 
                criteria : "(Primary_Email == \"" + v_ShopifyEmail + "\" && Shopify_ID == \"" + v_ShopifyID + "\")",
                page : 1,
                pageSize : 10
            // find the logged-in user record
                .then(function(response) {

                    // store the search results into an array
                    var recordArr =;
                    // quick loop to find the preferred name
                    for(var index in recordArr){
                        v_GreetingName = recordArr[index].Nick_Name;
                    // if not blank then let's display it
                    if(v_GreetingName != "")
                        // can't seem to do jQuery references within this SDK
                        document.getElementById('greeting-name').innerHTML = v_GreetingName;
        } catch(e) {

            document.getElementById('debug').innerHTML = "Sorry! We don't have any matching records.";


/* SAMPLE TO GET ONE RECORD - Working as of March 2024
        .then(function(data) {
            var config = {
                appName : "joes_quote_builder",
                reportName : "All_Customers",
                id : "123456789012345678"

                .then(function(response) {
                    document.getElementById('greeting-name').innerHTML =;

/* ************************************ */
/* Some non-Zoho JavaScript */
/* Set Copyright Year */
var today = new Date();
var currentYear = today.getFullYear();
$('footer span.year').text(currentYear);
  1.  // Start with Zoho SDK stuff 
  2.  zoho.creator.init() 
  3.      .then(function(data) { 
  5.          // Initialize 
  6.          var v_ShopifyID = ""
  7.          var v_ShopifyEmail = ""
  8.          var v_GreetingName = ""
  10.          // Try and catch 
  11.          try{ 
  13.              // Get Creator Parameters Passed in URL - Cannot use window.location URL 
  14.              var queryParams = zoho.creator.UTIL.getQueryParams()
  16.              // Check parameters were even specified 
  17.              if (queryParams.p_ShopifyEmail !== undefined) { 
  18.                  v_ShopifyEmail = queryParams.p_ShopifyEmail; 
  19.              } 
  20.              if (queryParams.p_ShopifyID !== undefined) { 
  21.                  v_ShopifyID = queryParams.p_ShopifyID; 
  22.              } 
  24.              // Setup a config to find this record (use a custom report that only has the 2 searchable fields) 
  25.              var config = { 
  26.                  appName : "joes_quote_builder", 
  27.                  reportName : "Contacts_Report_SearchableByWidget", 
  28.                  criteria : "(Primary_Email == \"" + v_ShopifyEmail + "\" && Shopify_ID == \"" + v_ShopifyID + "\")", 
  29.                  page : 1, 
  30.                  pageSize : 10 
  31.              } 
  33.              // find the logged-in user record 
  34.              zoho.creator.API.getAllRecords(config) 
  35.                  .then(function(response) { 
  37.                      // store the search results into an array 
  38.                      var recordArr =; 
  40.                      // quick loop to find the preferred name 
  41.                      for(var index in recordArr){ 
  42.                          v_GreetingName = recordArr[index].Nick_Name; 
  43.                          break
  44.                      } 
  46.                      // if not blank then let's display it 
  47.                      if(v_GreetingName != "") 
  48.                      { 
  49.                          // can't seem to do jQuery references within this SDK 
  50.                          document.getElementById('greeting-name').innerHTML = v_GreetingName; 
  51.                      } 
  53.                  })
  55.          } catch(e) { 
  57.              document.getElementById('debug').innerHTML = "Sorry! We don't have any matching records."
  58.          } 
  61.      })
  63.  /* SAMPLE TO GET ONE RECORD - Working as of March 2024 
  64.      zoho.creator.init() 
  65.          .then(function(data) { 
  66.              var config = { 
  67.                  appName : "joes_quote_builder", 
  68.                  reportName : "All_Customers", 
  69.                  id : "123456789012345678" 
  70.              } 
  72.              zoho.creator.API.getRecordById(config) 
  73.                  .then(function(response) { 
  74.                      document.getElementById('greeting-name').innerHTML =; 
  75.                      console.log(response)
  76.                  })
  77.          })
  78.  */ 
  80.  /* ************************************ */ 
  81.  /* Some non-Zoho JavaScript */ 
  82.  /* Set Copyright Year */ 
  83.  var today = new Date()
  84.  var currentYear = today.getFullYear()
  85.  $('footer span.year').text(currentYear)

Error(s) Encountered:
  • Error Status 401 Code 1030: Authorization Failure. The access token is either invalid or has expired. Please check your Zoho Account for more information. If your widget sits on an external server, it won't connect. I have tried publishing the Creator Widget page (doesn't work); then I have tried embedding the Widget page into another published Creator page (idem).
  • CORS Policy error(s): Check your design as you can have a JS widget talking to Zoho. You won't be able to pull/download files, even published ones, but you can display published image URLs (see Zoho Creator API 2.1: Download File).
  • Refused to connect to because it violates the following Content Security Policy directive: "connect-src don't bother. You're probably on an external server. Create your own web app on another server and setup a server to server API connection to your Zoho Creator instance.

Category: Zoho :: Article: 869

Credit where Credit is Due:

Feel free to copy, redistribute and share this information. All that we ask is that you attribute credit and possibly even a link back to this website as it really helps in our search engine rankings.

Disclaimer: Please note that the information provided on this website is intended for informational purposes only and does not represent a warranty. The opinions expressed are those of the author only. We recommend testing any solutions in a development environment before implementing them in production. The articles are based on our good faith efforts and were current at the time of writing, reflecting our practical experience in a commercial setting.

Thank you for visiting and, as always, we hope this website was of some use to you!

Kind Regards,

Joel Lipman

Related Articles

Joes Revolver Map

Joes Word Cloud


Badge - Certified Zoho Creator Associate
Badge - Certified Zoho Creator Associate

Donate & Support

If you like my content, and would like to support this sharing site, feel free to donate using a method below:

Donate to Joel Lipman via PayPal

Donate to Joel Lipman with Bitcoin bc1qf6elrdxc968h0k673l2djc9wrpazhqtxw8qqp4

Donate to Joel Lipman with Ethereum 0xb038962F3809b425D661EF5D22294Cf45E02FebF
© 2024 Joel Lipman .com. All Rights Reserved.