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

In the previous tutorials, you designed the user interface (UI) for an app named Related Leads. In this tutorial, you'll use Zendesk APIs to get live data and display it in the UI.

The app will fetch an organization's leads from theSell Core API. It'll do this by making a request to theRetrieve All Leadsendpoint:

             
GET/v2/leads/?organization_name={orgName}

端点是一个URL,您可以获取或设置信息rmation about a resource. The Retrieve All Leads endpoint gets information about leads. You can use the endpoint'sorganization_namequery parameter to limit the leads to a specific organization. To get the right leads, your app needs to provide the right organization name to the endpoint. This organization name will change based on the deal the user is currently viewing in Zendesk Sell.

The app logic should work as follows:

  1. The app accesses the deal that the user is viewing in the Zendesk Sell. The app gets the name of the organization associated with this deal.
  2. The app uses the organization's name to request leads from the Retrieve All Leads endpoint. The request will only retrieve up to five leads. These leads must belong to the organization and have a status of "new."
  3. If the request is successful, the app shows the organization's name and new leads in the organization template. If the request fails, the app shows an error message in a different template.

This tutorial covers the steps to building the app logic:

  1. Calling the framework API
  2. Calling the REST API
  3. Displaying the organization's leads
  4. Displaying the error message
  5. Code complete!

Calling the framework API

The first step is to access the deal the user is viewing in Zendesk Sell. You can then get the name of the organization associated with the deal.

How it works

In the deal card sidebar, the Zendesk Apps framework (ZAF) includes a Deals API that gives you access to the data of the deal.

The framework'sDeal objectlists the deal properties you can retrieve. Thedeal.organizationproperty returns anorganizationobject. This object contains data about the organization associated with the deal, including theorganization.nameproperty.

Based on this information, you can use the following path to get the name of the organization associated with a deal:

             
"deal.organization.name"

In ZAF, you use theclient.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. For example:

             
{"deal.organization.name":"Acme Co"}

Because the name string contains periods, you must use JavaScript bracket notation to retrieve its value:

             
constclient=ZAFClient.init();client.get("deal.organization.name").then(function(data){console.log(data["deal.organization.name"]);// something like Acme Co});

Communication between an iframe and its parent page is asynchronous. 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 request receives a response. The.then()method is used to wait for the callback. The method returns aPromiseand 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 based on the outcome."

             
client.get("deal.organization.name").then(run_this_fn_on_success,run_this_fn_on_failure);

For more information, refer toPromise.prototype.then()on the Mozilla Developer Network.

Getting the organization's name

In this section, you'll use thedeal.organization.name巴勒斯坦权力机构th and the ZAF Client API'sgetmethod to retrieve the name of the organization associated with a deal.

  1. Inmain.js, delete thedisplayLeads()anddisplayError()function calls from your self-invoking function.

                   
    displayLeads();displayError();
  2. Replace the deleted function calls with the following statement.

                   
    ...client.get("deal.organization.name").then(function(data){constorgName=data["deal.organization.name"];console.log('Organization name is '+orgName);});

    The statement gets the name of the organization associated with the deal the user is viewing. After getting a successful response, it assigns the returned data to a variable namedorgName.

  3. Check the organization name by refreshing the app and looking for theconsole.logmessage in your browser console.

  4. Replace theconsole.log()statement with the following function call:

                   
    requestLeads(client,orgName);

    调用传递clientandorgNamevariables to therequestLeads()function. You'll define this function in the next section. The function's job is to make an HTTP request to the Retrieve All Leads endpoint in the Sell Core API. You pass theclientargument because the function will need the ZAF Client object to make the HTTP request. You pass theorgNameargument because you want to limit the API request by the organization's name.

    Your self-invoking function should now look like this:

                   
    (function(){constclient=ZAFClient.init();client.invoke("resize",{width:"100%",height:"150px"});client.get("deal.organization.name").then(function(data){constorgName=data["deal.organization.name"];requestLeads(client,orgName);});})();

Calling the REST API

Your app can now get the name of the organization associated with a deal. Use this name to get information about leads for the organization from the Sell Core API.

Defining the API request

Theclient.request()method makes HTTP requests to external APIs. The method takes an object that defines the request settings as an argument. For example:

             
constsettings={url:“/ v2 /导致/”+"?organization_name="+encodeURIComponent(orgName)+"&status=new"+"&per_page=5",type:"GET",dataType:"json",};client.request(settings).then(function(data){console.log(data);},function(response){console.error(response);});

TheREST API docfor the Retrieve All Leads endpoint indicates the settings to include:

  • Theurlis/v2/leads/?organization_name={orgName}&status=new&per_page=5. For Sell Core API endpoints, you don't need to specify the full URL. For other endpoints, specify the full URL, such as 'https:// example.com/api/resource.json'.

    URL还包括几个查询参数:

    • ?organization_name={orgName}limits the response to a specific organization.
    • &status=newlimits the response to leads with a status of "new."
    • &per_page=5limits the response to five leads or fewer.
  • ThetypeisGET.

  • ThedataTypeisjson.

The request shouldn't include acorssetting. Requests from the ZAF Client to the Sell Core API aren't cross-origin requests and don't require the Zendesk proxy service.

Don't include credentials, such as an API key, in the request or its settings. The ZAF Client automatically authenticates requests made to the Sell Core API.

Note: The ZAF Client only supports the Sell Core API. ZAF doesn't support other Sell APIs, such as the Search API or Firehose API.

Getting the organization's leads

In this section, you'll use theclient.request()method and the Retrieve All Leads endpoint to make an HTTP request that retrieves an organization's new leads.

  1. Inmain.js, insert the following function directly after your self-invoking function:

                   
    functionrequestLeads(client,orgName){constsettings={url:“/ v2 /导致/”+"?organization_name="+encodeURIComponent(orgName)+"&status=new"+"&per_page=5",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 browser console withconsole.log(data). If the request is not successful, the app displays the response in the console withconsole.error(response).

  2. Check the results of the request in your browser console. Savemain.js, refresh the app, and look for theconsole.logmessage in the console. The message should contain an object with leads data for the organization.

  3. Test the results in case of failure by introducing a typo in one of the request settings. Savemain.js, refresh the app, and look for a relatedconsole.errormessage in the console.

    Fix the typo after you ensure the error handling works.

  4. In the first callback function, replace theconsole.logstatement with a call to thedisplayLeads()function. Include theorgNameanddataarguments in the call.

                   
    displayLeads(orgName,data);
  5. In the second callback function, replace theconsole.logstatement with a call to thedisplayError()function. Include theresponseargument in the call.

                   
    displayError(response);

    YourrequestLeads()function should now look as follows:

                   
    functionrequestLeads(client,orgName){constsettings={url:“/ v2 /导致/”+"?organization_name="+encodeURIComponent(orgName)+"&status=new"+"&per_page=5",type:"GET",dataType:"json",};client.request(settings).then(function(data){displayLeads(orgName,data);},function(response){displayError(response);});}

Displaying the organization's leads

In the previous section, you passed the organization name and leads data to thedisplayLeads()function call after getting a successful response from the Sell Core API.

In this section, you'll take that information and display it in your organization template.

  1. In yourdisplayLeads()function definition, addorgNameanddataarguments to receive the respective organization name and leads data:

                   
    functiondisplayLeads(orgName,data){...
  2. In thedisplayLeads()function definition, replace the hard-codedorgNamevalue in theorgDataobject with theorgNameargument:

                   
    constorgData={orgName:orgName,leads:[{"name":"Alice Aragorn","url":"https://app.futuresimple.com/leads/2104416001"},{"name":"Bob Baggins","url":"https://app.futuresimple.com/leads/2104416001"},]};
  3. Replace the hard-codedleadsvalue with a call to thegetLeads()function. Pass thedataargument to this function.

                   
    constorgData={orgName:orgName,leads:getLeads(data)};
  4. Add the followinggetLeads()function definition directly after thedisplayLeads()function definition:

                   
    functiongetLeads(data){letleads=[];for(letleadofdata.items){leads.push({name:`${lead.data.first_name}${lead.data.last_name}`,url:`https://app.futuresimple.com/leads/${lead.data.id}`,});}returnleads;}

    This function iterates through each lead in the response to retrieve:

    • The lead's first and last name
    • The lead's ID

    It uses this information to create an array of objects. Each object in the array represents a lead and contains:

    • The lead's full name (name)
    • TheLeads巴勒斯坦权力机构ge URL for the lead (url)

    It returns these objects in an array (leads).

  5. Savemain.jsand refresh the app. If your ZCLI server is not already started, seeTesting the appfor instructions.

    If the organization associated with the deal has no new leads, the alternative heading will display.

Displaying the error message

InCalling the REST API, you passed aresponseobject to thedisplayError()function after getting an error response from the Zendesk API:

             
displayError(response);

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

  1. Inmain.js, add theresponseargument to yourdisplayError()function definition to receive the error data:

                   
    functiondisplayError(response){...
  2. In thedisplayError()function definition, replace the hard-coded values in theerrorDataobject with the values in theresponseobject:

                   
    consterrorData={'status':response.status,'statusText':response.statusText};
  3. Test the error page by making a typo in one of the request settings inrequestLeads(). Savemain.js, and refresh the app. Your error template should display.

    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 Sell app. The final version of yourmain.jsfile should look like this:

             
(function(){constclient=ZAFClient.init();client.invoke("resize",{width:"100%",height:"150px"});client.get("deal.organization.name").then(function(data){constorgName=data["deal.organization.name"];requestLeads(client,orgName);});})();functionrequestLeads(client,orgName){constsettings={url:“/ v2 /导致/”+"?organization_name="+encodeURIComponent(orgName)+"&status=new"+"&per_page=5",type:"GET",dataType:"json",};client.request(settings).then(function(data){displayLeads(orgName,data);},function(response){displayError(response);});}functiondisplayLeads(orgName,data){constorgData={orgName:orgName,leads:getLeads(data)};renderTemplate("org-template",orgData,"content");}functiongetLeads(data){letleads=[];for(letleadofdata.items){leads.push({name:`${lead.data.first_name}${lead.data.last_name}`,url:`https://app.futuresimple.com/leads/${lead.data.id}`,});}returnleads;}functionrenderTemplate(templateId,dataObject,divId){constsource=document.getElementById(templateId).innerHTML;consttemplate=Handlebars.compile(source);constcompiledHtml=template(dataObject);document.getElementById(divId).innerHTML=compiledHtml;}functiondisplayError(response){consterrorData={'status':response.status,'statusText':response.statusText};renderTemplate("error-template",errorData,"content");}

Youriframe.htmlfile should look like this:

             
DOCTYPEhtml><html><head><metacharset="utf-8"><!--SeeUsing亚博Garden:https://developer.亚博.com/apps/docs/developer-guide/setup#using-亚博-gardenhttps://garden.亚博.com/css-components/bedrock/https://garden.亚博.com/css-components/utilities/typography/--><linkrel="stylesheet"href="https://cdn.jsdelivr.net/combine/npm/@zendeskgarden/[email protected],npm/@zendeskgarden/[email protected]"><linkrel="stylesheet"href="main.css">head><body><divid="content">div><footer><ahref="https://example.com/support"target="_blank">Reportbugsa>footer><scriptid="org-template"type="text/x-handlebars-template">{{#ifleads}}<h2>New leadsfor{{orgName}}</h2><ul>{{#each leads}}<li><a href="{{url}}"target="_blank">{{name}}</a></li>{{/each}}</ul>{{else}}<h2>Nonewleadsfoundfor{{orgName}}.</h2>{{/if}}script><scriptid="error-template"type="text/x-handlebars-template"><p>{{status}}-{{statusText}}error.Please report a bug at the link below.</p>script><scriptsrc="https://static.zdassets.com/zendesk_app_framework_sdk/2.0/zaf_sdk.min.js">script><scriptsrc="https://cdn.jsdelivr.net/npm/[email protected]/dist/handlebars.min.js">script><scriptsrc="main.js">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 toPart 5 - Installing the app in Zendesk Sell.