Widget Upload to CRM Fails with “Page Not Found” – Even with Correct Index Path

Widget Upload to CRM Fails with “Page Not Found” – Even with Correct Index Path

I'm building a simple widget to export Contact data to CSV in Zoho CRM, triggered via a custom button. The widget uploads cleanly, appears in the widget list, and is successfully assigned to a Contact detail view via a custom button. But when clicked, it displays a “Page Not Found” error instead of loading the index.html.

ZIP File Structure (Flat ZIP):

files.zip
├── index.html
├── script.js
└── manifest.json

manifest.json:

json
{
  "platform": "CRM",
  "widgetType": "web",
  "name": "Contact CSV Export",
  "location": {
    "Contacts": {
      "button": {
        "label": "Download CSV"
      }
    }
  },
  "url": "/index.html",
  "version": "1.0"
}

index.html:

html
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Download Contact CSV</title>
</head>
<body>
  <button onclick="downloadCSV()">Download CSV</button>
  <script src="script.js"></script>
</body>
</html>

script.js:

javascript
function downloadCSV() {
  ZOHO.CRM.API.getRecord({ Entity: "Contacts", RecordID: recordId }).then(function(data) {
    let contact = data.data[0];
    let csvContent = `ID,First Name,Last Name,Email\n${contact.id},${contact.First_Name},${contact.Last_Name},${contact.Email}`;
    let blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
    let link = document.createElement("a");
    link.href = URL.createObjectURL(blob);
    link.download = "contact.csv";
    link.click();
  });
}

let recordId = null;

ZOHO.embeddedApp.on("PageLoad", function(data) {
  recordId = data.EntityId[0];
  console.log("Contact ID loaded:", recordId);
});

ZOHO.embeddedApp.init();

What I've Tried:

  • Ensured ZIP includes only the three required files with no nested folders.

  • Manifest references /index.html (with leading slash, as required).

  • Deleted and recreated the widget and associated button.

  • Reuploaded ZIP multiple times via Developer Hub.

  • Cleared browser cache and logged out/in to reset possible caching issues.

Still getting “Page Not Found” when clicking the custom button from the Contact detail page.

Help Requested:

What else can I check to ensure Zoho loads index.html correctly? Is there a deployment or validation step I’m missing—even after successful upload?

Any guidance or proven examples would be hugely appreciated.

    • Sticky Posts

    • Kaizen #197: Frequently Asked Questions on GraphQL APIs

      🎊 Nearing 200th Kaizen Post – We want to hear from you! 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 #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.
    • Celebrating 200 posts of Kaizen! Share your ideas for the milestone post

      Hello Developers, We launched the Kaizen series in 2019 to share helpful content to support your Zoho CRM development journey. Staying true to its spirit—Kaizen Series: Continuous Improvement for Developer Experience—we've shared everything from FAQs
    • Kaizen #193: Creating different fields in Zoho CRM through API

      🎊 Nearing 200th Kaizen Post – We want to hear from you! 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.
    • Client Script | Update - Introducing Commands in Client Script!

      Have you ever wished you could trigger Client Script from contexts other than just the supported pages and events? Have you ever wanted to leverage the advantage of Client Script at your finger tip? Discover the power of Client Script - Commands! Commands