In the previous tutorials in this series, you designed the user interface for an app named Learn about Sell. In this tutorial, you'll update the app to list links to deal articles from the Zendesk Help Center, and show the deal card name.

Let's work out the app logic:

  1. When the user opens a deal card, the app uses the Apps framework API to post the Deal card name in the app window.
  2. The user clicks the Get docs button.
  3. The app makes a request to a Help Center Get Articles API endpoint to retrieve a list of deal articles.
  4. If the request is successful, it lists article links in the app window.

This tutorial covers the steps to building the app logic:

  1. Adding an event listener
  2. Making the API request and formatting the data
  3. Posting article links in the app
  4. Retrieving the deal card name using the Apps framework API
  5. Code complete!

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

Adding an event listener

The first step is to add an event listener for the Get docs button in your user interface. After an agent clicks the button, the app should make an API request to retrieve deal articles in the Zendesk Help Center.

To add an event listener

  • In the main.js file, insert the following code snippet (highlighted) in the self-executing function at the top of the file:
$(function () {    var client = ZAFClient.init();    client.invoke("resize", { width: "100%", height: "180px" });    showGetDocsButton();    $("#get-btn").click(function (event) {     event.preventDefault();     showDealArticles(client);    });    });

Because you included jQuery in your app, you can use the jQuery click() method to define an event listener. The highlig snippet adds a click listener to the element with an id of get-btn , which is the id you used for your Get docs button. When the user clicks the button, the script runs the function that's specified as an argument, which consists of several statements:

  • The first prevents the button from submitting a form
  • The second calls a custom function named ShowDealArticles(client), which you'll define in the next section. The function makes a Help Center Search API request to retrieve deal articles and format the articles in the app.

Making the API request and formatting data

In the main.js file, insert the following function after the showGetDocsButton function:

function showDealArticles(client) {   var url =     "https://support.zendesk.com/api/v2/help_center/articles/search.json?section=360006252673";   var request = new XMLHttpRequest();   request.onreadystatechange = handleResponse;   request.open("GET", url);   request.send();   function handleResponse() {     if (request.readyState === XMLHttpRequest.DONE) {       if (request.status === 200) {         response = JSON.parse(request.responseText);         let articles = [];         for (var article of response.results) {           articles.push({ title: article.title, url: article.htmlhtml_url });         }         showArticles(articles);       } else {         console.log("There was a problem with the request.");       }     }   } }

The function performs several tasks:

  • Makes a GET request to the Help Center Search Articles API endpoint to retrieve articles in the Deals section (section= 360006252673). Authentication is not required because the Articles API is available to everyone
  • Executes the handleResponse function when the readystate property changes. The handleResponse function contains statements that if the HTTP request status is okay, to format the returned article data, and pass it to the showArticles() function to display the article titles in the app

Posting article links in the app

Next, you'll add a handlebars template to the iframe.html file and showArticles() function in the main.js file to post article links in the app window.

To post article links in the app

  1. In the iframe.html file, add the following handlebars template after the "content" div tag:

    <script id="articles-template" type="text/x-handlebars-template"><ul style="list-style:unset;">{{#each articles}}<li><a href="{{url}}" target="_blank">{{title}}</a></li>{{/each}}</ul></script>

    The handlebars template named "articles-template" uses the #each expression to loop each article to create a list of linked article titles.

  2. In the main.js file, insert the following function after the showDealArticles(client) function:

    function showArticles(articles) {var article_data = { articles: articles };var source = $("#articles-template").html();var template = Handlebars.compile(source);var html = template(article_data);$("#content").html(html);}

    The showArticles(articles) function references the <script> tag in iframe.html that contains the "articles-template" handlebar template, compiles the template, generates the HTML from the template, and uses it to display content in the div element named "content".

  3. Save the files, reload the Sell app, and click Get Docs. The app should list links to deal articles in the text area:

Retrieving the deal card name using the Apps framework API

The Zendesk Apps framework gives you access to a large number of Sell APIs. The framework's Deal API doc shows the properties you can retrieve. For example, the property deal.name returns the name of the deal card.

You use the client.get(path) method to query the Deal 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. For example:

{"deal.name": "Acme Co Sales Opportunity"}

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

var client = ZAFClient.init();client.get('deal.name').then(function(data) {console.log(data['deal.name']); // something like Acme Co Sales Opportunity});

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('deal.name').then(run_this_fn_on_success,run_this_fn_on_failure);

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

You can add the deal.name path in the client.get(path) method to get the deal card name.

To get the deal card name

  1. In the main.js file, insert the following statement (highlighted) in your self-invoking function, after the click event:
$(function () {    var client = ZAFClient.init();    client.invoke("resize", { width: "100%", height: "200px" });    showGetDocsButton();        $("#get-btn").click(function (event) {     event.preventDefault();     showDealArticles(client);    });        client.get("deal.name").then(function (data) {     var deal_name = data["deal.name"];     dealCardName(deal_name);    });    });
The statement gets the deal card name currently open in the Sell interface. After getting a successful response, it assigns it to a variable named `deal_name`.
  1. Check the deal card name by saving the main.js file, reloading the app, and looking for the console.log message in your browser console:

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

    dealCardName(deal_name);

    The call passes the deal_name variable to the dealCardName() function you created in the previous tutorial.

  3. Make the following change (highlighted) to the dealCardName() function in main.js, to replace the placeholder text with the deal_name variable:

    function dealCardName(deal_name) {    var data = { name: deal_name };    var source = $("#deal-name-template").html();    var template = Handlebars.compile(source);    var html = template(data);    $("#deal-name").html(html);    }
  4. Save the files and reload the app. You should see the deal card name listed in the app:

Code complete!

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

$(function () {  var client = ZAFClient.init();  client.invoke("resize", { width: "100%", height: "200px" });  showGetDocsButton();
  $("#get-btn").click(function (event) {    event.preventDefault();    showDealArticles(client);  });
  client.get("deal.name").then(function (data) {    var deal_name = data["deal.name"];    dealCardName(deal_name);  });});
function dealCardName(deal_name) {  var data = { name: deal_name };  var source = $("#deal-name-template").html();  var template = Handlebars.compile(source);  var html = template(data);  $("#deal-name").html(html);}
function showGetDocsButton() {  var source = $("#get-docs-btn-template").html();  var template = Handlebars.compile(source);  $("#content").html(template());}
function showDealArticles(client) {  var url =    "https://support.zendesk.com/api/v2/help_center/articles/search.json?section=360006252673";  var request = new XMLHttpRequest();  request.onreadystatechange = handleResponse;  request.open("GET", url);  request.send();
  function handleResponse() {    if (request.readyState === XMLHttpRequest.DONE) {      if (request.status === 200) {        response = JSON.parse(request.responseText);
        let articles = [];        for (var article of response.results) {          articles.push({ title: article.title, url: article.html_url });        }        showArticles(articles);      } else {        console.log("There was a problem with the request.");      }    }  }
  function showArticles(articles) {    var article_data = { articles: articles };    var source = $("#articles-template").html();    var template = Handlebars.compile(source);    var html = template(article_data);    $("#content").html(html);  }}

Your iframe.html file should look like this:

<!DOCTYPE html><html>
<head>  <meta charset="utf-8">  <link rel="stylesheet" href="https://cdn.jsdelivr.net/combine/npm/@zendeskgarden/[email protected],npm/@zendeskgarden/[email protected],npm/@zendeskgarden/[email protected]">  <link rel="stylesheet" href="main.css"></head>
<body>  <h2 class="u-milli">Learn about deals in Sell</h2>  <div id="deal-name"></div>  <div id="content"></div>  <footer>    <a href="https://mysite.github.io/support" target="_blank">Report bugs</a>  </footer>
  <script id="deal-name-template" type="text/x-handlebars-template">    <div class="u-zeta"><h3>{{name}}</h3></div></script>
  <script id="get-docs-btn-template" type="text/x-handlebars-template">    <button type="button" id="get-btn" class="c-btn.c-btn--sm">Get docs</button></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/jquery.min.js"></script>  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/handlebars.min.js"></script>  <script src="main.js"></script>
  <script id="articles-template" type="text/x-handlebars-template">    <ul style="list-style:unset;">    {{#each articles}}      <li><a href="{{url}}" target="_blank">{{title}}</a></li>    {{/each}}  </ul></script>
</body>
</html>

If you like, keep tweaking your app.

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