In the previous tutorials in this series, you designed the user interface for an app named Requester X-ray. In this tutorial, you'll get the information about the requester and display it in the UI.

The app will fetch the requester information from the Zendesk REST API. It'll make a request to the Show User endpoint:

GET /api/v2/users/{id}.json

An endpoint is a URL where you can get or set information about a resource. The Show User endpoint includes an id variable, which is a Zendesk Support user ID. Your app needs to supply the ID to the endpoint but it doesn't know it in advance. The ID depends on the ticket the agent is viewing in Zendesk Support.

Let's work out the app logic. First, your app should access the ticket that's currently open in the agent interface and get the requester's user ID. Second, the app should use the ID to request the user information from the Show User endpoint. If the request is successful, the app should show the requester's information in the requester template. If the request fails, the app should show an error message in a different template. The app logic looks like this:

This tutorial covers the steps to building the app logic:

  1. Calling the framework API
  2. Calling the REST API
  3. Displaying the requester information
  4. Formatting the dates
  5. Displaying the error message
  6. Code complete!

This tutorial is part of a series on building a Zendesk app:

Calling the framework API

The first step is to get the ID of the requester from the ticket open in the agent interface.

How it works

The Apps framework includes a ticket API that gives you access to the ticket data of any ticket open in the agent interface.

The framework's Ticket object doc lists the ticket properties you can retrieve. Scanning the list in the doc, you find one in particular, the ticket.requester property, which returns a user object describing the user. Digging into the User object doc, you find the user.id property, which returns the user's ID as an integer.

Armed with this information, you can use the following path to get the requester's ID:

'ticket.requester.id'

In ZAF v2, you use the client.get(_path_) method to query the Data API. The method doesn't return the values directly. Instead, it returns an object containing a property with a name that corresponds to the API path. Example:

{  'ticket.requester.id': 29043265}

The name string contains periods, so use JavaScript bracket notation to retrieve its value:

var client = ZAFClient.init();client.get('ticket.requester.id').then(function(data) {  console.log(data['ticket.requester.id']); // something like 29043265});

Communication between an iframe and its parent page is asynchronous. In other words, the browser doesn't wait for a response to a request. It continues working normally while the request is being handled. You get a callback when the response is received. The .then()method is used to wait for the callback. The method returns a Promise and takes two arguments: a function to run on success and a function to run on failure. The statement basically means, "make the request, then do one of these two things after you know the outcome."

client.get('ticket.requester.id').then(  run_this_fn_on_success,  run_this_fn_on_failure);

For more information, see Promise.protoype.then() on the Mozilla Developer Network.

Getting the requester's user id

In the previous section, you learned you can use the following path to get the requester's user ID:

'ticket.requester.id'

Plug the path in the client.get(_path_) method to get an answer.

To get the requester's user id

  1. In the main.js file, insert the following statement in your self-invoking function:

    ...
    client.get('ticket.requester.id').then(  function(data) {    var user_id = data['ticket.requester.id'];    console.log('Requester id is ' + user_id);  });

    The statement gets the user id of the requester of the ticket currently open in the agent interface. After getting a successful response, it assigns it to a variable named user_id.

  2. Check the id by reloading the app and looking for the console.log message in your browser console.

    If your ZCLI server is not already started, see Testing the app for instructions.

  3. Replace the console.log() statement with the following function call:

    requestUserInfo(client, user_id);

    The call passes the client and id variables to a new function called requestUserInfo(), which you'll create in the next section. Its job will be to make an HTTP request to the Users API in the Zendesk REST API. You pass client along because the function will need the ZAFClient object to make the HTTP request.

Your self-invoking function so far should look as follows:

(function () {  var client = ZAFClient.init();  client.invoke('resize', { width: '100%', height: '120px' });
  client.get('ticket.requester.id').then(    function(data) {      var user_id = data['ticket.requester.id'];      requestUserInfo(client, user_id);    }  );})();

Calling the REST API

Now that your app can get the requester's ID from a ticket, you can use it to get the requester's "X-ray" user information from the Zendesk API.

Defining the API request

You can use the client.request() method to make HTTP requests to external APIs. The method takes an object that defines the request settings as an argument. Example:

var settings = {  url:'https://www.example.com/api/resource.json',  type:'GET',  dataType: 'json'};
client.request(settings).then(  function(data) {    console.log(data);  },  function(response) {    console.error(response.responseText);  });

What are the request settings for the X-ray app? The REST API doc for the Show User endpoint provides all the information you need:

  • the url is '/api/v2/users/{id}.json'. For Zendesk endpoints, you don't need to specify the full URL. For other endpoints, specify the full URL, such as 'https://www.example.com/api/resource.json'
  • the type is GET
  • the dataType is json

Getting the requester's information

In the previous section, you learned you can use the following settings to make an HTTP request to the Show User endpoint:

var settings = {  url:'/api/v2/users/{id}.json',  type:'GET',  dataType: 'json'};

To get the requester's information

  1. Insert the following function in the main.js file:

    function requestUserInfo(client, id) {  var settings = {    url: '/api/v2/users/' + id + '.json',    type:'GET',    dataType: 'json',  };
      client.request(settings).then(    function(data) {      console.log(data);    },    function(response) {      console.error(response);    }  );}

    If the request is successful, the app displays the data in the console with console.log(data). If the request is not successful, the app displays the response in red in the console with console.error(response).

  2. Check the results of the request in your browser console. Save the file, reload the app, and look for the console.log message in the console. You should see an object containing the user data.

  3. Test the results in case of failure by introducing a typo in one of the request settings. Save the file, reload the app, and look for the console.error message in the console.

    Remember to fix the typo in your request settings after you're satisfied that the error handling works as intended.

  4. In the first callback function, replace the console.log statement with a call to your showInfo() function:

    showInfo(data);
  5. In the second callback function, replace the console.log statement with a call to your showError() function:

    showError(response);

    Your requestUserInfo() function should look as follows:

    function requestUserInfo(client, id) {  var settings = {    url: '/api/v2/users/' + id + '.json',    type:'GET',    dataType: 'json',  };
      client.request(settings).then(    function(data) {      showInfo(data);    },    function(response) {      showError(response);    }  );
    }

Displaying the requester information

In the previous section, you passed the user information to the showInfo() function call after getting a successful response from the Zendesk API.

In this section, you take the information and display it in your requester template.

  1. In your showInfo() function definition (not the showInfo() function call), add an argument named data to receive the user data:

    function showInfo(data) {...
  2. In the showInfo() function, replace the hard-coded values in your requester_data object with the values in your data argument:

    var requester_data = {  'name': data.user.name,  'tags': data.user.tags,  'created_at': data.user.created_at,  'last_login_at': data.user.last_login_at};
  3. Save the file and click Reload All Apps in Zendesk Support to test your work. If your ZCLI server is not already started, see Testing the app for instructions.

    Note that the Tags line won't appear if the user doesn't have any tags in their Zendesk profile.

The dates aren't very user friendly. You decide to spend a few minutes fixing the problem.

Formatting the dates

You can use standard JavaScript Date methods to format the dates.

  1. Add the following helper function to your main.js file:

    function formatDate(date) {  var cdate = new Date(date);  var options = {    year: "numeric",    month: "short",    day: "numeric"  };  date = cdate.toLocaleDateString("en-us", options);  return date;}

    The function creates a JavaScript Date object from the date string passed to the function. It formats it using a Date formatting method and returns the modified date.

  2. Back in your showInfo() function, pass both dates to the helper function:

    'created_at': formatDate(data.user.created_at),'last_login_at': formatDate(data.user.last_login_at)
  3. Save the main.js file and click Reload All Apps in Zendesk Support to test your work.

    The dates should be friendlier than before.

Displaying the error message

In Calling the REST API above, you passed a response object to the showError() function after getting an error response from the Zendesk API:

showError(response);

In this section, you take the information and display it in your error template.

  1. Add an argument to your showError() function definition to receive the error data:

    function showError(response) {...
  2. In the showError() function, replace the hard-coded values in your error_data object with the values in your response object:

    var error_data = {  'status': response.status,  'statusText': response.statusText};
  3. Test the error page by making a typo in one of the request settings in requestUserInfo(). Save the file and reload the app. Your error template should be displayed.

    Remember to fix the typo in your request settings after you're satisfied that the error template works as intended.

Code complete!

Congratulations! You developed your first working ZAF app. The final version of your main.js file should look like this:

(function () {  var client = ZAFClient.init();  client.invoke('resize', { width: '100%', height: '120px' });
  client.get('ticket.requester.id').then(    function(data) {      var user_id = data['ticket.requester.id'];      requestUserInfo(client, user_id);    }  );})();
function requestUserInfo(client, id) {  var settings = {    url: '/api/v2/users/' + id + '.json',    type:'GET',    dataType: 'json',  };
  client.request(settings).then(    function(data) {      showInfo(data);    },    function(response) {      showError(response);    }  );}
function showInfo(data) {  var requester_data = {    'name': data.user.name,    'tags': data.user.tags,    'created_at': formatDate(data.user.created_at),    'last_login_at': formatDate(data.user.last_login_at)  };
  var source = document.getElementById("requester-template").innerHTML;  var template = Handlebars.compile(source);  var html = template(requester_data);  document.getElementById("content").innerHTML = html;}
function showError(response) {  var error_data = {    'status': response.status,    'statusText': response.statusText  };
  var source = document.getElementById("error-template").innerHTML;  var template = Handlebars.compile(source);  var html = template(error_data);  document.getElementById("content").innerHTML = html;}
function formatDate(date) {  var cdate = new Date(date);  var options = {    year: "numeric",    month: "short",    day: "numeric"  };  date = cdate.toLocaleDateString("en-us", options);  return date;}

Your iframe.html file should look like this:

<!DOCTYPE html><html>
<head>  <meta charset="utf-8">  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"    crossorigin="anonymous">  <link href="main.css" rel="stylesheet"></head>
<body>
  <div id="content"></div>
  <footer>    <a href="https://mysite.github.io/support" target="_blank">Report bugs</a>  </footer>
  <script id="requester-template" type="text/x-handlebars-template">    <table>    <tr>      <td>Customer:</td>      <td class="data">{{name}}</td>    </tr>    {{#if tags}}    <tr>      <td>Tags:</td>      <td class="data">{{#each tags}}{{this}} {{/each}}</td>    </tr>    {{/if}}    <tr>      <td>Added:</td>      <td class="data">{{created_at}}</td>    </tr>    <tr>      <td>Last signed in:</td>      <td class="data">{{last_login_at}}</td>    </tr>    </table>  </script>
  <script id="error-template" type="text/x-handlebars-template">    <p>{{status}} - {{statusText}} error. Please report a bug at the link below.</p>  </script>
  <script src="https://static.zdassets.com/zendesk_app_framework_sdk/2.0/zaf_sdk.min.js"></script>  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/handlebars.min.js"></script>  <script src="main.js"></script></body>
</html>

If you like, keep tweaking the app. You can download the completed source code of the app by clicking xr_app.zip.

The final step involves validating, packaging, and installing the app in your Zendesk Support instance. Continue to Part 5 - Installing the app in Zendesk Support.