So far, you have built a Zendesk app that can authorize Zendesk and configure the Slack channel for priority-based ticket notification. In this tutorial, you’ll complete the app by connecting to Slack and enabling the notification workflow.

Prerequisites

You completed the following tutorials:

Connect to Slack

In Part 2: Using ZIS to obtain a Slack OAuth token, you created a Slack app, stored the Slack OAuth client in ZIS, and used the client to obtain an access token with Postman. In this tutorial, you’ll implement the Slack OAuth flow with JavaScript. The code is a slightly modified from Part 1: Building a navbar app with OAuth.

  1. In assets/index.html, paste the following code to add a new Slack Authorization button:

    ...  <button id="btnConnect" class="c-btn c-btn--primary">Zendesk Authorization</button></div><div class="c-txt u-mb">  <button id="btnConnectSlack" class="c-btn c-btn--primary">Slack Authorization</button></div><div class="row">...
  2. In assets/connect.js, append the function below:

    // startSlackOAuth initiates a Slack OAuth flowfunction startSlackOAuth(integrationKey, subdomain) {  let data = JSON.stringify({    name: 'slack', // the name of the obtained access token    oauth_client_name: 'slack',    oauth_url_subdomain: subdomain,    origin_oauth_redirect_url: window.location.href,    permission_scopes: 'chat:write'  })
      let request = {    type: 'POST',    url: '/api/services/zis/connections/oauth/start/' + integrationKey,    contentType: 'application/json',    data: data  }
      client.request(request).then(    function (response) {      console.log('OAuth started successfully')      authorize(response.redirect_url)    },    function (response) {      console.log('Failed to start OAuth: ', response)    }  )}
  3. In assets/bootstrap.js, paste the code below to bind the button click event with startSlackOAuth:

    ...$("#btnConnect").click(function() { startOAuth(integrationKey, subdomain) });
    // Bind button to start Slack OAuth flow$("#btnConnectSlack").click(function() { startSlackOAuth(integrationKey, subdomain) });
    // Bind button to submit config...
  4. Reload the app in your Zendesk instance. You should be able to click Slack Authorization and complete a Slack OAuth flow from your app.

Invite the app to your Slack channel

Invite the app to the destination channel using Slack's channel settings page.

Upload a ZIS bundle

Make an OAuth enabled request with the following details to Postman to upload a bundle.

  • Method: POST
  • URL: https://{{subdomain}}.zendesk.com/api/services/zis/registry/{{integration_key}}/bundles

Add the bundle below in the request body.

Tip: You can use the environment variable feature in Postman to replace the dynamic values such as {{integration_key}} in the bundle and {{subdomain}} in the request URL.

{  "zis_template_version": "2019-10-14",  "name": "PostSlackMessageOnTicketCreated",  "description": "Post Slack Message When Ticket Is Created",  "resources": {    "post_ticket_update_flow": {      "type": "ZIS::Flow",      "properties": {        "name": "post_message_to_slack",        "definition": {          "StartAt": "LoadSettings",          "States": {            "LoadSettings": {              "Type": "Action",              "ActionName": "zis:common:action:LoadConfig",              "Parameters": {                "scope": "slackNotification"              },              "ResultPath": "$.settings",              "Next": "IsTicketPriorityMatch"            },            "IsTicketPriorityMatch": {              "Type": "Choice",              "Choices": [                {                  "Variable": "$.input.ticket_event.ticket.priority",                  "StringEqualsPath": "$.settings.priority",                  "Next": "GetZendeskTicket"                }              ],              "Default": "Done"            },            "GetZendeskTicket": {              "Type": "Action",              "ActionName": "zis:{{integration_key}}:action:get_zendesk_ticket_http_action",              "Parameters": {                "token.$": "$.connections.zendesk.access_token",                "ticketId.$": "$.input.ticket_event.ticket.id"              },              "ResultPath": "$.retrievedTicket",              "Next": "PostMessageToSlack"            },            "PostMessageToSlack": {              "Type": "Action",              "ActionName": "zis:{{integration_key}}:action:post_message_to_slack_http_action",              "Parameters": {                "token.$": "$.connections.slack.access_token",                "channelId.$": "$.settings.channel",                "ticketSubject.$": "$.retrievedTicket.ticket.subject",                "ticketDescription.$": "$.retrievedTicket.ticket.description",                "title.$": "*_New {{$.input.ticket_event.ticket.priority}} ticket #{{$.input.ticket_event.ticket.id}}_*",                "link.$": "<{{$.retrievedTicket.ticket.url}}|View in Zendesk>"              },              "ResultPath": "$.postMessageResponse",              "Next": "Done"            },            "Done": {              "Type": "Succeed"            }          }        }      }    },    "post_message_to_slack_action": {      "type": "ZIS::Action::Http",      "properties": {        "name": "post_message_to_slack_http_action",        "definition": {          "method": "POST",          "url": "https://slack.com/api/chat.postMessage",          "headers": [            {              "key": "Authorization",              "value": "Bearer {{$.token}}"            }          ],          "requestBody": {            "channel": "{{$.channelId}}",            "blocks": [              {                "type": "section",                "text": {                  "type": "mrkdwn",                  "text": "{{$.title}}"                },                "fields": [                  {                    "type": "mrkdwn",                    "text": "*Subject*"                  },                  {                    "type": "mrkdwn",                    "text": "*Description*"                  },                  {                    "type": "plain_text",                    "text": "{{$.ticketSubject}}"                  },                  {                    "type": "plain_text",                    "text": "{{$.ticketDescription}}"                  }                ]              },              {                "type": "section",                "text": {                  "type": "mrkdwn",                  "text": "{{$.link}}"                }              }            ]          }        }      }    },    "get_zendesk_ticket_action": {      "type": "ZIS::Action::Http",      "properties": {        "name": "get_zendesk_ticket_http_action",        "definition": {          "method": "GET",          "path": "/api/v2/tickets/{{$.ticketId}}.json",          "headers": [            {              "key": "Authorization",              "value": "Bearer {{$.token}}"            }          ]        }      }    },    "post_message_to_slack_on_ticket_created_job_spec": {      "type": "ZIS::JobSpec",      "properties": {        "name": "post_message_to_slack_on_ticket_created_job_spec",        "event_source": "support",        "event_type": "ticket.TicketCreated",        "flow_name": "zis:{{integration_key}}:flow:post_message_to_slack"      }    }  }}

Enable ZIS Flow on a Zendesk account

The installation of a workflow is based on enabling a JobSpec object on a given Zendesk account. Once a job spec is enabled on an account, ZIS can respond to a domain event such as ticket.TicketCreated by executing the desired workflow.

  1. In assets/registry.js, paste the following code and save the file:

    // installFlow enables the workflow on the current Zendesk account.// The underlying concept of JobSpec is used to associate a workflow with a// triggering event.function installFlow(integrationKey) {  const jobSpec =    'zis:' +    integrationKey +    ':job_spec:post_message_to_slack_on_ticket_created_job_spec'
      let request = {    type: 'POST',    url:      '/api/services/zis/integrations/' +      integrationKey +      '/job_specs/installation',    contentType: 'application/json',    data: JSON.stringify([{ name: jobSpec }])  }
      return client.request(request).then(    function (response) {      console.log('Flow enabled successfully')    },    function (response) {      console.log('Failed to enable flow: ', response)    }  )}
  2. Load the file in assets/index.html and add a button beneath Slack Authorization:

    ...<!-- enable workflow --><script type="text/javascript" src="registry.js"></script></head>...            <button id="btnConnectSlack" class="c-btn c-btn--primary">Slack Authorization</button>        </div>        <div class="c-txt u-mb">            <button id="btnInstallFlow" class="c-btn c-btn--primary">Install Flow</button>        </div>        <div class="row">...
  3. Modify assets/bootstrap.js to bind the button click with the installFlow function:

    ...// Bind button to start Slack OAuth flow$("#btnConnectSlack").click(function() { startSlackOAuth(integrationKey, subdomain) });
    // Bind button to start Slack OAuth flow$("#btnInstallFlow").click(function() { installFlow(integrationKey) });
    // Bind button to submit config...
  4. In your command line tool, navigate to the app directory that contains manifest.json, and run zcli apps:server to start a local HTTP server.

  5. In your Zendesk instance, append ?zcli_apps=true to the URL and reload the app. See Testing your app locally in a browser.

  6. Click the Install Flow button. To ensure all the OAuth tokens are acquired, you can also repeat the Zendesk authorization and Slack authorization steps.

Creating a Zendesk ticket with desired priority

To see the workflow in action, you can create a Zendesk ticket with the priority specified in your app's configuration. Example:

After creating the ticket, you should receive a Slack notification in the previously configured channel:

If you have trouble seeing the notification, you can troubleshoot using the integrations log. See Viewing the integrations log.

Congratulations! You've now completed the Zendesk app and activated a workflow on your Zendesk account. You can package and install the app as a private app. See Uploading and installing a private app.