Build a Serverless Call Routing Application with Time Zone Management in JavaScript

July 18, 2022
Written by
Reviewed by

Build a Serverless Call Routing Application with Time Zone Management in JavaScript

Time of day routing allows you to manage where incoming calls are directed based on time periods and which day it is. For example, routing calls to a support line during business hours or an after hours voicemail to maximize customer satisfaction. This can get extra tricky when the server that’s running your call routing app is located in a different time zone than your business (and this is extremely likely)!

In this tutorial, you’ll be building an app that routes incoming calls depending on the day, time of day relative to your business hours, and your business’ time zone. This will all run on Twilio’s Serverless infrastructure, so you won’t need to worry about hosting.

Prerequisites

Get started with the Twilio Serverless Toolkit

The Serverless Toolkit is CLI tooling that helps you develop locally and deploy to Twilio Runtime. The best way to work with the Serverless Toolkit is through the Twilio CLI. If you don't have the Twilio CLI installed yet, run the following commands in your terminal or command prompt to install it and the Serverless Toolkit:

npm install twilio-cli -g
twilio login
twilio plugins:install @twilio-labs/plugin-serverless

If this is your first time using the Twilio CLI and you don’t have an active profile set yet, run twilio profiles:use PROFILE_ID once before trying any of the following serverless commands.

Next, run the following commands to create your new Serverless project and switch into the resulting directory:

twilio serverless:init –empty timing
cd timing

This will prepare the folder structure for a Serverless project for you (the “empty” parameter tells the plugin not to pre-define any boilerplate Functions or Assets for you) and install all necessary dependencies.

Write your Function

With your app’s structure now ready, it’s time to create the Function that will handle call routing. To do so, run the following:

touch functions/handle-calls.protected.js

The .protected that’s added before the file extension tells the Serverless Toolkit to deploy your Function as Protected. This means that Twilio webhooks and other resources can make requests to your Function, but nothing else. Read the documentation on Function Visibility to learn more.

Next, open the handle-calls.protected.js file in your editor, paste in the following code, and be sure to save the modified file:

exports.handler = (context, event, callback) => {
  const twiml = new Twilio.twiml.VoiceResponse();
  const now = new Date();

  const { timeZone } = Intl.DateTimeFormat().resolvedOptions();
  console.log(`This Function is being executed in the ${timeZone} time zone`);

  const formatOptions = {
    hour: 'numeric',
    hour12: false,
    weekday: 'long',
    timeZone: 'America/Los_Angeles',
  };
  const formatter = new Intl.DateTimeFormat('en-US', formatOptions);

  const formattedDate = formatter.format(now).split(', ');
  const day = formattedDate[0]; // ex. 'Monday'
  const hour = Number(formattedDate[1]); // ex. 18

  const isWeekend = ['Sunday', 'Saturday'].includes(day);

  const isOpen = !isWeekend && hour >= 10 && hour < 19;

  if (isOpen) {
    twiml.dial(context.BUSINESS_PHONE_NUMBER);
    twiml.say('Thanks for calling! Connecting you to someone who can help.');
    return callback(null, twiml);
  }
  
  twiml.say("You've reached us outside of business hours, please call back between 10am and 7pm Pacific time, Monday through Friday. Stay on the line to leave us a message.");
  twiml.record();
  twiml.say("I didn't catch that, goodbye!");
  return callback(null, twiml);
};

This code logs out the time zone that the Function is being executed in (which will be UTC, definitely not Pacific time), determines the relative date and time for the Pacific time zone and formats it for parsing, and does some comparison to determine if the call is coming in while your business is open. Based on that determination, it will either connect the incoming caller to your businesses’ phone number, or prompt them to call back or leave a message.

So many time zones

In the past, you would need to reach for a heavy library like Moment.js and an even heavier extension, moment-timezone to do a conversion such as this. Nowadays, you can do this all with built-in methods, courtesy of Intl! If you’re curious how and why this works, check out this article that covers date and time conversion with Intl in more depth.

Configure Environment Variables

You’ll notice that the phone number to direct calls to is referenced from context as an Environment Variable, instead of hard-coded as an E.164 formatted phone number, such as “+13335551234”. This helps to make your code more portable and gives you the ability to make configuration changes to your application instantly, without needing to redeploy! Environment variables are a great way to store sensitive information like phone numbers and API keys, and to store configuration information.

To set the value of BUSINESS_PHONE_NUMBER, open the .env file in the root directory of your project, add the following line (substituting whatever number you’d like to test this out with; I’d suggest a roommate or friend who won’t mind the call), and be sure to save the file:

ACCOUNT_SID=ACxxxxx
AUTH_TOKEN=...
BUSINESS_PHONE_NUMBER=[Your number of choice goes here, without these brackets]

Don’t worry about your sensitive account credentials being present in this .env file! The Serverless Toolkit pre-configures a .gitignore file on your behalf, which ensures that sensitive files like .env won’t be uploaded if you try committing your project to platforms like GitHub.

With your Function written and environment variables set, it’s time to deploy! From your root directory, run twilio serverless:deploy. It will take a few brief moments for Twilio to create and deploy your application. In the console output, you will see a list titled Functions. You will see a URL that looks like https://timing-1234-dev.twil.io/handle-calls.

Connect your Function to a Twilio Phone Number

Let’s connect your Twilio phone number to your newly-minted Function, and verify that incoming calls are handled with Pacific time in mind!

Open up the phone numbers section of the Twilio Console, go to Phone Numbers > Manage > Active Numbers, and select the phone number that you would like to connect. Once on the configuration page for your phone number, scroll down to the Voice & Fax header and look for the A call comes in settings. From this dropdown, select Function, then fill in the remaining fields with the service name that you picked, the dev environment (the default if you’re using the Serverless Toolkit as shown so far), and lastly the path to your /handle-calls Function! Your settings will look something like this once done!

Incoming Message Configuration

If everything looks right, click Save at the bottom of this page. Incoming calls will now be sent to your Function.

Give your Twilio phone number a ring, and you will receive a time-of-day-appropriate response, regardless of which time zone you’re calling from!

Conclusion

Congratulations on your newfound mastery of time zone management and call routing! Want to try this against a different time zone than America/Los_Angeles? Take a look at this comprehensive table of time zones, substitute one in place of America/Los_Angeles in your Function’s code, and re-deploy your application to help your app shift it a different time zone.

Shifting time zones

I hope that you’ve enjoyed this article and learned something new that could help your current or next project! If you’re curious what else you can build with Twilio Functions, I encourage you to check out some more examples in our docs.

I can’t wait to see what you build!

Shawn Stern is a Developer Educator at Twilio. Reach out to him at sstern [at] twilio [dot] com if you have a cool JavaScript or TypeScript idea you’d like to share on this blog!