Respond to Incoming SMS with NodeJS and Google Cloud Functions

card image
February 21, 2024
Written by
Reviewed by

Respond to Incoming SMS with NodeJS and Google Cloud Functions

In today's fast-paced world, businesses have realized the power of instant communication with their customers via SMS and WhatsApp. But just sending out messages doesn’t live up to a good customer experience. Customers also expect to be able to respond to these messages. And your apps should do so with clever messages. If that excites you, you're in the right place!

In this article, you'll explore how to architect a robust mechanism for managing incoming SMS using Google Cloud Functions (Pub/Sub), and Node.js.

Typically, Twilio Functions serve as the ideal platform for serverless tasks involving SMS. This purpose-built environment is tailored to build and run code that interacts with Twilio’s communications platform. However, specific project requirements or constraints might necessitate the use of other runtimes, like Google Cloud Functions. This post demonstrates that you still have powerful options outside Twilio's sphere. Remember, your best tech choice always aligns with your specific needs!

Prerequisites

Our journey demands that you come pre-equipped with the following:

Let's gear up and embrace the exciting and challenging art of reciprocating incoming SMS messages using Google Cloud Functions and Node.js.

Handling Incoming SMS with Google Cloud Functions

A webhook is a method used by web applications to communicate with each other in real-time when a specific event occurs. They can be part of a traditional monolithic application, but they are especially suitable for serverless functions due to their scaling behavior. Let's put this into action:

Use the Power of Google Cloud Functions

Google Cloud Functions act as building blocks for serverless applications and allow you to run your code without provisioning or managing servers.

Go to the GCP Console to create a new Cloud Function. Click the blue Create Function button.

GCP console to create a new function

You possibly need to enable the proper API in a modal dialog. If you see this one, confirm with Enable

In the next dialog, give the new function a name like receive-sms. Make sure the HTTPS-based trigger is selected, and unauthenticated invocations are allowed. Only this way will Twilio be able to trigger the webhook.

Create function flow

Hit Next to start implementing the Cloud Function. You might also need to enable another set of APIs.

Implement the Serverless Function

The next user interface shows you the Inline Editor to implement the function. First, add the twilio dependency in the package.json.

{ 
  "dependencies": { 
    "@google-cloud/functions-framework": "^3.0.0", 
    "twilio": "4.21.0" 
  }
}

Then, implement the function that uses the `twilio` package to create a TwiML response that includes a random Dad Joke.

const functions = require("@google-cloud/functions-framework");
const { twiml } = require("twilio");

const jokes = [
 "What do kids eat for breakfast? Yogoat!",
 "What form of radiation bakes you cookies? A gramma ray",
 "Why cant college students take exams at the zoo? Too many cheetahs",
 "What does a storm cloud have on beneath its clothes? Thunderwear!",
];

functions.http("helloHttp", (req, res) => {
 // You can parse message details from the request body
 // e.g. console.log((req.body.From)
 const idx = Math.floor(Math.random() * jokes.length);
 const twimlRes = new twiml.MessagingResponse();
 twimlRes.message(jokes[idx]);
 res.type("text/xml");
 res.send(twimlRes.toString());
});

Click Deploy to activate the Cloud Function. After deployment, you should see the URL of the function and copy it for later.

const functions = require("@google-cloud/functions-framework");
const { PubSub } = require('@google-cloud/pubsub');
const { twiml } = require("twilio");

const pubsub = new PubSub();

functions.http("helloHttp", (req, res) => {
  const topic = pubsub.topic(req.body.topic);

  const messageObject = {
    data: {
      message: req.body.body,
      from: req.body.from,
    },
  };
  const messageBuffer = Buffer.from(JSON.stringify(messageObject), 'utf8');

 // Publish a message
 try {
  topic.publishMessage(messageBuffer);
 } catch (err) {
  console.error(err);
 }

//return an empty response and send another message later
 const twimlRes = new twiml.MessagingResponse();
 res.type("text/xml");
 res.send(twimlRes.toString());
});

The snippet above also illustrates the possibility of sending a message to the Pub/Sub Messaging Service so that other cloud services can react to it. This is beneficial if you need to spawn off a long-running process, such as an AI bot, that will proactively send a response. It’s not recommended to wait for long-running computations, such as AI, in the webhook directly, as this might cause a timeout. Even if the result comes back before the timeout, this leads to a lot of idle time, which might not be cost-effective as the compute time is a component of Google Cloud Functions pricing.

 

Test the Function

You can test this function in a new browser tab, since this function explicitly allows unauthenticated inbound traffic. This is great. Alternatively, you can also use curl:

 

curl  -X GET https://us-central1-<project-name>.cloudfunctions.net/receive-sms

In production, you would want to verify the signature of the request to make sure it’s sent by Twilio and no one else. It might also make sense to bundle multiple Cloud Functions behind an API Gateway .

Purchase the phone number you want to use

To send a message, you need to buy a phone number—ideally from the region you are based in—to avoid roaming charges. To accomplish this, go to the Twilio Console and search for a number you’d like to buy.

Twilio Console to purchase a number
Regulators all over the world try to fight SMS fraud by implementing certain guidelines and restrictions on the purchase of phone numbers. So there might be some additional steps required for your country. Here’s a list of all the regulatory guidelines .

Register the Function as Webhook

Now it’s time to go to the Twilio Console and find the number you purchased earlier. Click on the number, go to the Configure tab, and find the Messaging Configuration box. In this box, there’s a section A message comes in. Make sure you add the URL of your function as a webhook and that it’s using HTTP POST.

Twilio console to register webhook with number
Did you know that you can reuse the same webhook to respond to incoming WhatsApp messages ? You only need to add the URL of your function in the configuration of the WhatsApp Sender.

You've just simplified customer communication by automating the complex process of handling incoming messages. Feel the power yet? Maybe you start feeling it when you text that number and receive a “funny” dad joke.

Conclusion

Handling incoming SMS with Google Cloud Functions opens up countless possibilities for better customer interactions. Especially if you have already built on Google Cloud Platform. It adds responsiveness and dynamism to your customer interactions - from quick acknowledgements to instant automated actions.

Let's keep feeding our curiosity, and never stop learning. I can’t wait to see what you build.