Extending Zendesk with the help of Zendesk App, Ruby on Rails API and CORS

Why we decided to create our own Zendesk app

In one of our projects, we use Zendesk - a service for processing users' feedbacks. With its help, users report problems, offer new features and leave their comments. The entire ticket base is stored on the Zendesk side. General information about our users (email, name, user_id) is also mirrored in Zendesk. So, our technical support staff has the access to all tickets and users on https://our-subdomain.zendesk.com page.

Zendesk access to tickets and users

Upon integrating Zendesk into the project and receiving initial feedback, our technical support engineers proposed enhancements to the service. One suggestion was to include the following functionality:

  • Display the current user's information from our database on the user's page, along with links for quick access to the user's profile in our application.
  • Show the creator of the ticket on the ticket page, similar to how it's displayed on the user's page.

Developing Zendesk app

To implement this, it was decided to write our own Zendesk app. This application should display a summary of the user activity for the last year, links for fast access to the user's profile and other useful data on the user's page (as well as on the ticket page) in Zendesk. It is not allowed to store all this data on Zendesk's servers. Therefore, we decided to create API action that will provide the data in JSON format. Zendesk app will call this action, receive information about user and display it on the user and tickets pages in Zendesk.

After creating the API action, we get an URL of the following format: https://our-domain/api/admin/zendesk/:id.json. From this URL, we can obtain information about the user we are interested in (we have to be logged in as admin). Here is an example of server response:

{"user":{"id":123, name:John Doe, link:https://our-domain/user/profile/link, ...}}

Now, we create our application using the developer's guide on building and deploying Zendesk apps. In app.js, we set up the request that calls our API for getting the user data:

    requests: {
      getUserData: function() {
        var id = this.user().externalId(); # this.user() - an object of the opened user on Zendesk, externalId - the user's id in our database
        return {
          url: 'https://our-domain/api/admin/zendesk/' + id,
          type: 'GET',
          dataType: 'json'
        };
      }
    }

When all settings are done, we get a basic Zendesk app that can be uploaded to Zendesk. After uploading, we can open the user page on Zendesk and see that information about user is not displayed in our Zendesk app. We go to the browser console and see an error:

XMLHttpRequest cannot load https://our-domain/api/admin/zendesk/123. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://our-subdomain.zendesk.com' is therefore not allowed access.

This error says that we are trying to send XHR request to domain that is different from the one we are currently using. That's why the browser blocks this request for security reason. In order to solve this issue, we decided to apply CORS technology. To use this technology, we have to configure our client (Zendesk app) and our server written in Ruby on Rails.

Zendesk app is set up by adding the following lines to the configuration of the request.

    requests: {
      getUserData: function() {
        var id = this.user().externalId();
        return {
          url: 'https://our-domain/api/admin/zendesk/' + id,
          type: 'GET',
          dataType: 'json',
          cors: true,
          xhrFields: { withCredentials: true }
        };
      }
    }

Now, let's set our server. To do this, add before_action to the controller:

  before_action :set_cors_headers

  private

  def set_cors_headers
    headers['Access-Control-Allow-Origin'] = 'https://our-subdomain.zendesk.com'
    headers['Access-Control-Allow-Credentials'] = 'true'
  end

These two lines do the following:

  • HTTP header Access-Control-Allow-Origin specifies the domains which our server is authorized to accept XHR requests from. We indicated our domain on Zendesk in this header. If the server receives XHR requests from other domains, it will respond with the error that we saw earlier in the console of our browser.
  • The second HTTP header Access-Control-Allow-Credentials allows domains listed above to use cookies, stored in the user's browser for our website. In other words, now when our Zendesk app sends the request to our API, with its Origin (https://our-subdomain.zendesk.com) included into header, our server will respond to such requests correctly.

We deploy our changes to the production server, upload a new version of Zendesk app and check the user's page on Zendesk again. Ta-da! In the right sidebar we can see the result of our work – all additional information about the user received from our API.

Our Zendesk App

Final notes

Thus, we have extended the abilities of Zendesk, by developing our Zendesk app. And our technical support engineers were thankful for such a useful and handy addition to the Zendesk service. We also hope that this article can provide some useful insights on how to build a Zendesk app for those who need it.