Identify Unknown Phone Numbers with JavaScript, Twilio Lookup and SMS

November 16, 2018
Written by
Joe Previte
Contributor
Opinions expressed by Twilio contributors are their own

qUascKFxN9r_GVqOW2coJIFt9aSMvXby-nBre4z4h84UeyrY9gXhfnDpQd1ShsnrZtwMUcmmN4sEgtE-csVFzmOOKorGZqrwbqIuLC9DSUNUmUY3iw9HocLr7gIls_thJ78ersV4

You know that awkward feeling when you get a nice text from a friend but for some reason, you don't have their number saved? You can't remember and it’s too late for you to respond with, "I'm sorry. Who is this?"

We're going to save you from the embarrassing moment of not knowing who it is by building an app that will let you identify numbers on the go over text.

How We’re Going to Avoid This Problem

Our app will take advantage of three Twilio APIs:

- Functions: the serverless environment which will hold our app

- Lookup: to look up the phone number and see who it belongs to

- SMS: to send us a text with the phone number.

The combination of these three will allow us to send a text with a phone number to our Function which will then perform a Lookup and respond to our text with the caller name (if available) connected to that phone number. Seems pretty straightforward, right?

Sign Up for Twilio & Get a Number

In order to getting started, we need to do a few things. If you don’t already have an account with Twilio, you try it for free here. After signing up, you can get your first Twilio phone number, which we will later configure.

Set Up Our Twilio Function

Next, create a Function in the Twilio Console which will execute the lookup and then text us with the caller’s name (if it exists). You can do this by clicking on the three dots on the left menu and scroll down to Runtime under Developer Tools.

On the left side, you’ll see Functions.

After you click on that, click the red plus button to create a new Function. A modal will pop-up where you can select Blank for the template.

For the name, we will call this “Lookup Number”. In the next field, add “/lookup-num” to the path. Make sure the box is checked for “Check for valid Twilio signature” and then select “Incoming Messages” for Event. Click save.

The last piece of the setup is giving our function access to our Account SID and Authorization Token. We can do this by clicking on Configure on the left side and checking the box that reads “Enable ACCOUNT_SID and AUTH_TOKEN”. This will allow us to call context.getTwilioClient() which will return a  REST client that we can use to make calls to the Twilio Lookup API.

Now that we’ll all set up, we can dive into the coding part 😎.

Parsing the Phone Number From Our Text

When a text message is sent to our app, we’ll need to do a few things:

  1. Check to make sure a US phone number was sent (area code + seven digits)
  2. Remove spaces, dashes and parentheses
  3. Add the country code to the front

To make keep our code clean and organized, we are going to write a function to do this. Inside your Function, add the following code:

function parseNumber(message) {
  // Check to make sure there are at least two numbers
  if(message.match(/\d{2,}/g)) {
    const cleanedUpNumber = message.replace(/[-() ]/g, '');
    // Check if it's less than 10 digits
    if (cleanedUpNumber.length < 10) {
      return false
    // Check if equal to 10 
    } else if (cleanedUpNumber.length === 10) {
      return `+1${cleanedUpNumber}`
    // Check if it has country code
    } else if (cleanedUpNumber.length > 10) {
      const countryCode = '+1'
      if (cleanedUpNumber.slice(0, 2) === countryCode) {
        return cleanedUpNumber
      }
    }
    return false
  } else {
    return false
  }
}

Take a look at the comments through the code to understand how the function works. We first check to make sure there are at least two digits in the message. Then we check to see if it’s a valid number (area code + seven other digits). If it is, we then check to see if it already has the country code (+1 for US numbers). If it doesn’t, we add it. In summary, this function will return false if the number is invalid, or it will return the number with the country code if it’s valid.

Send a Message in Response

The next function we’re going to write is called sendMessage. As you might assume, it will allow us to send a message in response. Add this to your Function after parseNumber.

 function sendMessage(message) {
        let twiml = new Twilio.twiml.MessagingResponse();
        twiml.message(message);
        callback(null, twiml);
    }

Because Functions come with the twilio helper library by default, this allows us to call new Twilio straight out of the box 😄

Checking for the Caller Name

Using the Lookup API, we can check if there’s a caller name available. Add this function after the previous function:

function getCallerName(number) {
      return new Promise((resolve, reject) => {
        client.lookups.phoneNumbers(number)
          .fetch({type: 'caller-name'})
          .then(phone_number => {
            resolve(phone_number.callerName.caller_name);
          })
          .done();
      });
    }

This function is a little bit different than our previous two. This one returns a Promise because we’re working with an asynchronous operation. We’re using the lookups API to lookup a number. When it is resolved, or in other words succeeds, it will return to us the caller name.

Do the Thing!

Now that we’ve made written these three awesome helper functions, it is time to make some magic happen! Add the following code to your Function:

    // Validate number
    const number = parseNumber(event.Body);
    let message = '';
        if (number) {
        // Find out who the number belongs to
        const callerName = await getCallerName(number);
        if (callerName !== null) {
            message = `This number appears to be registered to: ${callerName}`;    
        } else {
            message = `Aw. Sorry to let you down but we can't associate a name with that number.`;
        }
        
        } else {
            message = 'Oops! The number you sent doesn\'t appear to be correct. Please make sure it has ten digits. Can you try sending the number again?';
        }
        sendMessage(message);

To break it down, we first parse the number from the text message (event.Body gives us the body of the message) using our function parseNumber. Then we use our other function getCallerName to lookup the caller name using the Lookups API. Notice we’re using the keyword await because we want to *pause* the rest of our program from running until we receive the response.

Since we are working with asynchronous code and using the keyword await we need to add the keyword async at the very top on line 1 to indicate that our entire Function is asynchronous.

After everything is complete, here is what your Function should look like:

exports.handler = async function(context, event, callback) {
	// initialize Twilio client
	const client = context.getTwilioClient();
	
	function parseNumber(message) {
      // Check to make sure there are at least two numbers
      if(message.match(/\d{2,}/g)) {
        const cleanedUpNumber = message.replace(/[-() ]/g, '');
        // Check if it's less than 10 digits
        if (cleanedUpNumber.length < 10) {
          return false;
        // Check if equal to 10 
        } else if (cleanedUpNumber.length === 10) {
          return `+1${cleanedUpNumber}`;
        // Check if it has country code
        } else if (cleanedUpNumber.length > 10) {
          const countryCode = '+1';
          if (cleanedUpNumber.slice(0, 2) === countryCode) {
            return cleanedUpNumber;
          }
        }
        return false;
      } else {
        return false;
      }
    }
    
    function sendMessage(message) {
        let twiml = new Twilio.twiml.MessagingResponse();
        twiml.message(message);
        callback(null, twiml);
    }
	
	function getCallerName(number) {
      return new Promise((resolve, reject) => {
        client.lookups.phoneNumbers(number)
          .fetch({type: 'caller-name'})
          .then(phone_number => {
            resolve(phone_number.callerName.caller_name);
          })
          .done();
      });
    }
    
    // Validate number
    const number = parseNumber(event.Body);
    let message = '';
	if (number) {
        // Find out who the number belongs to
        const callerName = await getCallerName(number);
        if (callerName !== null) {
            message = `This number appears to be registered to: ${callerName}`;    
        } else {
            message = `Aw. Sorry to let you down but we can't associate a name with that number.`;
        }
        
	} else {
	    message = 'Oops! The number you sent doesn\'t appear to be correct. Please make sure it has ten digits. Can you try sending the number again?';
	}
	sendMessage(message);
}

Wire Up Our Function to a Twilio Number

Our Function is ready for business! Let’s wire it up to a Twilio number and see it in action.

Inside the Twilio Console, head over to phone numbers. Click on the phone number you purchased earlier. Scroll down to Messaging and where it says “A message comes in”, click the dropdown and select “Function”. To the right, select the “Lookup Number” Function we just created. Then click Save.

To confirm that it’s working, follow these steps:

  1. Send your cell phone number in a text to your Twilio phone number. Either your response will have a name (hopefully yours) that is associated with the number, or it will tell you ‘Aw. Sorry to let you down but we can't associate a name with that number’.
  2. Then try sending a 9 digit number like “602555123”. You should receive our custom error message “Oops! The number you sent doesn\'t appear to be correct. Please make sure it has ten digits. Can you try sending the number again?”

Say goodbye to awkward moments. Now, you have a friend you can text whenever you need to lookup a number on the go 😉

If you enjoyed this tutorial, tweet me @jsjoeio and let me know.