Instant Lead Alerts with Node.js and Express

You probably already have landing pages or product detail views which you're using to generate some excellent leads for your business.  Would you like to let the sales team know when you've got a new qualified lead?

In this tutorial we'll use Twilio Programmable SMS in a Node.js and Express application to send a message when a new lead is found.

Lead Alerts Flow

In this example we'll be implementing instant lead alerts for a fictional real estate agency.

We'll create a landing page for a new house on the market and notify a real estate agent the moment a potential customer requests information.

Learn how Porch uses Twilio SMS to send home contractors instant alerts when they are selected for a new project.

Loading Code Samples...
Language
var cfg = {};

// HTTP Port to run our web application
cfg.port = process.env.PORT || 3000;

// A random string that will help generate secure one-time passwords and
// HTTP sessions
cfg.secret = process.env.APP_SECRET || 'keyboard cat';

// Your Twilio account SID and auth token, both found at:
// https://www.twilio.com/user/account
// 
// A good practice is to store these string values as system environment
// variables, and load them from there as we are doing below. Alternately,
// you could hard code these values here as strings.
cfg.accountSid = process.env.TWILIO_ACCOUNT_SID;
cfg.authToken = process.env.TWILIO_AUTH_TOKEN;

// A Twilio number you control - choose one from:
// https://www.twilio.com/user/account/phone-numbers/incoming
// Specify in E.164 format, e.g. "+16519998877"
cfg.twilioNumber = process.env.TWILIO_NUMBER;

// The sales rep / agent's phone number
cfg.agentNumber = process.env.AGENT_NUMBER;

// Export configuration object
module.exports = cfg;
config.js
Configuration values for your Express server

config.js

Let's build!  Click the button below to continue.

Populate Landing Page Data

To display a landing page for our house we first need some information we'd like to display for the user.

For demonstration purposes we've hard-coded an object containing the information we need.

Loading Code Samples...
Language
const Twilio = require('twilio');
const config = require('../config');
const Express = require('express');


// Some hard-coded information about a house
var house = {
    title: '555 Sunnybrook Lane',
    price: '$349,999',
    description: 'You and your family will love this charming home. '
        + 'Featuring granite appliances, stainless steel windows, and '
        + 'high efficiency dual mud rooms, this joint is loaded to the max. '
        + 'Motivated sellers have priced for a quick sale, act now!'
};

// Map routes to controller functions
module.exports = function () {
    // Create an authenticated Twilio API client
    var client = new Twilio(config.accountSid, config.authToken);
    const router = Express.Router();

    // Render landing page
    router.get('/', function(request, response) {
        response.render('index', house);
    });

    // Send lead notification
    router.post('/leads', function(request, response) {
        // Assemble a text message body
        var message = 'New lead received for ' + house.title + '. Call '
            + request.body.name + ' at ' + request.body.phone + '. Message: "'
            + request.body.message + '"';

        // Send lead notification to agent
        client.messages.create({
            to: config.agentNumber,
            from: config.twilioNumber,
            body: message
        })
        .then(() => {
          // Otherwise, respond with 200 OK
          response.status(200).send('Lead notification was successfully sent.');
        })
        .catch((err) => {
          console.error(err);
          response.status(500).send();
        })
    });

    return router;
};
controllers/router.js
Routes to expose listing data and qualify new leads

controllers/router.js

Next, let's look at how our landing page will be rendered.

Render the Landing Page

In our Jade template we insert data about the house.  

We'll also include a form in the sidebar which will let a user enter their contact information when they request more information.

 

Loading Code Samples...
Language
extends layout

block content
  .row
    .col-sm-8
      h1= title
      h3= price
      p
        img.img-responsive(src="/house.jpg")
      p= description

    .col-sm-4.demo
      h4 Talk To An Agent
      p.
        A trained real estate professional is standing by to answer any
        questions you might have about this property. Fill out the form below
        with your contact information, and an agent will reach out soon.

      form(action='/leads', method='POST')

        .form-group
          label(for='name') Your Name
          input.form-control(type='text', name='name',
            placeholder='John Appleseed')

        .form-group
          label(for='phone') Your Phone Number
          input.form-control(type='text', name='phone',
            placeholder='+16512229988')

        .form-group
          label(for='message') How can we help?
          input.form-control(type='text', name='message',
            placeholder='')        

        button.btn.btn-primary(type='submit') Request Info

block scripts
  script(src='form.js')
views/index.jade
Landing page template

views/index.jade

Now that our Landing Page is ready, let's setup our Twilio Client to send messages to the sales team whenever a new lead comes in.

Creating a Twilio REST API Client

Now we need to create a helper class with an authenticated Twilio REST API client that we can use anytime we need to send a text message.

We initialize it with our Twilio Account Credentials stored as environment variables.  You can find the Auth Token and Account SID in the console:

console credentials

Loading Code Samples...
Language
const Twilio = require('twilio');
const config = require('../config');
const Express = require('express');


// Some hard-coded information about a house
var house = {
    title: '555 Sunnybrook Lane',
    price: '$349,999',
    description: 'You and your family will love this charming home. '
        + 'Featuring granite appliances, stainless steel windows, and '
        + 'high efficiency dual mud rooms, this joint is loaded to the max. '
        + 'Motivated sellers have priced for a quick sale, act now!'
};

// Map routes to controller functions
module.exports = function () {
    // Create an authenticated Twilio API client
    var client = new Twilio(config.accountSid, config.authToken);
    const router = Express.Router();

    // Render landing page
    router.get('/', function(request, response) {
        response.render('index', house);
    });

    // Send lead notification
    router.post('/leads', function(request, response) {
        // Assemble a text message body
        var message = 'New lead received for ' + house.title + '. Call '
            + request.body.name + ' at ' + request.body.phone + '. Message: "'
            + request.body.message + '"';

        // Send lead notification to agent
        client.messages.create({
            to: config.agentNumber,
            from: config.twilioNumber,
            body: message
        })
        .then(() => {
          // Otherwise, respond with 200 OK
          response.status(200).send('Lead notification was successfully sent.');
        })
        .catch((err) => {
          console.error(err);
          response.status(500).send();
        })
    });

    return router;
};
controllers/router.js
Create a Twilio REST Client

controllers/router.js

Our Twilio Client is now ready to send messages.  Next, let's see how we will handle an incoming lead.

Handling the POST Request

This code handles the HTTP POST request issued by our landing page.

Here we use the Twilio REST API Client to send an SMS message to the real estate agent's phone number, which is stored in an environment variable. We include the lead's name, phone number, and inquiry directly in the body of the text message sent to the agent.

Now the agent has all the information they need to follow up on the lead.

Loading Code Samples...
Language
const Twilio = require('twilio');
const config = require('../config');
const Express = require('express');


// Some hard-coded information about a house
var house = {
    title: '555 Sunnybrook Lane',
    price: '$349,999',
    description: 'You and your family will love this charming home. '
        + 'Featuring granite appliances, stainless steel windows, and '
        + 'high efficiency dual mud rooms, this joint is loaded to the max. '
        + 'Motivated sellers have priced for a quick sale, act now!'
};

// Map routes to controller functions
module.exports = function () {
    // Create an authenticated Twilio API client
    var client = new Twilio(config.accountSid, config.authToken);
    const router = Express.Router();

    // Render landing page
    router.get('/', function(request, response) {
        response.render('index', house);
    });

    // Send lead notification
    router.post('/leads', function(request, response) {
        // Assemble a text message body
        var message = 'New lead received for ' + house.title + '. Call '
            + request.body.name + ' at ' + request.body.phone + '. Message: "'
            + request.body.message + '"';

        // Send lead notification to agent
        client.messages.create({
            to: config.agentNumber,
            from: config.twilioNumber,
            body: message
        })
        .then(() => {
          // Otherwise, respond with 200 OK
          response.status(200).send('Lead notification was successfully sent.');
        })
        .catch((err) => {
          console.error(err);
          response.status(500).send();
        })
    });

    return router;
};
controllers/router.js
Handle a POST from the lead form

controllers/router.js

That's a wrap! We've just implemented an application to instantly route leads to salespeople using text messages. 

Itching to build more?  We'll look at some other use cases in the next pane.

Where to Next?

Node and Twilio - a great combination.  Here are a couple other times we teamed them up for great results:

Appointment Reminders

Learn to implement appointment reminders on your web app with Twilio, and avoid some of those no-shows.

Two-Factor Authentication with Authy

Learn to implement two-factor authentication (2FA) on your web app with Twilio-powered Authy.

Did this help?

Thanks for checking out this tutorial!  Tweet @twilio to let us know what you're building.

Kevin Whinnery
Jose Oliveros
Paul Kamp
Andrew Baker

Need some help?

We all do sometimes; code is hard. Get help now from our support team, or lean on the wisdom of the crowd browsing the Twilio tag on Stack Overflow.

1 / 1
Loading Code Samples...
var cfg = {};

// HTTP Port to run our web application
cfg.port = process.env.PORT || 3000;

// A random string that will help generate secure one-time passwords and
// HTTP sessions
cfg.secret = process.env.APP_SECRET || 'keyboard cat';

// Your Twilio account SID and auth token, both found at:
// https://www.twilio.com/user/account
// 
// A good practice is to store these string values as system environment
// variables, and load them from there as we are doing below. Alternately,
// you could hard code these values here as strings.
cfg.accountSid = process.env.TWILIO_ACCOUNT_SID;
cfg.authToken = process.env.TWILIO_AUTH_TOKEN;

// A Twilio number you control - choose one from:
// https://www.twilio.com/user/account/phone-numbers/incoming
// Specify in E.164 format, e.g. "+16519998877"
cfg.twilioNumber = process.env.TWILIO_NUMBER;

// The sales rep / agent's phone number
cfg.agentNumber = process.env.AGENT_NUMBER;

// Export configuration object
module.exports = cfg;
const Twilio = require('twilio');
const config = require('../config');
const Express = require('express');


// Some hard-coded information about a house
var house = {
    title: '555 Sunnybrook Lane',
    price: '$349,999',
    description: 'You and your family will love this charming home. '
        + 'Featuring granite appliances, stainless steel windows, and '
        + 'high efficiency dual mud rooms, this joint is loaded to the max. '
        + 'Motivated sellers have priced for a quick sale, act now!'
};

// Map routes to controller functions
module.exports = function () {
    // Create an authenticated Twilio API client
    var client = new Twilio(config.accountSid, config.authToken);
    const router = Express.Router();

    // Render landing page
    router.get('/', function(request, response) {
        response.render('index', house);
    });

    // Send lead notification
    router.post('/leads', function(request, response) {
        // Assemble a text message body
        var message = 'New lead received for ' + house.title + '. Call '
            + request.body.name + ' at ' + request.body.phone + '. Message: "'
            + request.body.message + '"';

        // Send lead notification to agent
        client.messages.create({
            to: config.agentNumber,
            from: config.twilioNumber,
            body: message
        })
        .then(() => {
          // Otherwise, respond with 200 OK
          response.status(200).send('Lead notification was successfully sent.');
        })
        .catch((err) => {
          console.error(err);
          response.status(500).send();
        })
    });

    return router;
};
extends layout

block content
  .row
    .col-sm-8
      h1= title
      h3= price
      p
        img.img-responsive(src="/house.jpg")
      p= description

    .col-sm-4.demo
      h4 Talk To An Agent
      p.
        A trained real estate professional is standing by to answer any
        questions you might have about this property. Fill out the form below
        with your contact information, and an agent will reach out soon.

      form(action='/leads', method='POST')

        .form-group
          label(for='name') Your Name
          input.form-control(type='text', name='name',
            placeholder='John Appleseed')

        .form-group
          label(for='phone') Your Phone Number
          input.form-control(type='text', name='phone',
            placeholder='+16512229988')

        .form-group
          label(for='message') How can we help?
          input.form-control(type='text', name='message',
            placeholder='')        

        button.btn.btn-primary(type='submit') Request Info

block scripts
  script(src='form.js')
const Twilio = require('twilio');
const config = require('../config');
const Express = require('express');


// Some hard-coded information about a house
var house = {
    title: '555 Sunnybrook Lane',
    price: '$349,999',
    description: 'You and your family will love this charming home. '
        + 'Featuring granite appliances, stainless steel windows, and '
        + 'high efficiency dual mud rooms, this joint is loaded to the max. '
        + 'Motivated sellers have priced for a quick sale, act now!'
};

// Map routes to controller functions
module.exports = function () {
    // Create an authenticated Twilio API client
    var client = new Twilio(config.accountSid, config.authToken);
    const router = Express.Router();

    // Render landing page
    router.get('/', function(request, response) {
        response.render('index', house);
    });

    // Send lead notification
    router.post('/leads', function(request, response) {
        // Assemble a text message body
        var message = 'New lead received for ' + house.title + '. Call '
            + request.body.name + ' at ' + request.body.phone + '. Message: "'
            + request.body.message + '"';

        // Send lead notification to agent
        client.messages.create({
            to: config.agentNumber,
            from: config.twilioNumber,
            body: message
        })
        .then(() => {
          // Otherwise, respond with 200 OK
          response.status(200).send('Lead notification was successfully sent.');
        })
        .catch((err) => {
          console.error(err);
          response.status(500).send();
        })
    });

    return router;
};
const Twilio = require('twilio');
const config = require('../config');
const Express = require('express');


// Some hard-coded information about a house
var house = {
    title: '555 Sunnybrook Lane',
    price: '$349,999',
    description: 'You and your family will love this charming home. '
        + 'Featuring granite appliances, stainless steel windows, and '
        + 'high efficiency dual mud rooms, this joint is loaded to the max. '
        + 'Motivated sellers have priced for a quick sale, act now!'
};

// Map routes to controller functions
module.exports = function () {
    // Create an authenticated Twilio API client
    var client = new Twilio(config.accountSid, config.authToken);
    const router = Express.Router();

    // Render landing page
    router.get('/', function(request, response) {
        response.render('index', house);
    });

    // Send lead notification
    router.post('/leads', function(request, response) {
        // Assemble a text message body
        var message = 'New lead received for ' + house.title + '. Call '
            + request.body.name + ' at ' + request.body.phone + '. Message: "'
            + request.body.message + '"';

        // Send lead notification to agent
        client.messages.create({
            to: config.agentNumber,
            from: config.twilioNumber,
            body: message
        })
        .then(() => {
          // Otherwise, respond with 200 OK
          response.status(200).send('Lead notification was successfully sent.');
        })
        .catch((err) => {
          console.error(err);
          response.status(500).send();
        })
    });

    return router;
};