Search code examples
javascriptwebhookszendesk

Zendesk App Error & Delayed/Failed Webhook Post


I am building a Zendesk app that will post a variety of information to a webhook. Currently, I am running into two issues. The client.invoke() function says it is not a function in the console when the send email button is pressed. Additionally, sometimes the after the button is pressed, the app will successfully post to the webhook, other times it won't post at all. I cannot narrow down what is causing the discrepancies on when it posts. I'm unsure if this is related to the app I've built or an issue interacting with Zendesk.

Here is the app:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <link href="https://cdn.jsdelivr.net/bootstrap/2.3.2/css/bootstrap.min.css" rel="stylesheet">
  <link href="main.css" rel="stylesheet">
  <script src="https://cdn.jsdelivr.net/jquery/3.2.1/jquery.min.js"></script>
  <script type="text/javascript" src="https://assets.zendesk.com/apps/sdk/2.0/zaf_sdk.js"></script>
  <script src="https://cdn.jsdelivr.net/handlebarsjs/4.0.8/handlebars.min.js"></script>
</head>
<body>
  <script>  
  var client = ZAFClient.init();
  client.invoke('resize', { width: '100%', height: '450px' });
  client.get('ticket.brand.subdomain').then(
    function(data) {
      var subdomain = data['ticket.brand.subdomain'];
      console.log('Zendesk Subdomain is ' + subdomain);
      document.getElementById('subdomainform').value = subdomain;
  }
);
  client.get('ticket.organization.id').then(
  function(data) {
    var org_id = data['ticket.organization.id'];
    console.log('Org id is ' + org_id);
    document.getElementById('orgidform').value = org_id;
  }
);
  </script>
  <form name="submissionForm">
    <div class="formBox">
      <label for="title">First Name</label>
      <input type="text" id="firstName" placeholder="First Name"/>
    </div>
    <div class="formBox">
      <label for="title">Last Name</label>
      <input type="text" id="lastName" placeholder="Last Name"/>
    </div>
    <div class="formBox">
      <label for="title">Email</label>
      <input type="text" id="email" placeholder="Email"/>
    </div>
    <div class="formBox">
      <select id="rescom">
        <option value="residential">Residential</option>
        <option value="commercial">Commercial</option>
      </select>
    </div>
    <div class="formBox">
      <button id="btn">Click to Send Email</button>
    </div>
    <div><p id="explain">The fields below are ready-only and required for submission. If you don't see them, please refresh the app.</p></div>
    <div class="formBox">
      <input type="text" id="subdomainform" readonly="readonly"/>
    </div>
    <div class="formBox">
      <input type="text" id="orgidform" readonly="readonly"/>
    </div>
  </form>
  <script>
    let content = [];
    const addDay1 = (ev)=>{
      let information = { 
        id: Date.now(),
        firstName: document.getElementById('firstName').value,
        lastName: document.getElementById('lastName').value,
        email: document.getElementById('email').value,
        subdomain: document.getElementById('subdomainform').value,
        orgid: document.getElementById('orgidform').value,
        rescom: document.getElementById('rescom').value
      }
      content.push(content);
      document.forms[0].reset();

      const Url ='{PLACEHOLDER}';

    $.ajax({
      url: "{WEBHOOK URL}",
      type: "POST",
      dataType: 'json',
      data: {information},
      complete: function(){alert("Failure")}
    });
    }
    document.addEventListener('DOMContentLoaded', ()=>{
      document.getElementById('btn').addEventListener('click', addDay1);
    });
  </script>

</body>
</html>

What am I missing? Appreciate any and all help that can be provided.


Solution

  • This was solved my a community manager from Zendesk. See post below:

    Make sure ZAFClient is fully registered before attempting to do subsequent ZAFClient methods. Something like:

    client.on('app.registered', e => {
    
      client.get('ticket.brand.subdomain').then(
        function(data) {
          var subdomain = data['ticket.brand.subdomain'];
          console.log('Zendesk Subdomain is ' + subdomain);
          document.getElementById('subdomainform').value = subdomain;
        }
      );
    
      client.get('ticket.organization').then(
        function(data) {
          var org_id = data['ticket.organization.id'];
          console.log('Org id is ' + org_id);
          document.getElementById('orgidform').value = org_id;
        }
      );
    
    }) The "not a function in the console" error is caused from the app's HTML page being resubmitted again when you click the button. In
    

    Zendesk Apps framework, the connection from the app (using ZAFClient.init()) to the main agent window is done through parameters that are passed to the app when the framework first loads it. You can see this in your browser's Network tab if you look for something like "iframe.html?origin=https%3A%2F%2Fyour_subdomain.zendesk.com&app_guid=ff7133010-abff-4f1c-a7bf-ff7133fff7133" -- the origin and app_guid params are needed to make the connection. When you resubmit the page, those parameters no longer are passed on the new page reload and the new call to ZAFClient.init() doesn't successfully initialize. Thus leading the error when the now invalid 'client' object is attempting to be used to call 'invoke'. You have to treat these app pages like single-page apps.

    Phew! All that said -- you can still use HTML functionality, just don't have it resubmit the entire page when the button is pressed. You can do this by adding type="button" to the button tag.

    Click to Send Email

    See also: HTML button to NOT submit form

    Hope this gets you on your way!