For any Freshworks' product that allows its users to automate their workflows, developers can now define their own custom logic amidst this workflow. We call it Custom Actions. This feature will allow the app to be the central component of Action defined by the user.

Typical examples of workflow actions are,

What will we be learning

In this tutorial, we are going to build a Freshcaller routing automation with the help of Custom actions to do the following two tasks,

  1. Handle VIP customers - to route the call quickly to relevant teams. For example, it would be a great use in a case where a premium customer would like to connect the live agent without going-through IVR and waiting time.
  2. Return dynamic response - to answer to the customer queries. For example, a customer can know about the transition status of the e-commerce ordered item without needing to go-through IVR or connect to an agent.

Prerequisites

Ensure to,

  1. HaveFreshworks Developer Kit (FDK) installed.
  2. Have aFreshcaller Account signed up.

Run the following command to create a boilerplace serverless app:

fdk create --products freshcaller --template your_first_serverless_app

The project files required for the serverless app are created. For more information, refer to Create serverless apps.

The actions that can be included as part of an automated workflow must be defined in a file (actions.json) in the home directory. The action names are keys to callback functions.

  1. Navigate to the home directory of your project and create a new file with name, actions.json. The file content must follow the JSON schema.
  2. In the actions.json file, define the validateVIPPhoneNumber and respondOrderStatus actions and the corresponding attributes.

Note: The terms inviteUser and deleteUser are the keys to callback functions. The action names must be the callback function names. You must define the callback functions in the server.js file.

actions.json

{
 "validateVIPPhoneNumber" : {
  "display_name" : "validate VIP users based on phone numbers",
  "parameters" : {
    "$schema": "http://json-schema.org/draft-04/schema#",
    "type": "object",
    "properties": {
     "input": {
       "type": "string"
       }
     },
     "required": [
       "input"
     ]
   },
   "response": {
     "type": "object",
     "properties": {
       "user_id": {
         "type": "string"
       }
     }
   },
  "description": "Sends an OTP to user's registered email address"
},
"respondOrderStatus" : {
   "display_name" : "to send the message to be played as a dynmaic message in Freshcaller",
   "parameters" : {
         "$schema": "http://json-schema.org/draft-04/schema#",
         "type": "object",
         "properties": {
          "input": {
            "type": "string"
            }
          },
          "required": [
            "input"
          ]
        },
   "description": "Sends an OTP to user's registered email address",
   "response": {
        "type": "object",
        "properties": {
          "user_id": {
            "type": "string"
          }
        }
  }
 }
}

Navigate to server.js file and define the callback functions corresponding to the actions defined in the actions.json file.

As an acknowledgement to the automated workflow, the actions should return a result. In the server.js file, use the renderData() method to return the result of the callback function to the workflow from where the function is triggered, through actions. If the callback function succeeds, it returns a response data object as the second argument of the renderData() callback. Otherwise, it returns an error object with a status and message as the first argument of the renderData() callback.

In the callback functions, we will do the following operation before returning the results.

  1. validateVIPPhoneNumber
    This function will validate if the incoming phone number is a VIP number and return the result if it's valid or invalid.
  2. respondOrderStatus

This function will validate if the appropriate product is chosen from IVR and return an error if proper input is not received.

Upon receiving the right product input, it will return the status of the respective product. In our case, we will always send it as "in progress".

server.js

exports = {
validateVIPPhoneNumber: function (request) {   
   let validVIPNumbers = ['+15684561239','+12587419632'],
   response = validVIPNumbers.includes(request.input) ? 'valid': 'invalid',
   data = {
     response,
     "app_variables": {}
   };
  
   return renderData(null, { data });
 },
 respondOrderStatus: function (request) {
   const productIndex = request.input
   const productName = ['Freshcaller', "Freshdesk", "Freshsales", "Freshchat", "Freshservice"];
   if (productName(productName) === -1) {
     const error = { status: 404, message: "The selected product is not found. Choose a valid product." };
     return renderData(error)
   }
   return renderData(null, {
     success: true, data: {
       response: request.input, "app_variables": { "name": productName[productIndex], status: "in progress" }
     }
   });
 }
}

After your app is published and integrated with Freshcaller, when you design a call workflow using the routing automation, the custom actions configured in the app are listed as functions when the app is selected.

We will test the custom actions by simulating the actions and check the actual results from the app with the expected results.

You can simulate a workflow trigger and test your app from the testing page (http://localhost:10001/web/test).

1. Run the fdk run command. A message with the test URL is displayed.

2. To initiate the workflow actions from the testing page, navigate to the test URL from your browser.

3. From the Select type drop-down field, select actions. The actions defined in the actions.json file are displayed in the Select action drop-down list.

4. To test the workflow, select an action. The payload JSON is displayed.

Note: You can modify the payload values before clicking on the Simulate button to validate the app thoroughly. You can test the app with various test scenarios such as, adding a user whose account does not exist, adding a user to an organization that does not exist, and so on.

5. Click Simulate to trigger the appropriate callback function.

For more information on how to test the workflow actions, refer tothe documentation related to testing.

Here's what we learned in this tutorial,

The app showcased in this tutorial is available inthe GitHub repository