September 23, 2014

Holy biscuits was last week a barrel of monkeys.  All of us at Twilio have had a beastly boatload of fun seeing the stuff you’ve started building with Twilio MMS.  Many of you blazed through Kevin’s Getting Started with MMS tutorial over the weekend to get started on your hacks and, of course, seeing all your mustached faces with the example project we built last week remains a source of never-ending laughs.

Selection_005

This go round, I thought we would have a look at something a little more real world.  Working on the devangel crew, I get to travel around the world meeting all kinds of developers producing rad work.  While on the road, keeping an eye on the apartment back in Brooklyn definitely provides some peace of mind.  For my second hack, I thought I might provide that in real time using MMS.  These kinds of cameras are available on Amazon for $180, but I wanted to see if I could build my own for $0 with my Linux desktop, a webcam I already own and a little Python code.

What does it look like?  Let’s take a look at what happened when a clearly agitated mutant horseman broke into my apartment after deploying the Twilio-powered camera.

Yeesh.  Harrowing.

For this project, we’re going to build a security camera that sends a photo whenever motion is detected using the tools below.

What You Will Need

For this project, we’re going to need a few things before we get started.

How It Works

We’ll leverage a few different technologies to build our MMS enabled security camera.  We’ll use an excellent software motion detector for Linux (aptly called Motion) to watch for any movement in the frame.  When Motion detects some movement, it’ll launch our Python app which will look for an arbitrary number of images over a few seconds to craft into an alert.

Now, if our machine connected to the camera was available on the public Internet, the images would be easily available for Twilio to see.  However, as a quick Google search will show, having your security camera available on the Internet may not be a great idea.  So instead, our script will upload that photo to Amazon S3 so that Twilio can get it.  We’ll then use Twilio MMS to send ourselves a message with the S3 public link as the MediaUrl.

Getting Started

Let’s begin by getting our dependencies installed.  First, we’ll need to install some Python modules to interact with Twilio and with Amazon S3.  Note, if you are not using virtualenv, you will need administrator privileges to install.

pip install twilio boto

If you prefer, you can use a requirements.txt file to do this.

boto==2.32.1
twilio==3.6.7

Next, we’ll install Motion to handle our video.  Installation options for his open source motion detector are here for the Linux distribution of your choice – for this tutorial, we’ll use Ubuntu.

sudo apt-get install motion

 

Finally, we’ll create a new S3 bucket to house our camera.  First, we’ll log into the AWS Management Console and navigate to S3 administration panel.  Then we’ll click the Create Bucket button in the upper left hand corner.

 

Next, we’ll name our bucket.

 

Then we’ll open the properties of our newly created bucket.

 

Then add a new bucket policy in the Permissions dialog:

 

 

Click “Add a new policy”.

Next, we’ll write a new policy to make the photos we upload publicly accessible so Twilio can reach them for our MMS alerts.  Bucket policies are written in JSON and you can use this template as a guide:

{
  "Version":"2012-10-17",
  "Statement":[{
	"Sid":"AddPerm",
        "Effect":"Allow",
	  "Principal": "*",
      "Action":["s3:GetObject"],
      "Resource":["arn:aws:s3:::<put-name-of-bucket-here>/*"
      ]
    }
  ]
}

Finally we’ll click “Save” to apply the policy making sure all the images we upload will be available on S3.

For one last optional step, we can create a new access key for our app.  First we’ll go to the Security Credentials page of our management console and click on “Access Keys.”

And then we can generate a new key.

Click Show Access Key and we can keep our values for our AWS credentials or download the root key csv file.

With our AWS setup completed, we’re ready to get Motion configured.

Configuring Motion

The first piece we need to set up is the configuration of Motion to use our camera.  This will involve manipulating a few of the configuration settings to execute the script that we are going to write together.  We can copy the example below into a file we’ll call local.conf.

Here’s an example with the important values we need:

# Image width - default is very low. Motion does require these values
# to be a multiple of 16, so default HD resolutions will not work.
width 1024       
height 768                                                              

# Target directory of where we want our images to go.                                
target_dir images                                                            

# Script we want to execute when a motion event begins.  Whole lot of
# configuration needs to be done here including:
# - Twilio Account Sid                      
# - Twilio Auth Token           
# - Twilio Phone Number                                                     
# - Receiving Number you wish to get the alerts
# - AWS Access Key ID                          
# - AWS Secret Key                     
# - Name of S3 bucket   
# We also pass the timestamp of the event to use as a key for the image.
#  Numbers must be in E.164 format.       
#  When the event starts, we'll send 3 images that are a second apart
on_event_start python motionalert.py --account_sid=ACxxxxxxx --auth_token=yyyyy --aws_access_key_id=wwwww --aws_secret_key=zzzz --s3_bucket=your-bucket-name-here --twilio_number=+15556667777 --receiving_number=+15558675309 --timestamp==%Y-%m-%d-%H-%M-%S-%q --body="Motion detected at %H:%M!" --motion_target_dir images --num_of_images 3
# When the event ends, we'll send the last frame.
on_event_end python motionalert.py --account_sid=ACxxxxxxx --auth_token=yyyyy --aws_access_key_id=wwwww --aws_secret_key=zzzz --s3_bucket=your-bucket-name-here --twilio_number=+15556667777 --receiving_number=+15558675309 --timestamp==%Y-%m-%d-%H-%M-%S-%q --body="Motion ended at %H:%M." --motion_target_dir images --num_of_images 1

With this configuration, each time period during which Motion detects movement in the frame, it will execute a Python app twice – once at the beginning of the movement and once at the end.  Now all that is left is to write the app itself.

Connecting Motion To Your Phone With Twilio

With our bucket and motion detector configured, we can now cut some code.  Our app will need to do three things:

  1. Get an image that Motion has recorded.
  2. Upload that image to a place where Twilio can retrieve it.
  3. Create a new Twilio message with the location of that image as the MediaUrl.

Let’s create that app together by opening a new file named motionalert.py.

First up, we will import everything we need for the app and create a class to serve as basis for the alerts we want to send from Motion through Twilio to our phones.  We’ll also create an Exception handler so we can gracefully return error information in the command line with a hint to use our command line interface’s --help flag.

 

import os
import glob
import argparse
import logging
from time import sleep

from twilio.rest import TwilioRestClient
from twilio.exceptions import TwilioException

from boto.s3.connection import S3Connection
from boto.s3.key import Key

class MotionAlert(object):
    def __init__(self, account_sid=None, auth_token=None,
                 aws_access_key_id=None, aws_secret_key=None, s3_bucket=None,
                 twilio_number=None, receiving_number=None,
                 motion_target_dir=None, timestamp=None, body=None,
                 num_of_images=None):
        """
        A class that sends Twilio MMS alerts based on input from Motion, a
        software movement detector for Linux.

        Attributes:
            account_sid: Your Twilio Account Sid.
            auth_token: Your Twilio Auth Token.
            aws_access_key_id: Your AWS Access Key Id.
            aws_secret_key: Your AWS Secret Key.
            s3_bucket: The name of the AWS S3 bucket to use for uploading
                       images.
            twilio_number: The Twilio number from which alerts will be sent.
            receiving_number: The number you wish to receive alerts.
            motion_target_dir: Path to where Motion is storing its images.
            timestamp: Current timestamp, generated by the Motion event.
            body: Text of the message you want to send.
            num_of_images: An integer of the number of images you wish
                           to send in your alert.
            twilio_client: A Twilio client object initialized with your
                           credentials.
            s3_connection: A S3 connection object initialized with your
                           credentials.
        """
        self.account_sid = account_sid
        self.auth_token = auth_token
        self.aws_access_key_id = aws_access_key_id
        self.aws_secret_key = aws_secret_key
        self.s3_bucket = s3_bucket
        self.twilio_number = twilio_number
        self.receiving_number = receiving_number
        self.motion_target_dir = motion_target_dir
        self.timestamp = timestamp
        self.body = body
        self.num_of_images = int(num_of_images)

        # Initialize our two API clients with our credentials.
        self.twilio_client = TwilioRestClient(self.account_sid,
                                              self.auth_token)
        try:
            self.s3_connection = S3Connection(self.aws_access_key_id,
                                              self.aws_secret_key)
        except Exception as e:
            raise MotionAlertError("Error connecting to S3: {0}".format(e))

class MotionAlertError(Exception):
    def __init__(self, message):
        """
        An Exception that handles output of errors to the user.

        Arguments:
            message: The message you want to display to the user for the
            exception.
        """
        logging.error("ERROR: {0}".format(message))
        logging.error("Try running with --help for more information.")

Next, we’ll define a function to get an image that Motion recorded.  As Motion operates on a buffer for the motion analysis, we can just grab the most recently created image in the target directory to be reasonably assured it will catch something meaningful in frame.

def get_latest_image_from_directory(self, motion_target_dir):
        """Retrieves the most recently created .jpg file from target directory.

        Arguments:
            motion_target_dir: The directory in which Motion stores its images.

        Returns:
            String with path to most recently created image.
        """
        try:
            # Use a glob generator to find the newest image
            return max(glob.iglob('{0}/*.jpg'.format(motion_target_dir)),
                       key=os.path.getctime)
        except ValueError as e:
            # Raise an error if we did not find any images
            raise MotionAlertError("Could not find any images in motion "
                                   "target directory: "
                                   "{0}".format(motion_target_dir))
        except OSError as e:
            # Raise an error if we cannot access the directory.
            raise MotionAlertError("Could not find the motion target dir: "
                                   "{0}".format(e))

Now that we have code to find images, we need to upload them to S3 so Twilio can find them for the messages we are about to create.  Now, here’s where we start using that S3 bucket we set up earlier in the tutorial.  Let’s define a function on our MotionAlert class to help us upload our images to that bucket.

def upload_image_to_s3(self, image_file_path, bucket_name):
        """Uploads images to Amazon's S3 service.

        Arguments:
            image_file_path: Path to image to upload on local machine.
            bucket_name: Name of the S3 bucket where image should be uploaded.
            key_name: Name of the key for the file on S3 (usually the
                      timestamp).
        """
        try:
            # Attempt to get the S3 bucket with our S3 connection.
            bucket = self.s3_connection.get_bucket(bucket_name)
        except Exception as e:
            # Error out if we're unable to locate the S3 bucket.
            raise MotionAlertError("Error connecting to S3 bucket: "
                                   "{0}".format(e))

        try:
            # Create a new key using image_file_path as the key
            key = Key(bucket)
            key.key = image_file_path 
            key.set_contents_from_filename(image_file_path)
            return key
        except Exception as e:
            # Error out if we're unable to upload the image.
            raise MotionAlertError("Error uploading file to S3: {0}".format(e))

Now that we have the image in a place where Twilio can see it, let’s add another function to our MotionAlert class to send an MMS to our phones.

def send_alert_to_phone_number(self, from_=None, to=None, body=None,
                                   media_url=None):
        """Sends a MMS using Twilio.

        Keyword Arguments:
            from_: The Twilio number from which the alert will be sent.
            to: The phone number that will receive the alert.
            body: Text for the alert.
            media_url: The fully qualified path to the image for the alert
                       available on the Internet.
        """
        try:
            # Send the alert using the Twilio Messages resource.
            self.twilio_client.messages.create(from_=from_, to=to,
                                               body=body, media_url=media_url)
        except TwilioException as e:
            # Error out if the request fails.
            raise MotionAlertError("Error sending MMS with Twilio: "
                                   "{0}".format(e))

Now, let’s tie all that together with a send function to string our three functions together.

def send(self):
        """Send an alert via Twilio MMS from Motion.
        Returns:
            message: a Twilio Message object from a successful request.
        """
        # Let the user know we're working on sending an alert to a phone number.
        logging.info("Sending alert to {0}...".format(self.receiving_number))

        # Get the specified series of images from the camera.
        image_paths = []
        for i in xrange(self.num_of_images):
            image_file_path = \
                self.get_latest_image_from_directory(self.motion_target_dir)
            # Wait 2 seconds to get next image
            image_paths.append(image_file_path)
            if i != self.num_of_images:
                sleep(1)

        # Try to upload that image to S3.
        s3_keys = []
        if image_paths:
            for image_path in reversed(image_paths):
                s3_key = self.upload_image_to_s3(image_path,
                                                 self.s3_bucket)
                s3_keys.append(s3_key)
        else:
            raise MotionAlertError("Could not retrieve an image to send.")

        # Try to send the image uploaded to S3 via Twilio MMS.
        if s3_keys:
            media_urls = []
            for s3_key in s3_keys:
                media_url = "https://s3.amazonaws.com/{0}" \
                            "/{1}".format(self.s3_bucket,
                                          s3_key.key)
                media_urls.append(media_url)
            message = self.send_alert_to_phone_number(from_=self.twilio_number,
                                                      to=self.receiving_number,
                                                      body=self.body,
                                                      media_url=media_urls)
            return message
        else:
            raise MotionAlertError("Could not send image to "
                                   "{0}.".format(self.receiving_number))

        # Confirm to user we are complete sending the alert.
        if message:
            logging.info("Alert sent to {0}.".format(self.receiving_number))
        else:
            logging.error("An unknown error occured sending to "
                          "{0}.".format(self.receiving_number))

Lastly, let’s create a command line interface for our class by using argparse.

# Create a command line interface for our class.
parser = argparse.ArgumentParser(description="Motion Alert - send MMS alerts "
                                             "from Motion events.",
                                 epilog="Powered by Twilio!")

parser.add_argument("-S", "--account_sid", default=None, required=True,
                    help="Use a specific Twilio Account Sid.")
parser.add_argument("-K", "--auth_token", default=None, required=True,
                    help="Use a specific Twilio Auth Token.")
parser.add_argument("-#", "--twilio_number", default=None, required=True,
                    help="Use a specific Twilio phone number "
                         "(e.g. +15556667777).")
parser.add_argument("-s", "--aws_access_key_id", default=None, required=True,
                    help="Use a specific Amazon Web Services Access Key Id.")
parser.add_argument("-k", "--aws_secret_key", default=None, required=True,
                    help="Use a specific Amazon Web Services Secret Key.")
parser.add_argument("-b", "--s3_bucket", default=None, required=True,
                    help="Use a specific Amazon Web Services S3 Bucket.")
parser.add_argument("-t", "--receiving_number", default=None, required=True,
                    help="Number to receive the alerts.")
parser.add_argument("-T", "--timestamp", default=None, required=True,
                    help="Timestamp of event passed from Motion.")
parser.add_argument("-B", "--body", default=None, required=True,
                    help="Body of message you wish to send.")
parser.add_argument("-d", "--motion_target_dir", default=None, required=True,
                    help="Directory where Motion is storing images from "
                         "motion capture.")
parser.add_argument("-i", "--num_of_images", default=None, required=True,
                    help="Number of image to send in an alert.")

# Configure our logging for the CLI output.
logging.basicConfig(level=logging.INFO, format="%(message)s")

# Present that CLI to the user when the Python file is executed.
if __name__ == "__main__":
    args = parser.parse_args()
    motion_alert = MotionAlert(**vars(args))
    motion_alert.send()

With the pieces of functionality in place, let’s put it all together to see what it looks like together in one copy/pasteable snippet.

import os
import glob
import argparse
import logging
from time import sleep

from twilio.rest import TwilioRestClient
from twilio.exceptions import TwilioException

from boto.s3.connection import S3Connection
from boto.s3.key import Key

class MotionAlert(object):
    def __init__(self, account_sid=None, auth_token=None,
                 aws_access_key_id=None, aws_secret_key=None, s3_bucket=None,
                 twilio_number=None, receiving_number=None,
                 motion_target_dir=None, timestamp=None, body=None,
                 num_of_images=None):
        """
        A class that sends Twilio MMS alerts based on input from Motion, a
        software movement detector for Linux.

        Attributes:
            account_sid: Your Twilio Account Sid.
            auth_token: Your Twilio Auth Token.
            aws_access_key_id: Your AWS Access Key Id.
            aws_secret_key: Your AWS Secret Key.
            s3_bucket: The name of the AWS S3 bucket to use for uploading
                       images.
            twilio_number: The Twilio number from which alerts will be sent.
            receiving_number: The number you wish to receive alerts.
            motion_target_dir: Path to where Motion is storing its images.
            timestamp: Current timestamp, generated by the Motion event.
            body: Text of the message you want to send.
            num_of_images: An integer of the number of images you wish 
                           to send in your alert.
            twilio_client: A Twilio client object initialized with your
                           credentials.
            s3_connection: A S3 connection object initialized with your
                           credentials.
        """
        self.account_sid = account_sid
        self.auth_token = auth_token
        self.aws_access_key_id = aws_access_key_id
        self.aws_secret_key = aws_secret_key
        self.s3_bucket = s3_bucket
        self.twilio_number = twilio_number
        self.receiving_number = receiving_number
        self.motion_target_dir = motion_target_dir
        self.timestamp = timestamp
        self.body = body
        self.num_of_images = int(num_of_images)

        # Initialize our two API clients with our credentials.
        self.twilio_client = TwilioRestClient(self.account_sid,
                                              self.auth_token)
        try:
            self.s3_connection = S3Connection(self.aws_access_key_id,
                                         self.aws_secret_key)
        except Exception as e:
            raise MotionAlertError("Error connecting to S3: {0}".format(e))

    def send(self):
        """Send an alert via Twilio MMS from Motion.
        Returns:
            message: a Twilio Message object from a successful request.
        """
        # Let the user know we're working on sending an alert to a phone number.
        logging.info("Sending alert to {0}...".format(self.receiving_number))

        # Get the specified series of images from the camera.
        image_paths = []
        for i in xrange(self.num_of_images):
            image_file_path = \
                self.get_latest_image_from_directory(self.motion_target_dir)
            # Wait 2 seconds to get next image
            image_paths.append(image_file_path)
            if i != self.num_of_images:
                sleep(1)

        # Try to upload that image to S3.
        s3_keys = []
        if image_paths:
            for image_path in reversed(image_paths):
                s3_key = self.upload_image_to_s3(image_path,
                                                 self.s3_bucket)
                s3_keys.append(s3_key)
        else:
            raise MotionAlertError("Could not retrieve an image to send.")

        # Try to send the image uploaded to S3 via Twilio MMS.
        if s3_keys:
            media_urls = []
            for s3_key in s3_keys:
                media_url = "https://s3.amazonaws.com/{0}" \
                            "/{1}".format(self.s3_bucket,
                                          s3_key.key)
                media_urls.append(media_url)
            message = self.send_alert_to_phone_number(from_=self.twilio_number,
                                                      to=self.receiving_number,
                                                      body=self.body,
                                                      media_url=media_urls)
            return message
        else:
            raise MotionAlertError("Could not send image to "
                                   "{0}.".format(self.receiving_number))

        # Confirm to user we are complete sending the alert.
        if message:
            logging.info("Alert sent to {0}.".format(self.receiving_number))
        else:
            logging.error("An unknown error occured sending to "
                          "{0}.".format(self.receiving_number))

    def get_latest_image_from_directory(self, motion_target_dir):
        """Retrieves the most recently created .jpg file from target directory.

        Arguments:
            motion_target_dir: The directory in which Motion stores its images.

        Returns:
            String with path to most recently created image.
        """
        try:
            # Use a glob generator to find the newest image
            return max(glob.iglob('{0}/*.jpg'.format(motion_target_dir)),
                       key=os.path.getctime)
        except ValueError as e:
            # Raise an error if we did not find any images
            raise MotionAlertError("Could not find any images in motion "
                                   "target directory: "
                                   "{0}".format(motion_target_dir))
        except OSError as e:
            # Raise an error if we cannot access the directory.
            raise MotionAlertError("Could not find the motion target dir: "
                                   "{0}".format(e))

    def upload_image_to_s3(self, image_file_path, bucket_name):
        """Uploads images to Amazon's S3 service.

        Arguments:
            image_file_path: Path to image to upload on local machine.
            bucket_name: Name of the S3 bucket where image should be uploaded.
            key_name: Name of the key for the file on S3 (usually the
                      timestamp).
        """
        try:
            # Attempt to get the S3 bucket with our S3 connection.
            bucket = self.s3_connection.get_bucket(bucket_name)
        except Exception as e:
            # Error out if we're unable to locate the S3 bucket.
            raise MotionAlertError("Error connecting to S3 bucket: "
                                   "{0}".format(e))

        try:
            # Create a new key using image_file_path as the key
            key = Key(bucket)
            key.key = image_file_path 
            key.set_contents_from_filename(image_file_path)
            return key
        except Exception as e:
            # Error out if we're unable to upload the image.
            raise MotionAlertError("Error uploading file to S3: {0}".format(e))

    def send_alert_to_phone_number(self, from_=None, to=None, body=None,
                                   media_url=None):
        """Sends a MMS using Twilio.

        Keyword Arguments:
            from_: The Twilio number from which the alert will be sent.
            to: The phone number that will receive the alert.
            body: Text for the alert.
            media_url: The fully qualified path to the image for the alert
                       available on the Internet.
        """
        try:
            # Send the alert using the Twilio Messages resource.
            self.twilio_client.messages.create(from_=from_, to=to,
                                               body=body, media_url=media_url)
        except TwilioException as e:
            # Error out if the request fails.
            raise MotionAlertError("Error sending MMS with Twilio: "
                                   "{0}".format(e))

class MotionAlertError(Exception):
    def __init__(self, message):
        """
        An Exception that handles output of errors to the user.

        Arguments:
            message: The message you want to display to the user for the
            exception.
        """
        logging.error("ERROR: {0}".format(message))
        logging.error("Try running with --help for more information.")

# Create a command line interface for our class.
parser = argparse.ArgumentParser(description="Motion Alert - send MMS alerts "
                                             "from Motion events.",
                                 epilog="Powered by Twilio!")

parser.add_argument("-S", "--account_sid", default=None, required=True,
                    help="Use a specific Twilio Account Sid.")
parser.add_argument("-K", "--auth_token", default=None, required=True,
                    help="Use a specific Twilio Auth Token.")
parser.add_argument("-#", "--twilio_number", default=None, required=True,
                    help="Use a specific Twilio phone number "
                         "(e.g. +15556667777).")
parser.add_argument("-s", "--aws_access_key_id", default=None, required=True,
                    help="Use a specific Amazon Web Services Access Key Id.")
parser.add_argument("-k", "--aws_secret_key", default=None, required=True,
                    help="Use a specific Amazon Web Services Secret Key.")
parser.add_argument("-b", "--s3_bucket", default=None, required=True,
                    help="Use a specific Amazon Web Services S3 Bucket.")
parser.add_argument("-t", "--receiving_number", default=None, required=True,
                    help="Number to receive the alerts.")
parser.add_argument("-T", "--timestamp", default=None, required=True,
                    help="Timestamp of event passed from Motion.")
parser.add_argument("-B", "--body", default=None, required=True,
                    help="Body of message you wish to send.")
parser.add_argument("-d", "--motion_target_dir", default=None, required=True,
                    help="Directory where Motion is storing images from "
                         "motion capture.")
parser.add_argument("-i", "--num_of_images", default=None, required=True,
                    help="Number of image to send in an alert.")

# Configure our logging for the CLI output.
logging.basicConfig(level=logging.INFO, format="%(message)s")

# Present that CLI to the user when the Python file is executed.
if __name__ == "__main__":
    args = parser.parse_args()
    motion_alert = MotionAlert(**vars(args))
    motion_alert.send()

 

Giving It A Try

With our S3 bucket and Motion configured as well as our Python app written, now we get to give it a go and see what happens.

Let’s do that by executing this command using the local.conf file we made towards the beginning of the tutorial.

motion -c local.conf

We should get some output indicating Motion is firing up:

(MotionAlert)rspectre@drgonzo:~/workspace/MotionAlert$ motion -c local.conf 
[0] Processing thread 0 - config file local.conf
[0] Motion 3.2.12 Started
[0] ffmpeg LIBAVCODEC_BUILD 3482112 LIBAVFORMAT_BUILD 3478528
[0] Thread 1 is from local.conf
[1] Thread 1 started
[1] cap.driver: "uvcvideo"
[1] cap.card: "UVC Camera (046d:0821)"
[1] cap.bus_info: "usb-0000:00:1a.7-4"
[1] cap.capabilities=0x84000001
[1] - VIDEO_CAPTURE
[1] - STREAMING
[1] Config palette index 8 (YU12) doesn't work.
[1] Supported palettes:
[1] 0: YUYV (YUV 4:2:2 (YUYV))
[1] 1: MJPG (MJPEG)
[1] Selected palette YUYV
[1] Test palette YUYV (1024x768)
[1] Adjusting resolution from 1024x768 to 960x720.
[1] Using palette YUYV (960x720) bytesperlines 1920 sizeimage 1382400 colorspace 00000008
[1] found control 0x00980900, "Brightness", range 0,255 
[1] 	"Brightness", default 128, current 139
[1] found control 0x00980901, "Contrast", range 0,255 
[1] 	"Contrast", default 32, current 32
[1] found control 0x00980902, "Saturation", range 0,255 
[1] 	"Saturation", default 32, current 32
[1] found control 0x00980913, "Gain", range 0,255 
[1] 	"Gain", default 64, current 64
[1] mmap information:
[1] frames=4
[1] 0 length=1382400
[1] 1 length=1382400
[1] 2 length=1382400
[1] 3 length=1382400
[1] Using V4L2
[1] Resizing pre_capture buffer to 1 items

And if some movement gets generated, we can check our phone for the result.

It seems as though an angry horse-man has intruded into my apartment.

Selection_005

But it appears the beast didn’t care for my interior decorating and departed without touching anything.

Selection_006

Wonder why that guy had such a long face.  BOOM.

Next Steps

Now that we’ve got a rudimentary motion camera sending MMS alerts, we can build on even more functionality in the future.  For example, we could:

  • Send MMS alerts to multiple phones.
  • Spin up and spin down the camera based on an SMS command.
  • Convert recorded video into a single animated GIF instead of still frame pictures.
  • Alert only when there is movement in certain sections of the frame to reduce false positives.
  • Install this rig with a low-power Linux device like a Raspberry Pi.

Playing around with hardware like cameras in creative ways can unlock even more potential for Twilio MMS.  If you’re hacking your cameras in creative ways, I definitely want to hear about it – you can find me on Twitter @dn0t or via email at rob@twilio.com.

How To Build Your Own MMS Enabled Motion Activated Security Camera With Linux, Python and S3

Bookmark this post:
Ma.gnolia DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google


word of mouth marketingDay 2 of Social Media Week found us on the 82nd floor of Chicago’s Willis Tower for the 2014 and Beyond: The Future of Going Social event, where Suzanne Fanning of WOMMA (Word of Mouth Marketing Association) gave us her expert outlook on what businesses of all sizes need to know about word of mouth marketing, with some excellent tips that you can use to improve your relationship with your customers. We thought we’d share the highlights here.

Social is the Future

Remember when people said social media was for teenagers and nothing lasting would come of it? Well, they were wrong. Obviously. At this point we all know that businesses that don’t acknowledge the power of social media are destined for mediocrity. But the future gets brighter and brighter: according to a recent report by CMO Survey, one fifth of a business’s marketing budget will go toward social in the next five years. Why is this so important? Because, according to Nielson, 92% of consumers trust recommendations from friends and family over any other communication. Fanning pulled up the Edelman Trust Barometer and let us see for ourselves: consumers are more likely to trust other consumers these days. At the top of the list are friends, family, employees, etc. At the bottom? CEOs, text ads, display ads, banner ads…you get the picture. So what do smart marketers do with this information? They get social and focus on word of mouth.

Solving the Social Media Puzzle Isn’t What You Think

“Everyone is trying to solve the social media puzzle,” Fanning said. “Dividing focus between all these different platforms. But smart marketers don’t focus on platforms: they focus on people.”

And while people do spend a lot of time on social media, they spend more time off. Yes, 25 billion conversations happen on social media in a year, but what about offline, says Fanning. Try 750 billion. If you want to get people talking about you offline, then you need to take actions online to drive those conversations. There are a few things that many marketers do that Fanning insists are passé, and offers some different options:

  • Instead of disruption, focus on delightConsumers want to be delighted. Make their lives easier. Do something that helps them. It will have a deeper impact.
  • Instead of making them care about you, show you care about themGet customer obsessed.
  • Instead of focusing on high ad spend, focus that spend on WOM. Don’t let your budget cramp your creativity when it comes to getting the world talking about you.

The Essential Elements to a Successful Word of Mouth Marketing Program

Aside from focusing on people and creating experience-driven campaigns that place your customers at the center of all that you do, Fanning offers five essential elements for putting together a successful word of mouth marketing program.

  • Credible. Customers don’t trust a lot of marketing efforts these days. If you’re trying to slip them something, they’ll know it.
  • Social. Give them the tools they need to share your campaign, make it easy for these conversations to take place.
  • Repeatable. Buzz campaigns are over. Instead of focusing time and budget on a flash-in-the-pan scheme that will garner a lot of attention for one stunt, instead aim for something with long-term impact that you can replicate easily.
  • Measureable. Fanning emphasized measuring what matters. Not just “likes,” but engagement, brand lift, and more. Know what you want to measure and do it.
  • Respectful. While we hope that our efforts will get our businesses into people’s homes and hearts, there is such a thing as pushing too hard. Be transparent and respect privacy, etc.

Whether you’re to B2B or B2C, every business should focus on being C2C, Fanning says. Get consumers talking about your brand, and the rest comes naturally.

Were you at Fanning’s talk today? Let us know what else you learned in the comments, or subscribe to our blog and follow us on Twitter to keep up with our Social Media Week updates!

The post Social Media Week Chicago: Elements of Word of Mouth Marketing appeared first on Ifbyphone.

Bookmark this post:
Ma.gnolia DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google


September 22, 2014

Tickets to Burning Man sell out months and months before droves of people board converted school busses, load bikes onto the backs of cars and drive into the desert. When it came time to buy a ticket, Manuel Ebert missed the bus.

Days before burning man he was desperate to find a ticket. He trolled forums, Craigslist, and tried his hand at asking friends but came up empty handed. Every forum post he responded to was a moment too late. The tickets were already gone within minutes of posting. So, he made an app that crawled Burning Man forum ePlaya for ticket postings and alerted him of new tickets via Twilio SMS.

With the help of his app, Manuel made a successful trip to the desert and was in Black Rock City, “entangled in EL wire and exploding anvils 100ft into the air.” Here’s how he made it happen.

The following is a syndicated post by Manuel. Read the full blog post on Manuel’s blog here.

Inner Nerd To The Rescue

I would personally find it unethical to write a bot to get a ticket for me, but at least the process of sitting on a computer and hitting the refresh button can be automated. The battle plan is to turn the HTML mess of the ePlaya phpBB board which only barely graduated from nested tables into clean data with Kimono and then notify my whenever that data changed.

First, let’s identify what we need in our API. Here’s what a section of the forum looks like:

kimonoWe obviously need the title of the post since we’re ultimately only interested in tickets offered, not tickets needed. The date of the post might also be interesting, as are the number of replies (since we won’t care unless we’re the first). To select the date and replies, simply highlight the text by clicking and dragging your cursor over it the way you would do it in a text editor:

Opening the raw data view, we can now see the the data, the whole data, and nothing but the data:

{
  "Title": {
    "text": "Oh... my... god...",
    "href": "https://eplaya.burningman.com/viewtopic.php?f=370&t=71750"
  },
  "Date": {
    "text": "Sat Aug 30, 2014 9:16 pm",
    "href": "https://eplaya.burningman.com/viewtopic.php?f=370&t=71750"
  },
  "Replies": "0"
}

Note how KimonoLabs neatly captures the URL to the individual thread, too. We’ll use that later.

Now, we can tell Kimono to send us an email whenever that data changes. However we’re

1. not interested in getting email every time somebody posts a reply to an old thread and
2. the lowest interval for automatic polling is 15 minutes.

So, let’s write a few lines of Python to deal with the data. We’ll use the requests module to fetch the API:

import requests
URL = "https://www.kimonolabs.com/api/6zzoaezg?apikey="
response = requests.get(URL).json()
data = response['results']['collection1']

Now

data
will be a list of dictionaries like the one above. Next we need to need to find all new posts. Let’s have a closer look at the URLs in the title attribute:

https://eplaya.burningman.com/viewtopic.php?f=370&t=71750

Here,

370
is the id of the forum, and
71750
is the id of the topic. Before we run the script the first time, let’s create a file called
latest_topic.txt
and put
71750
inside. Back in Python, we load the file find find the newest topic, split every URL to find the topic id of the post, and if it’s newer than the newest topic from the last time we run the script, we remember this posts in a
new_posts list
. And while we’re on it, we also keep track of the maximum topic id we encounter so we can save it when we’re done finding new topics:

latest_topic = int(open('latest_topic.txt').read())
max_topic = latest_topic
new_posts = []
 
for post in data:
    topic = int(post['Title']['href'].split('t=')[-1])
    if topic > latest_topic:
        new_posts.append(post)
        max_topic = max(max_topic, topic)
 
with open('latest_topic.txt', 'w') as f:
    f.write(str(max_topic))

Drop Into Twilio

Great. Now let’s turn to our friends at Twilio for turning data into a concierge web notification service. Twill allows you to send text messages to any phone and takes less than 5 minutes to set up. Let’s write a short method that will take a post and send a text message to a number:

def send_message(post, number):
    URL = "https://api.twilio.com/2010-04-01/Accounts//SMS/Messages.json"
    text = "{}: '{}' ({} replies) {}".format(
        post['Date']['text'],
        post['Title']['text'],
        post['Replies'],
        post['Title']['href']
)
    params = {
        "From": "",
        "To": number,
        "Body": text
}
    requests.post(URL, data=params, auth=("", ""))

The format operation turns the post into a string such as

“Sat Aug 30, 2014 9:16 pm: ‘Oh… my… god…’ (0 replies) https://eplaya.burningman.com/viewtopic.php?f=370&t=71750″

Finally, a simple POST request to the Twilio API is enough to send this string to a number. All that’s left to do is sending a text message for every post in

new_posts
. But wait… have you heard of the term “geospatial arbitrage”? Instead of notifying only myself, let’s send this message to friends in three different timezones in the US, the UK and Japan to maximise the chance of one of us being able to reply first:

for post in new_posts:
    for number in ('+1 415 123-4567', '+44 20 1234567' '+81 3 12345678'):
        send_message(post, number)

Done. If you’re on a free Twilio trial account, make sure all of the recipients’ numbers are verified. Last thing is to make sure this script runs, like, very often. Let’s save it as

ticket_search.py
and make an entry in our Crontab by typing crontab -e in our Terminal and adding a line

* * * * * python ticket_search.py

To make this script run once per minute.

Lean back.

At 7:04 PST in the morning, three phones on three different continents gently buzzed as part of our globally orchestrated concert of APIs and data, scripts and servers. I was the first one to tap the reply link, and sure enough:

The Ticket!

Incredibly happy and exhausted, I paypal’ed the money to the seller, wrote a hand-letter postcard to say thanks, and started packing my bag for Burning Man.

You can get the full script to build your own Burning Man Ticket Notifier here here

Leading image via cultriot.com

Building a Burning Man Ticket Notifier with Twilio SMS

Bookmark this post:
Ma.gnolia DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google


social media week chicago
As many of you know, today marked Day 1 of Social Media Week, the worldwide event with a presence in 24+ cities internationally, uniting to provide ideas and inspiration to make the most of our hyper-connected world. To kick off Social Media Week Chicago, we chose an event that we thought spoke to our hearts at Ifbyphone: Building the City of the Future, with Mayor Rahm Emanel and 1871 CEO Howard Tullman.

The way these two power players see it, the city of Chicago and the local tech industries are joining forces to attract entrepreneurs and creative minds to the Windy City. Mayor Emanuel is the first to point out how far we’ve come, pointing to PayPal’s decision in the late 90’s to leave Chicago for the West Coast because they couldn’t get the funding or find the talent here in the Midwest. Now, the mayor says proudly, we see how PayPal has bought Braintree…and has chosen to keep the headquarters here in Chicago, providing a solid tech presence and a nice chunk of jobs to our burgeoning tech community.

Tullman followed up with another bit of encouragement. “You need three things to build a tech city,” he says. “Money—and money doesn’t always have to lead; often, it follows—talent, and customers. Chicago has all three.”

It’s that talent that Mayor Emanuel chooses to really highlight, citing a Midwest work ethic that keeps Chicago head and shoulders above the competition in cities like San Francisco and New York. “We’ve got talent and we’ve got loyalty. The work ethic in Chicago is gold standard. Plus our cost of living is significantly less than the coasts.”

“It’s a great place to start your career and raise your family,” Tullman adds.

So how do Tullman and Mayor Emanuel work together to ensure that they’re doing everything they can to create a city that attracts the talent and resources necessary to build a city of the future?

Hosting the first ever Venture Capital Summit, for starters. Mayor Emanuel aims for this new initiative to double the size of Chicago’s tech sector, adding 40,000 new jobs over the next 10 years. He dreams of creating a platform where people starting businesses of all kinds can get the resources and funding they need to start building. “No one industry has more than 13% of Chicago’s market. Our diversity is our strength.”

He also seeks to tackle immigration reform, pointing out that huge numbers of the small businesses that fuel our economy are started by immigrants. “You can’t be pro-small business and anti-immigration,” he says firmly. “Immigration is essential to small business success. Look at University of Illinois,” he says, citing the ever-increasing number of students coming from China to attend that institution and learn technology skills. “I see those numbers, and I look at that as a win.”

It’s clear that Mayor Emanuel and Mr. Tullman have a vision for Chicago’s future. As Tullman said, this city has the money, the talent, and the customers needed to create a strong tech city. We’d add a fourth thing to the list: fire. And by the looks of these two gentlemen, we have that too.

We can’t wait to attend more events for Social Media Week 2014, so stay tuned for another blog, or follow us on Twitter!

The post Social Media Week Chicago: Building a Tech City with Rahm Emanuel appeared first on Ifbyphone.

Bookmark this post:
Ma.gnolia DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google


MemeSpeak has launched a cool new social networking tool that allows users to create and substitute talking head animations for textual blogging, in many languages, on any social network or blog. The Web application supports multiple language text inputs and natural language audio outputs in English, French, Spanish, German, Portuguese, Mandarin, Cantonese, Hindi, Vietnamese, Russian, […]

Bookmark this post:
Ma.gnolia DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google


September 19, 2014

marketing check-upEveryone knows how it can be: your body feels smooth and there aren’t necessarily any major pains that raise a red flag, but sometimes when you step off the curb you feel a twinge in your ankle, or you wake up with a headache. It’s nothing to call an ambulance over, but it’s troubling nonetheless. The same thing happens with your marketing. There are little pains that you notice, but you don’t necessarily want to strip it down for major surgery. Sometimes, though, ignoring little pains can mean big trouble down the road. Here are five symptoms that mean your marketing needs a check-up.

You Don’t Really Know How Sales Calls Are Handled

After the marketing team spends its time, energy, and budget generating leads, you hope that once those leads get passed to sales, they’re being handled perfectly and converted into opportunities and revenue. But we all know this isn’t always the case. The trouble is when you’re not really sure how the sales team is handling the leads. Marketing and sales alignment is an issue that can be solved in many ways, but you can start by implementing tools that will help sales handle leads better, enabling them to listen and learn in order to improve their closing.

Your Analytics Don’t Show the Source of Calls

You’re tracking spend for everything else, so it may be easy to overlook phone calls in light of everything else. But if your analytics are missing the source of phone calls, then that’s a sure sign that you need the Marketing Doctor. If you don’t know whether it was paid search, a banner ad, social media, or a trade show that drove the phone lead, then you don’t have an accurate understanding of which of your marketing efforts are actually effective.

You Have a Feeling You’re Not Getting Your Credit

When it comes time to ask for more budget for your department, you have to be able to demonstrate the impact your efforts are having on the company’s goals. Are you struggling to prove your influence? If you’re not able to track the source of inbound leads, including calls, and how those leads translate to revenue, it’s easy for sales to mark their source as any old thing, and erase the hand you had in generating those leads and accounts.

Your Company Doesn’t Have a Way of Responding to Web Leads Efficiently

You may not have a problem generating web leads, but if those leads are going cold before anyone ever reaches out to them, then it’s not only a sales problem but a marketing problem. Something as easy as a click-to-call in your marketing efforts or a phone number on your website could direct hot leads straight to the rep as opposed to languishing in a web form graveyard. There’s also the option of using lead response tools, which trigger phone calls to connect you with web leads instantly. Not a bad idea if you’re worried about leads going cold—which you should be.

You Don’t Put Phone Numbers on Your Ads or Website

We mentioned this above, and we’ll expand here. This is a sure-fire symptom that your marketing might need a dose of medicine. Your job is to make it as easy as possible for leads to reach you if they are ready to move forward with the sales process, and when you neglect to put a phone number on your website or marketing initiatives—even marketing emails—you are making it that much harder for prospects who want to call to become customers. You should be encouraging them to reach you no matter what the means.

Want to learn more about ways to fix the little aches and pains that your marketing and sales teams experience? Download our free white paper, The Definitive Guide to Voice-Based Marketing Automation.

The post 5 Symptoms That Mean Your Marketing Needs a Check-Up appeared first on Ifbyphone.

Bookmark this post:
Ma.gnolia DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google


September 18, 2014

600_343499832Yesterday we attended Silverpop’s Digital Marketing University, where we returned to the college experience for a day and learned everything our Silverpop professors could teach us about marketing in the digital space in an increasingly customer-driven world. Here are four highlights from the syllabus for those of you who couldn’t join us in class.

Marketing Should Own the Customer Experience

Bryan Brown of Silverpop started his talk by asking the audience who they thought “owned” customer experience at their company. Calls of “sales!” and “support!” were the response, but Brown countered with, “But who creates the idea of customer experience to begin with? Marketing.” It’s a fair point: marketing messaging is what creates customers’ expectations of what their experience will be upon becoming a customer, and it’s usually marketing that sends out customer communications, on housekeeping as well as new products, etc. It’s marketing, Brown declared, that should own customer experience, and ensure that every touch point—from sales to troubleshooting—is aligned with the messaging they construct in their campaigns.

Think Like the Buyer

And that means getting personal. Why are our smartphones so important to us, Brown asked? Though replaceable, why would losing your phone be such a disaster? “Because it’s yours,” Brown insisted, not just in terms of ownership but in terms of your personal customization of that device. From your sound settings to your photos to your apps to the ordered arrangement of those apps, your phone is yours, comprised of your daily life. “This is how marketing should be,” said Brown. “Personal and targeted to customers’ individual behaviors and preferences.”

When Brown said “get personal,” he meant diving deeper into your marketing campaigns and thinking of your customers as more than one amalgamated blob. They have different preferences and interests, so for starters, try getting personal with your email marketing. Brown called many email marketing campaigns “hope strategies”: we send emails to 100% of our lists hoping that 3% will take an action. But what about the other 97%? Hoping for an action from the 3% risks alienating the 97%. Segment your segments: think like your buyer.

Stop Marketing Blind

Big Data is great and all, but more important than Big Data is Right Data. The abovementioned example of marketing being like our customized, personalized smartphone is possible when we have the right data. Marketing automation platforms for online and offline strategies—including voice—can harvest a lot of the data we need to make better marketing decisions. The sooner you start looking at the right data, the sooner you can stop marketing blind, and the sooner your marketing sees your customers clearly, the better their experience with your business will be.

Stay Away from Siloed Technology

Siloed technology contributes to marketing blindness in many cases. Businesses may have the right data, but when that data is stored in different technology siloes, the lack of integration makes said data much less effective. The right integrations can mean all the difference in the world for your data, working together to provide actionable insight. This almost always means a better experience for your customer: there are fewer missed details and when everyone at your business is on the same page, it makes for seamless customer service.

There is always more to learn when it comes to digital marketing, but yesterday was a great refresher on how we can use the digital space to create an incredible customer experience. With the right technology, the right data, and the right outlook, we can ensure that our customers feel unique—because that’s how we’ll market to them.

The post 4 Tips from Silverpop on Creating an Incredible Customer Experience appeared first on Ifbyphone.

Bookmark this post:
Ma.gnolia DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google


All of us at Twilio are over the moon by the possibilities now unlocked by the availability of MMS on US phone numbers.  We know from experience that the real ingenuity will come from you – the air around Twilio is electric with anticipation of the amazing things you’ll build.  We’ve got a lot of hacks we’re excited to show you in the weeks that follow along with the best work we find from all of you.

Have a sick MMS hack?  Send it my way – rob@twilio.com.  Want to get started? Check out this guide by Kevin Whinnery. We can’t wait to see what you build.

To kick off our autumn of MMS hacking, I wanted to share the first thing I did with Twilio MMS.  A couple years ago, my buddy Aidan Feldman released one of the most critical photo services the Internet has yet seen: Mustachify.me.  A truly democratizing technology, Aidan’s killer website makes the august, sophisticated countenance of a long, curly mustache available to everyone.

His magical code can turn this:

Into this:

From the second I got my hands on Twilio MMS, I knew I had to extend Aidan’s service to every phone in the United States and Canada.

Try it now by sending a selfie here:

  • US – (646) 846-8238

  • Canada – (438) 793-8863

Now let’s build our own together.

What You’ll Need

If you want to cut to the chase and have your own working mustache machine, go ahead and deploy the Mustached Message Service to Heroku immediately:

Deploy

If you’d like to build the service yourself, we can get those glorious mustaches messaging with a few ingredients:

  • Your Twilio account – signup for free here.
  • A Twilio phone number enabled for MMS (available in Canada and the United States only for now)
  • Python
  • Flask, a web microframework for Python.
  • A web host accessible on the Internet or a localhost tunneling service like the excellent ngrok.

Getting Started

Awww snap gang – time to bust some hot Pythonic stash action. First, we’ll kick out a little boilerplate to get our Flask app ready to accept some Twilio requests. If you are using pip, you can satisfy these dependencies with a requirements.txt file.

Flask==0.10.1
twilio==3.6.7

Or directly by running this command:

pip install twilio flask

Now let’s cut a little boilerplate to respond with a simple text message.

# Import Flask microframework
from flask import Flask
# Import Twilio Python module
from twilio import twiml

app = Flask(__name__)

# Define the endpoint we'll use for the project. 
@app.route('/sms', methods=['POST'])
def sms():
    # Use the Twilio Python module to craft our response to inbound MMS.
    response = twiml.Response()

    # For now, send a text message back.
    response.message("Boiler plate, snacky!")

    # Casting the object as a string will format our response into TwiML 
    # that Twilio can read and parse.
    return str(response)

if __name__ == "__main__":
    # Since this is a development project, we will keep debug on to make our
    # lives easier. We would want to configure our app more conservatively
    # in production.
    app.debug = True
    app.run()

Configuring Your Twilio Number

Now we’ll take the basic endpoint we created and point a Twilio phone number to it. First, we need to go to our Twilio account and purchase a MMS-enabled number. (Note: MMS enabled phone numbers are only available for numbers in the United States and Canada)

Selection_001

Next we’ll set up that number with the publicly accessible address of the application we created above. Like we specified in our app’s only route, we’ll point to /sms for our domain.

Awesome – now after we click save, we should be able to send a message to the number and get a response from our boilerplate app.

Echoing Back MMS Messages

Next, let’s adjust our app to echo back to the user the messages he/she sends to our Twilio MMS-enabled number. We can leverage the <Media> noun and Flask’s request object to send the photo our app receives back to the user as a visual echo statement.

from flask import Flask
# Import the request object from Flask.
from flask import request

from twilio import twiml

app = Flask(__name__)

# Define the endpoint we'll use for the project. 
@app.route('/sms', methods=['POST'])
def sms():
    response = twiml.Response()

    # Check if we have media in the message.
    if request.form['NumMedia'] != '0':
        # If we do, echo back the media to the user.
        with response.message() as message:
            message.body = "I received this image."
            message.media(request.form['MediaUrl0'])
    else:
        # If we do not, indicate such to user.
        response.message("Could not find an image in your message.")

    return str(response)

if __name__ == "__main__":
    # Since this is a development project, we will keep debug on to make our
    # lives easier. We would want to configure our app more conservatively
    # in production.
    app.debug = True
    app.run()

Rad – now that we can receive an image and then send it back to the user.

Stashing The Faces

Now we can use Aidan’s mustachify.me service to apply upon every face it can fine with a killer curly cookie duster. Fortunately, mustachify’s interface is a simple URL param with the MediaUrl we receive from Twilio.

from flask import Flask
from flask import request

from twilio import twiml

app = Flask(__name__)

# Define the URL for the service mustaching our photos.
MUSTACHIFY_URL = "http://mustachify.me/?src="

@app.route('/sms', methods=['POST'])
def sms():
    response = twiml.Response()

    if request.form['NumMedia'] != '0':
        with response.message() as message:
            message.body = "STASHED."
            # Give mustachify.me our MediaUrl
            message.media("{0}{1}".format(MUSTACHIFY_URL,
                                          request.form['MediaUrl0']))
    else:
        response.message("Could not find an image in your message.")

    return str(response)

if __name__ == "__main__":
    # Since this is a development project, we will keep debug on to make our
    # lives easier. We would want to configure our app more conservatively
    # in production.
    app.debug = True
    app.run()

Now if we give it a try, every photo gets some distinguished upperlipholstery.

Check out what the Twilio Devangel crew did with this already:

Next Steps

If you’d like to see a more fully fleshed version of this application, be sure to check out the Github Repo here. You can also find the code for Aidan’s mean mustaching machine here.

While mustaches make everything more fun, this is just the entertaining tip of the iceberg of what is possible with receiving and sending Twilio MMS.  Here are just a few of the MMS-powered image manipulation use cases we’ve kicked around:

  • Funhouse mirror photobooths
  • Using optical character recognition to translate signs into different languages
  • Chromakey / alpha channel replacement transporting photo subjects to different places
  • Apply Instagram style vintage filters

We know from experience that no matter how imaginative we get with the services we create, those ideas serve as a mere horizon of the world of wonder you – the Twilio developer – have built time and time again.  We can’t wait to see it – reach out to me at @dn0t on Twitter or via email at rob@twilio.com with your MMS hacks!

How To Build A Mustached Message Service With Twilio MMS And Python

Bookmark this post:
Ma.gnolia DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google


.obi-nav{position:relative;color:#cdcdcd;background-color:#231f20;height:30px;font-size:16px;box-shadow:0 3px 3px rgba(205,205,205,.8);overflow:hidden;font-family:"Whitney SSm A","Whitney SSm B","Helvetica Neue",Helvetica,Arial,sans-serif;-webkit-font-smoothing:subpixel-antialiased;z-index:10}.obi-hidden{display:none}.obi-chooser,.obi-toc{background-color:#231f20;color:#cdcdcd!important}.obi-toc{position:absolute;top:3px;left:0;cursor:pointer;margin-top:3px;padding:0 10px}.obi-toc-contents *{font-size:14px;color:#cdcdcd!important}.obi-toc-contents a{text-decoration:none}.obi-toc-contents p:hover{text-decoration:underline;color:#eee!important}.obi-subnav a{font-size:12px;padding-left:10px}.obi-chooser{position:absolute;top:0;right:0;text-align:right;border-left:2px solid}.obi-chooser-option{cursor:pointer;padding:6px 10px}.obi-chooser-option:hover,.obi-toc :hover{color:#ddd!important}.obi-chooser-option:not(:first-child){font-size:14px}.obi-chooser-option:not(:first-child):hover{color:#eee}.obi-chooser-option:first-child::after{content:"\25BC";font-size:10px;padding:5px 0} .entry-content h2 {padding:10px 0;} .entry-content h3 {font-weight:bold !important;} .obi-toc-contents p{padding:0 !important; margin-top:10px;} -webkit-font-smoothing: subpixel-antialiased;

For the last century, humanity has maintained that “a picture is worth a thousand words”. While photos may have changed a lot, morphing from paper to pixels, that old adage is truer than ever in the digital age. Whether happy or heartbreaking, the millions of pictures we take every day help us tell our stories like no other medium can.

The team at Twilio has been working very hard to bring the power of pictures to our messaging platform. And today, were are thrilled to announce that Picture Messaging has arrived for all US and Canadian numbers, giving you the power to speak a thousand words in a single message.

With this new messaging capability, your apps can send concert tickets directly to a user’s mobile phone, accept photos to accompany an insurance claim, or just share that incredible animated GIF you saw on Tumblr with your friends. Words are inadequate to describe our excitement to see how you, our wickedly clever developer community, will put this new capability to use.

To help you get started using your new super power, we’ll explore the basic usage of Twilio MMS in a variety of programming languages and web frameworks. Using the chooser below, select the programming language and framework combination that looks most interesting to you. We’ll show you how to get started using that set of tools to send and receive picture messages.

Sound good? Then pick a language below and let’s get started! ↘

Setting Up
Node.js | Express
Python | Flask
C# | .NET MVC
PHP
Java | Servlets
Ruby | Sinatra

Setting Up

Before we can start sending and receiving MMS messages, we have a little bit of work to do. We need to sign up for a Twilio account for starters, and then obtain an MMS-enabled phone number to use with our application. Let’s get that taken care of so we can move on to the code.

Sign up for a Twilio account

If you don’t already have one, sign up for a Twilio account now. During the signup process, you’ll be prompted to search for and buy a number. You can go ahead and just take the default number for now.

After you take the default number, you might want to play around with it and send yourself a few text messages, maybe receive a phone call. Once you’re ready to get to the MMS action, click the button to go to your account.

Buy an MMS-enabled phone number

On your account dashboard, you’ll see your account SID and auth token near the top of the screen. These are like your username and password for the Twilio API – you’ll need these values later on to make authenticated requests to the Twilio API.

But for now, we need to either buy or use an existing phone number that can send MMS messages. Click on “Numbers” in the top nav. In your list of phone numbers, there are icons indicating the capabilities of each number. If you already have a number with MMS enabled, then you’re all set!

If you still need a number with MMS, click the “Buy Number” button. In the resulting dialogue, search for a number that has MMS capabilities.

In the resulting list, choose the option to buy one of these MMS-enabled phone numbers. Great! Now that we have an MMS-capable number, we’re ready to write code that sends and receives MMS messages. We’ll start sending our first pictures by using a high level helper library that makes it easier to work with the Twilio API.

Set up our project

Before we begin, you will need to have both Node.js and npm installed. If you haven’t already, you can download a Node.js installer for your platform here, which should also include npm.

In a terminal window, create a new folder called “demo”. This will be the home of our Node.js application. Next, install the Twilio module and our other dependencies from npm.

npm install twilio express body-parser

Now, let’s create the files and directory structures we’ll need to start developing our application.

touch app.js
mkdir views
touch views/index.jade

For this simple application, we’ll just need those two files – “app.js” and “views/index.jade”. We’re using the popular Express web framework for node, along with some supporting modules. Those supporting modules are Jade (a template engine for rendering HTML) and body-parser, which we use to process incoming POST parameters to our web app. And we’ve also installed the Twilio module for node.js, which will help us in doing the Twilio bits of our application.

Before we begin, you will need to have both Python and pip installed. If you haven’t already you can install a Python installer for your platform here. In addition, you will want to install pip to manage your packages.

In a terminal window, create a new folder called “demo.” This will be the home of our Python application. Next, install the Twilio module and Flask with a pip install command.

pip install twilio flask

Finally, to complete setup, let’s create a new file called app.py in our “demo” directory. This is where our web application code will live in just a little while.

To demostrate how to use the messaging APIs, we’ll write a simple servlet application (and one plain old Java class) that will send and receive messages. We’ll assume that you already have Java installed on your system. For this particular tutorial, we will be creating a Dynamic Web Project in Eclipse – you can download the version of Eclipse we’re using from here. We will also be deploying to Apache Tomcat – if you don’t have Tomcat on your system, you can download it from here.

Once you download and launch Eclipse, create a new “Dynamic Web Project”. Call the project “MmsDemo” – take note of this name, as it also functions as your servlet app’s context root.

You may also need to configure a runtime for this application – that’s why we downloaded Tomcat. During project creation, if you have none available, click “New Runtime”. Here, you can configure the Tomcat version you downloaded, and tell Eclipse where you extracted it.

Next, you’ll need to download and install the Twilio helper library for Java. There’s lots of ways to get it, including through the Maven repository, but for this example let’s go ahead and download the jar directly. As of this writing, our helper library is at version 3.4.x – make sure to download the version with all dependencies bundled.

Once you download the jar, you can drag and drop or copy/paste it into our app’s WEB-INF/lib directory, so it will be available on the Java class path.

Before we begin, we assume you have Ruby and Ruby Gems installed. If you’re on a Mac, these should be installed already – if you’re on Windows, you might consider this installer. If you’re on Linux, you probably know what you’re doing ;) – but here’s a solid guide to getting started through apt-get on Ubuntu.

In a terminal window, create a new folder called “demo”. Change into this directory – we’ll put all our application code here. Next, let’s install the Twilio and Sinatra Ruby gems:

[sudo] gem install twilio-ruby sinatra

Next, let’s create the files and directory structures we will need:

touch app.rb
mkdir views
touch views/index.erb

For this application, we will be using the lightweight Ruby web framework Sinatra. Along with Ruby’s ERB templating engine, it should provide all the functionality we need for this application. We’ll use the Twilio Ruby gem to make interacting with the Twilio APIs a bit easier – we’ll see how as the tutorial goes on.

Before we begin, we assume that you have a server installed running PHP. If you’re on a Mac, you might consider MAMP. If you’re on Windows, you might consider XAMPP. If you’re on Linux, you probably know what you’re doing ;) – but here’s a solid guide to getting started on Ubuntu.

In a terminal window, navigate to your document root folder and create a new folder called “demo” – we’ll put all our application code here. Change into your new “demo” directory. Now, let’s install the Twilio PHP library. If you’re a fan of composer you can install “twilio/sdk” but in this case we’ll install it manually.

wget https://github.com/twilio/twilio-php/zipball/master
unzip master

For this application, we will be using pure PHP without a framework. The only external dependency we’ll use is the Twilio PHP library, which makes interacting with the Twilio APIs a bit easier. You’ll see how to make use of it later on.

To demonstrate how to use the messaging APIs, we’ll write an ASP.NET MVC application that uses the Twilio helper library for .NET.

In Visual Studio, create a new “ASP.NET Web Application”. Call the project “MmsDemo”. Remember this name, as you’ll need it later when we handle incoming MMS messages.

Next, you’ll need to install the Twilio.Mvc helper library for .NET using NuGet. There are a few ways to do this and both of them are covered in our installation guide.

Now that our project is all set up, let’s send an MMS message through our Twilio account!

Sending MMS Messages with the REST API

To send an MMS message, we’ll need to make an authenticated request to the Twilio REST API. You can do this in any programming language or environment that speaks HTTP, but in this example we’ll be using a special language-specific helper library that makes this very easy.

If you’ve used Twilio before to send text messages, you probably know that in the POST parameters you send to Twilio, you include a “Body” parameter that contains the text for the message. With MMS, you can include a text body as well if you want to. The new parameter for MMS is “MediaUrl” – this must be a fully qualified URL to an image that is accessible on the public Internet, and is under 5 MB in size.

There are a few requirements about the type of image you’re trying to send also – you can check those out here in the docs. If your image is something Twilio can handle, we’ll send it along as an MMS message to the phone number of your choosing. Let’s use a Twilio REST client to send our first MMS message!

For this example, we’re going to create a web form where a user can enter a destination number and send an MMS. In your application folder, open “views/index.jade” in your favorite text editor. We’ll use Jade to generate an HTML page with a form that will contain the values we need to send an MMS message:

doctype html
html(lang='en')
  head
    style.
      input[type="text"] {
        width: 200px;
        display: block;
        margin: 10px 0;
      }
  body
    h1 Send Yourself A Picture
    form(action='https://www.twilio.com/blog/send', method='POST')
      input(type='text', name='phone', placeholder='enter a phone number')
      input(type='text', name='url', placeholder='paste a URL to a photo')
      input(type='text', name='message', 
        placeholder='optional - include a text message')
      input(type='submit', value='Send me the picture!')

Now, open “app.js” and add in the following code – take a look through the comments to see what’s happening at each step:

// require dependencies for the application
var twilio = require('twilio');
var express = require('express');
var bodyParser = require('body-parser');

// Create a simple Express web app that will parse incoming POST bodies
var app = express();
app.use(bodyParser.urlencoded({ extended: true }));

// Create a route to render the home page
app.get('/', function(request, response) {
    response.render('index.jade');
});

// Create a route that will handle the form submission
app.post('/send', function(request, response) {
    // to send a message, we need a Twilio REST client - we create one here,
    // initializing with our Twilio account credentials. I am loading them here
    // from system environment variables, accessible through the "process.env"
    // global object in Node
    var client = new twilio.RestClient(process.env.TWILIO_ACCOUNT_SID,
        process.env.TWILIO_AUTH_TOKEN);

    // Now, get the parameters POSTed from our form:
    var toNumber = request.body.phone;
    var message = request.body.message;
    var mediaUrl = request.body.url;

    // Now let's send the message!
    client.sendMessage({
        to: toNumber,
        body: message,
        mediaUrl: mediaUrl,
        // This is the MMS-enabled number you purchased previously
        from: process.env.TWILIO_NUMBER
    }, function(err, messageData) {
        if (err) {
            response.send('Oops, there was an error :(');
            console.error(err);
        } else {
            response.send('Message sent! SID: ' + messageData.sid);
        }
    });
});

// Start the web application, and serve on local port 3000
app.listen(3000);

Now, we’re ready to run the app! In your terminal, start the application with “node app.js”. In your browser, visit localhost:3000 to see your running application.

In the form, enter in your mobile phone number, an optional message, and a URL to an image on the Internet. Google image search is definitely your friend here, but if you’re at a loss, may I suggest this animated GIF from Adventure Time?

First, let’s fire up a Python REPL to write some Python code to send a MMS.

python

Next, let’s import a class to help us interact with the Twilio API, the TwilioRestClient.

from twilio.rest import TwilioRestClient

Then we’ll define our account credentials to authenticate our client and instantiate a client to use.

from twilio.rest import TwilioRestClient
 
TWILIO_ACCOUNT_SID = 'ACxxxxxxxxxxxxxxxx'
TWILIO_AUTH_TOKEN = 'yyyyyyyyyyyyyyyyyyy'
 
client = TwilioRestClient(TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN)

Next, we’ll send our first picture:

from twilio.rest import TwilioRestClient
 
TWILIO_ACCOUNT_SID = 'ACxxxxxxxxxxxxxxxx'
TWILIO_AUTH_TOKEN = 'yyyyyyyyyyyyyyyyyyy'
TWILIO_NUMBER = '+1555667777'
MY_NUMBER = '+15558889999'
 
client = TwilioRestClient(TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN)
 
client.messages.create(from_=TWILIO_NUMBER, to=MY_NUMBER,
        media_url="https://www.twilio.com/packages/company/img/logos_downloadable_round.png")

You can send almost any image you want with your message – in the code above we sent the Twilio logo, but you can also send animated GIFs like the one below.

In your Eclipse project, create a new class – anywhere within the Java Resources’ “src” folder is fine. Call the new class “SendMessage”. Now, open up SendMessage.java and add the following code – check the comments at each step to see what’s going on:

import com.twilio.sdk.TwilioRestClient;
import com.twilio.sdk.TwilioRestException;
import com.twilio.sdk.resource.factory.MessageFactory;
import com.twilio.sdk.resource.instance.Message;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
 
import java.util.ArrayList;
import java.util.List;
 
public class SendMessage {
 
	// Find your Account Sid and Token at twilio.com/user/account - it is unwise to
	// store these values in source code, however. You should store them in
	// environment variables or other secure configuration 
	public static final String ACCOUNT_SID = "ACXXX";
	public static final String AUTH_TOKEN = "xxxxx";
 
	// Here, we create a simple main method that sends an MMS message
	public static void main(String[] args) throws TwilioRestException {
		// Create an authenticated REST client
		TwilioRestClient client = new TwilioRestClient(ACCOUNT_SID, AUTH_TOKEN);
 
		// Create a list of parameters to send along with the request to Twilio
		List<NameValuePair> params = new ArrayList<NameValuePair>();
		
		// This is the text body of the message (optional)
		params.add(new BasicNameValuePair("Body", "Trust Pound!"));
		
		// This is the number to send the message to - your phone number would work great
		params.add(new BasicNameValuePair("To", "+16512080532"));
		
		// This is your MMS-enabled Twilio number
		params.add(new BasicNameValuePair("From", "+16518004844"));
		
		// Also, we provide a full URL to an image that is accessible on the Internet
		params.add(new BasicNameValuePair("MediaUrl", "http://i.imgur.com/Act0Q.gif"));
 
		// Now, let's send the message!
		MessageFactory messageFactory = client.getAccount().getMessageFactory();
		Message message = messageFactory.create(params);
		System.out.println(message.getSid());
	}
}

The code above should be good to send yourself an MMS message! To run it, select the SendMessage.java file in the file explorer, right click it, and choose “Run as… Java Application”. You can use any image URL you like for the example, but if you’re at a loss, may I suggest this animated GIF from Adventure Time?

For this example, we’re going to create a web form where a user can enter a number and send an MMS. In your application folder, open “views/index.erb” with your favorite text editor. We’ll be using Ruby’s ERB template engine to generate a simple HTML page with a form that will contain the values we need to send an MMS message:

<!doctype html>
<html lang="en">
<head>
    <style>
    input[type="text"] {
        width: 200px;
        display: block;
        margin: 10px 0;
    }
    </style>
</head>
<body>
    <h1>Send Yourself A Picture</h1>
    <form action="https://www.twilio.com/blog/send" method="POST">
        <input type="text" name="phone" placeholder="enter a phone number"/>
        <input type="text" name="url" placeholder="paste a URL to a photo"/>
        <input type="text" name="message" placeholder="optional - include a text message"/>
        <input type="submit" value="Send me the picture!"/>
    </form>
</body>
</html>

Now, open app.rb and add the following code – take a look through the comments to see what’s happening at each step:

# require app dependencies
require 'rubygems'
require 'sinatra'
require 'twilio-ruby'
 
# create a route to render the home page
get '/' do
  erb :index
end
 
# create a route to handle the POST request to the form
post '/send' do
  # create an authenticated Twilio REST client with our Twilio Account SID
  # and auth token - these are like our username and password for the Twilio
  # API. We load these values as system environment variables, but for
  # testing you can replace ENV['xxxxx'] with a string containing your actual
  # credentials. Make sure not to commit them to version control, though!
  client = Twilio::REST::Client.new ENV['TWILIO_ACCOUNT_SID'], 
    ENV['TWILIO_AUTH_TOKEN']
 
  # Get POST parameters submitted by the user through the form
  to_number = params[:phone]
  media_url = params[:url]
  message_text = params[:message]
 
  # Send a message!
  message = client.account.messages.create(
    :to => to_number,
    :body => message_text,
    :media_url => media_url,
 
    # This is the MMS enabled number you purchased previously - replace
    # the environment variable with a string like "+16518675309"
    :from => ENV['TWILIO_NUMBER']
  )
 
  # Send back a simple text response that the message was sent
  "Message sent! SID: #{message.sid}"
end

Now, we’re ready to run the app! In your terminal, start the application with “ruby app.rb”. In your browser, visit localhost:4567 to see your running application.

In the form, enter in your mobile phone number, an optional message, and a URL to an image on the Internet. Google image search is definitely your friend here, but if you’re at a loss, may I suggest this animated GIF from Adventure Time?

For this example, we’re going to create a web form where a user can enter a number and send an MMS. In your application folder, create and open “index.html” with your favorite text editor. We’ll be writing a simple HTML page containing a form with all the values we need to send an MMS message:

<!doctype html>
<html lang="en">
<head>
    <style>
    input[type="text"] {
        width: 200px;
        display: block;
        margin: 10px 0;
    } 
    </style>
</head> 
<body>
    <h1>Send Yourself A Picture</h1>
    <form action="send.php" method="POST">
        <input type="text" name="phone" placeholder="enter a phone number"/>
        <input type="text" name="url" placeholder="paste a URL to a photo"/>
        <input type="text" name="message" placeholder="optional - include a text message"/>
        <input type="submit" value="Send me the picture!"/>
    </form>
</body>
</html>

Now, create and open “send.php” and add the following code – take a look through the comments to see what’s happening at each step:

<?php
 
  require_once('twilio-php/Services/Twilio.php'); // Loads the library
 
  // Create an authenticated Twliio REST client with our Twilio Account SID
  // and auth token - these are like our username and password for the Twilio
  // API. We load these values as system environment variables, but for
  // testing you can replace $_SERVER['xxxxx'] with a string containing your actual
  // crendials. Make sure not to commit them to version control, though!
  $sid = $_SERVER['TWILIO_ACCOUNT_SID'];  
  $token = $_SERVER['TWILIO_AUTH_TOKEN']; 
  $client = new Services_Twilio($sid, $token);
      
  // Get POST parameters submitted by the user through the form
  $to_number = $_POST['phone'];
  $media_url = $_POST['url'];
  $message_text = $_POST['message'];
      
  // Send a message!
  $message = $client->account->messages->sendMessage(
    $_SERVER['TWILIO_NUMBER'], 
    $to_number,
    $message_text, 
    $media_url
  );
 
  // Send back a simple text resopnse that the message was sent
  echo 'Message sent! SID: ' . $message->sid;

Now you’re ready to give your app a spin. If you’re running locally using MAMP or XAMPP, visit localhost:8080/demo to see your running application.

In the form, enter in your mobile phone number, an optional message, and a URL to an image on the public Internet. Google image search is definitely your friend here, but if you’re at a loss, may I suggest this animated GIF from Adventure Time?

For this example, we’re going to create a web form where a user can enter a number and send an MMS. To do this we’ll need to create a view to present our form and a controller to handle the user’s input.

Create a new controller called “MmsController”. Open up “MmsController.cs” and add the following using statements:

using Twilio;
using Twilio.TwiML;
using Twilio.TwiML.Mvc;

Next, create a new View inside of the “Views\Mms” folder called “Index.cshtml”. Replace the contents of this file with the following code:

<style>
    input[type="text"] {
        width: 250px;
        display: block;
        margin: 10px 0;
    }
</style>
<h1>Send yourself a picture!</h1>
 
@using (Html.BeginForm("Send", "Mms", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
{
    @Html.TextBox("phone", "", new { placeholder = "enter a phone number" })
    @Html.TextBox("url", "", new { placeholder = "paste a URL to a photo" })
    @Html.TextBox("message", "", new { placeholder = "optional - include a text message" })
    <input type="submit" value="Send me the picture!" />
}

At this point we have our web form set up and ready to be displayed. The next step is to add code to our controller to handle the user’s form input. Open up “MmsController.cs” again and add the following method – take a look through the comments to see what’s going on at each step:

[HttpPost]
public ActionResult Send(string phone, string message, string url)
{
    // Create a new TwilioRestClient passing in your AccountSid and AuthToken
    var client = new TwilioRestClient("** your Twilio AccountSid **", "** your Twilio AuthToken **");
    
    // Send a message from your number to the target number, with media url and optional message...
    client.SendMessage("** your MMS-enabled Twilio phone number **", phone, message, new string[] { url });
    
    // Redirect back to the form to do it again!
    return Redirect("/");
}

Now we’re ready to run the app! Press F5 to start the application in your default browser. In the form, enter in your mobile phone number, an optional message, and a URL to an image on the public Internet. Google image search is definitely your friend here, but if you’re at a loss, may I suggest this animated GIF from Adventure Time?

come on grab your friendshttp://i.imgur.com/Act0Q.gif

In a few moments, your handset should buzz with a new message that contains your image! Let that sink in for a second – you now have the ability to programmatically send animated GIFs to your friends and colleagues via MMS (animations work on many, but not all, handsets). Please, use this power responsibly.

So now we know how to send outbound messages, but what about accepting inbound MMS messages? We can definitely do that as well. Let’s write some code to enable that in our web application.

Receiving MMS Messages in Your Application

To let developers know about inbound messages to their phone numbers, Twilio makes use of a callback pattern called webhooks. Whenever an interesting event happens within Twilio, such as an incoming call or text message, Twilio will send an HTTP request to a URL you specify with information about the event.

In the case of an incoming message or call, Twilio needs your web application to tell it how to respond. Should Twilio send a text message back? If it’s a call, should Twilio drop the caller into a conference, or maybe forward the call to another number?

The way your application tells Twilio what to do next is by responding to a webhook request with an XML document containing a set of about a dozen special tags we call TwiML. In the case of MMS, we’ll be responding with the <Message> tag. We’ll see how that works in just a bit, using an XML (TwiML) -generating utility that is available in our Twilio helper library.

When Twilio sends our app a webhook request, that request will contain (by default) POST data about the incoming call. There will be POST parameters for the number of the incoming texter, the body of their message, and other useful data. You can see all the data available in the incoming request here.

In the case of MMS, there will be a couple POST fields of particular interest to you. The first is “NumMedia” which indicates how many images were sent with the message. Then there will be one or many POST fields with the naming convention “MediaUrl[n]“, where “n” is the index of the media object you’re dealing with. For example, an incoming MMS with three images attached would have POST parameters called “MediaUrl0″, “MediaUrl1″, and “MediaUrl2″. You can use these values to work with media that are submitted to your application.

In our example, we’re going to implement a new endpoint that will respond to incoming MMS messages by replying with that animated GIF we saw earlier. The XML we are sending back will look like this:

<?xml version="1.0" encoding="UTF-8"?>
<Response>
  <Message>
    <Body>Trust pound!</Body>
    <Media>http://i.imgur.com/Act0Q.gif</Media>
  </Message>
</Response>

Let’s see what the code looks like to actually generate this TwiML in response to a POST request.

Implement a webhook route that returns TwiML

Open up “app.js” again in your text editor of choice. Now, let’s add a route that will accept a POST request from Twilio, and return XML (TwiML) as a response. Add the following code under the route definition for “/send”. Follow along with the comments to see what is happening at each step:

// Handle an incoming request from Twilio
app.post('/message', function(request, response) {
    // create a TwiML response object. This object helps us generate an XML
    // string that we will ultimately return as the result of this HTTP request
    var twiml = new twilio.TwimlResponse();
 
    // prepare the TwiML response
    twiml.message(function() {
        this.body('Trust Pound!');
        this.media('http://i.imgur.com/Act0Q.gif');
    });
 
    // Render an XML response
    response.type('text/xml');
    response.send(twiml.toString());
});

Now in the terminal, make sure to restart your Node process so that these changes take effect.

Let’s open up that app.py file in your text editor of choice. Now, we’ll create a Flask application with a route called “/message”. This route will accept a POST request from Twilio, and return XML (TwiML) as a response. Add the following code to app.py. Follow along with the comments to see what is happening at each step.

# Import the Flask microframework we installed earlier.
from flask import Flask
 
# Import the Twilio Python module we install earlier.
from twilio import twiml
 
 
# Create our application
app = Flask(__name__)
 
 
# Create our webhook to respond to Twilio MMS with Adventure Time Gifs.
@app.route('/sms', methods=['POST'])
def sms():
    response = twiml.Response()
    with response.message() as message:
        message.body = "Trust pound!"
        message.media("http://i.imgur.com/Act0Q.gif")
    return str(response)
    
if __name__ == "__main__":
    app.run()

To handle incoming HTTP requests from Twilio, we’ll now need to create a servlet. In Eclipse, right click on the Java Resources’ “src” directory. Under the “New” menu, choose “Servlet”. In the resulting dialogue, type in “MmsServlet” as the class name and click “Finish”. This should create a new file called “MmsServlet.java”. Replace the contents of this file with the following – read along in the comments to find out what’s happening precisely at each step, but we’re creating a servlet that will respond to a POST request by rendering TwiML.

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.twilio.sdk.verbs.*;

@WebServlet("/MmsServlet")
public class MmsServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	/**
	 * @see HttpServlet#HttpServlet()
	 */
	public MmsServlet() {
		super();
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		// Create a TwiML response and the message's child nodes
		TwiMLResponse twiml = new TwiMLResponse();
		Message msg = new Message();
		Body body = new Body("Trust Pound!");
		Media media = new Media("http://i.imgur.com/Act0Q.gif");

		// Assemble the TwiML response
		try {
			msg.append(body);
			msg.append(media);
			twiml.append(msg);
		} catch (TwiMLException e) {
			e.printStackTrace();
		}

		// Render the XML response
		response.setContentType("application/xml");
		response.getWriter().print(twiml.toXML());
	}

}

Now, we need to deploy our servlet to our servlet container Tomcat. In Eclipse, right click on the top-level project. Under the Run As menu, click “run on server”. This should start a local Tomcat server on port 8080. The logic we just included should now be available at localhost:8080/MmsDemo/MmsServlet if you followed the naming conventions we used in this tutorial.

Open up “app.rb” again in your text editor of choice. Now, let’s add a route that will accept a POST request from Twilio, and return XML (TwiML) as a response. Add the following code under the route definition for “/send”. Follow along with the comments to see what is happening at each step:

# create a route that will respond to an incoming POST request from Twilio
post '/message' do
  # Create a TwiML response object - this object helps us generate an XML string
  # that we will return as the result of this request
  twiml = Twilio::TwiML::Response.new do |r|
    r.Message do |m|
      m.Body 'Trust Pound!'
      m.Media 'http://i.imgur.com/Act0Q.gif'
    end
  end
 
  # set the Content-Type header of the response for XML
  content_type 'text/xml'
  twiml.text
end

Back in the terminal, make sure to restart your Ruby process so that these changes take effect.

Create and open “message.php” in your text editor of choice. Add the following code that will respond to Twilio’s incoming POST request with some XML (TwiML). Follow along with the comments to see what’s happening at each step:

<?php
 
  require_once('twilio-php/Services/Twilio.php'); // Loads the library
      
  header('Content-type: text/xml');
 
  // Create a TwiML response object - this object helps us generate an XML string
  // that we will output as the resopnse of this request
  $response = new Services_Twilio_Twiml();
  $message = $response->message();
  $message->body('Trust Pound!');
  $message->media('http://i.imgur.com/Act0Q.gif');
  print $response;

Open up “MmsController.cs” again. We’re going to add a controller method that will accept a POST request from Twilio and return XML (TwiML) as a response. Add the following method to “MmsController” under the “Send” method we added previously. Follow along with the comments to see what is happening at each step:

// Create our webhook to respond to Twilio MMS with Adventure Time Gifs.
public ActionResult message()
{
    // Create a new TwiML response that will generate TwiML to return to Twilio
    var response = new TwilioResponse();
 
    // Setup a <Message> response passing in a message and the URL to the Trust pound gif
    response.Message("Trust pound!", new string[] { "http://i.imgur.com/Act0Q.gif" }, null);
 
    return new TwiMLResult(response);
}

Get a public URL for your app with ngrok

Now that we have an endpoint that can respond to an incoming request from Twilio, we need to get it on the Internet. We could deploy it to the web host or public server of our choice, but in development, it’s usually nice to have Twilio hit the local version of your application that’s currently running. But how can we put our laptop on the Internet?

Enter one of our very favorite tools, ngrok. Ngrok forwards HTTP traffic from a public subdomain to a local port on your computer. To use ngrok, you simply download the binary executable for your system, navigate to the directory where you downloaded it in a Terminal window, and execute the command, passing in the port number you’re running your app on locally.

Using ngrok can be a bit more involved if you’re running on Windows. Check out this tutorial for in-depth information on getting ngrok going on that OS. For more guidance on using and configuring ngrok generally, you might check out this post as well.

For our application, we’re running on port 300050004567808080808888 if you’ve been following the instructions so far. In your terminal, type “./ngrok {your port}” on Mac/*nix systems or just “ngrok {your port}” on Windows. For ASP.NET MVC, you can launch ngrok from the “ngrok Configurator” described in the ngrok on Windows tutorial. This will ensure you are using the correct port. The result should be an interface like this one that contains your local port’s new public URL.

See that http:// URL in terminal output? Copy that bad boy to your clipboard – we’re going to use it to configure our Twilio MMS number to send incoming MMS messages to our application. Head back out to your account page and let’s get that configuration set.

Configure your Twilio number

Go to your account’s phone numbers and click on your MMS number. In the screen that follows, you’ll see two text fields – the Voice and Messaging URLs for this number. This is where you configure the URLs that will receive HTTP requests when your phone number gets an incoming message or call.

In the messaging URL field, paste in your ngrok URL from earlier. Append to this the route that we created for rendering a TwiML response. Your servlet route, if you used the suggested names, is probably /MmsDemo/MmsServlet rather than /message. The number configuration should look something like this:

Note that the route for the ASP.NET MVC application will be “/Mms/Message” if you followed along with the naming conventions in this tutorial.

Save your configuration changes, and then send a (text or picture) message to your Twilio number. In a moment or two, you should receive a reply with the message and image we included in our TwiML response!

Wrapping Up

In this tutorial, we’ve learned the basics of sending and receiving MMS messages with Twilio. With these basic building blocks, you can create entirely new categories of messaging applications. Send boarding passes, promote sale items, send receipts, share ultrasound images, save prom photos – you send or receive any picture that makes up the story you need to tell.

In the weeks ahead, watch the blog for more tutorials on how to put MMS to work. In the meantime, check out the official REST API docs for in-depth information on the messaging APIs. You can also have a look at the documentation for Media resources to see what you can do with user-submitted image content.

If you have any questions or run into problems, don’t hesitate to reach out at help@twilio.com. We’d also love to see what you’re up to and what you’ve built – feel free to hit us up on the Twitters if you’d like to chat. Though words may not be sufficient to tell us what you’ve made – feel free to send us a picture also.

Getting Started with Twilio MMS Messaging

Bookmark this post:
Ma.gnolia DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google


Today, we’re happy to announce newly expanded Twilio messaging capabilities. For the first time ever, you can now send and receive MMS on all US Twilio phone numbers.

We’ve eliminated months-long wait time and prohibitive costs typically associated with enabling MMS from your app by working with every carrier directly. Now with the click of a button you have three ways to communicate. You can use any Twilio number to send media, send SMS, or make a call.

MMS gives you a new way to reach out to customers efficiently and immediately, bringing you the best traits of email and SMS together. Like SMS, nearly all MMS are read by recipients within the first four minutes. Similar to email, you can say a whole lot in one message by using rich media.

We’re incredibly excited to see how you use MMS, and what the developer community will build with it. To get started hacking with MMS in your language, check out our Getting Started Guide here.

Here are a few of the things that Twilio customers are already using MMS for:

  • Mobile Marketing: Pictures and videos improve open and conversion rates, conveying details you can’t explain in just 160 characters via text message. 
  • Delivery Logistics: Rich media gives customers peace of mind when they know the face of their delivery man, taxi driver, or courier. 
  • Records and Auditing: Customers can conveniently and instantly upload in-app pictures and receive receipts on their mobile phones via MMS. 

Twilio MMS Storage and Pricing

Twilio MMS supports several different file formats, and offers 5 GB of free storage. Images that you send are automatically resized if necessary to meet carrier guidelines. Twilio Messaging features like Message Delivery Information are also available for outgoing MMS messages, allowing you to confidently determine message delivery.
Finally, each MMS costs $0.01 to receive and $0.02 to send. Head over to https://www.twilio.com/mms to learn more.

Picturing the Future of Messaging: Twilio MMS Now Available on all US Numbers

Bookmark this post:
Ma.gnolia DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google


September 17, 2014

One of the things I’m grateful for in my work so far is having the chance to write meaningful code in many different programming languages. Most recently this has been JavaScript (node/browser), Objective-C, and Ruby, but I cut my teeth as a Java/JEE developer, developed huge Adobe Flex apps in ActionScript 3, and have been asked to contribute code (for good or ill) in C#, Python, and Perl as well. Notably absent from that list is the workhorse of the Internet, the glue that holds the world wide web together – I am referring of course to PHP. But as luck would have it, I have recently had a pressing need to learn the rudiments of this venerable server-side scripting language and start to fill that gap.

As I orient myself in the PHP multiverse, I am discovering that the language seems to be entering something of a renaissance. When your only interaction with PHP is the odd WordPress hack, you don’t understand the nuance of how web developers are pushing this technology ahead. While there is still incredible diversity in how problems are solved, PHP seems to have a strong player in package management with Composer. The runtime and language continue to evolve with PHP 5.6, PHPNG, and Facebook’s HipHop VM showing there’s still healthy competition and passion around the platform.

The higher-level web frameworks of PHP are legion, and continue to evolve apace. Recently, there’s been a lot of excitement around the Laravel framework. As I learn about and explore Laravel I can understand why – it brings together a lot of the tools and frameworks that were already well-liked and battle-tested in the PHP community into a cohesive whole.

Of course, the first thing I did when I started learning Laravel was to get to the “Hello World” level with Twilio. Maybe what I learned during that process can be useful for you as well? If developing web apps with Laravel is cool, surely using Laravel and Twilio to call or text your customers is even cooler.

In this tutorial, I’ll show you how to get up and running with Twilio and Laravel using the cloud development platform Nitrous.io. We’ll show how to receive incoming calls or text messages in your Laravel app using a callback mechanism called webhooks. We’ll also use Twilio’s helper library for PHP to make authenticated requests against the REST API, which enables us to send text messages and make outbound phone calls. You’ll also leave with resources to learn more about Twilio, Laravel, and the other technologies used in this post.

Sound like a plan? Then let’s get started! We’ll begin by setting up a PHP/Laravel development environment in the cloud with Nitrous before diving into the Twilio side of things.

Setting Up Your Dev Environment with Nitrous.io

Nitrous is a cloud-based development environment that makes it easy to create and configure a development machine for a variety of popular programming languages. It also has the benefit of living on the Internet, so you can preview with a live URL that you can share with your co-workers (and Twilio, as we will see later). We’re using Nitrous here since it’s the fastest way I’ve found to go from absolute zero to a functional PHP dev environment. But if you’re cool using Homestead, MAMP, or your pre-existing PHP development environment, go right ahead and use it, and skip to the “Responding to Incoming Calls and Text Messages” section of this tutorial. Just know that Twilio will need a public URL for your server (ngrok works great to give your local machine a public URL – I wrote a little tutorial about it here).

This tutorial assumes you will (at least initially) use Nitrous’ cloud-based IDE, but you can download their Desktop app if you’d prefer to work locally with your own editor and tools. Let’s get our Nitrous box set up to hack on our Laravel app.

Provision a Nitrous box for local development

If you haven’t already, go and sign up for a Nitrous development account. Once signed up and authenticated, go to your dashboard and create a new PHP box.

You can tune the resources available to your liking, but a free account has a limited amount of resources to go around. Once your box is created, click the button that says “IDE”:

In the page that follows, you’ll be greeted with a familiar interface that resembles IDEs you might use on the desktop. There’s a file explorer view, an editor view, and a terminal window docked on the bottom of the screen. There’s already an Apache HTTP server installed and running on port 3000, set up to serve the contents of your ~/workspace/www folder. To make sure that’s all good, create a simple PHP script in that directory called “index.php” and add the following code:

<?php echo phpinfo(); ?>

In your IDE, you’ll notice a menu of options along the top edge of the screen – one of these is called “Preview”. Click this menu, and choose port 3000 (not the SSL version). This should open up a new web browser window with information about your PHP environment on screen. There’s a time and a place for “no framework” PHP, but in this tutorial we’d like to use Laravel. Let’s see how we get that set up on Nitrous.

Installing Laravel and creating a project

In order to use Laravel on our Nitrous box, we have a little more work to do. We’ll need to edit some configuration files and install a bit more software on our development box. Just below the file explorer view, there’s an option to show hidden files – make sure to click this, as we’ll need to edit some of those hidden files in just a few seconds:

But first, let’s make sure we have the latest and greatest version of Composer, the package manager for PHP. We’ll be using it to manage and install all of our dependencies, including Twilio and Laravel. In the terminal pane of the IDE, enter “composer selfupdate”:

Now, per the instructions in the Laravel docs, we’ll globally install the “laravel” command with Composer, so we can use it to manage and create new projects. In the terminal, enter “composer global require “laravel/installer=~1.1″:

This will download and install Laravel, but we still need to add the “laravel” command to our system path. To do this, we’ll have to edit “.bash_profile” in our home directory. You should see this file in your explorer on the left, if you clicked the “Show Hidden” button beneath it. In this file, replace the line that configures your system path with the following:

export PATH="$HOME/.parts/autoparts/bin:~/.composer/vendor/bin:$PATH"

In the terminal, type “source .bash_profile” – now, you should have the “laravel” command on your system path. Confirm this by typing “laravel” into the terminal with no additional arguments:

Okay, now let’s create our new Laravel app. In the terminal, “cd workspace” to change into the directory where we’ll create our application. Type “laravel new myproject” to create a new Laravel project called “myproject” in the workspace directory:

Okay, sweet – now we have a Laravel project set up on our Nitrous box. Now, we need to point our Apache HTTP server to this new Laravel project. In your file explorer, find the “httpd.conf” configuration file for Apache – it should be in “~/.parts/etc/apache2/httpd.conf”. Open this file, and locate the configuration entry for the server’s document root – change the reference to “www” (the old PHP app) to your new project’s public folder. The configuration will end up looking something like the following:

DocumentRoot "/home/action/workspace/myproject/public"
<Directory "/home/action/workspace/myproject/public">
  Options Indexes FollowSymLinks
  AllowOverride All
  Require all granted
</Directory>

The “public” folder we set as the document root will contain all your static assets (CSS, JavaScript, images, etc). It also contains a “.htaccess” configuration file that sets up Laravel’s router and enables pretty URLs. Now we need to restart the Apache server to have our new app served up. On a Nitrous box, we use the autoparts package manager to install and manage dependent software. Using the “parts” command, let’s restart Apache with “parts restart apache2″:

Now, let’s preview our website again – in the “Preview” menu of the IDE, choose port 3000 again. This time you should see the Laravel logo, and the welcome text “You have arrived”:

And arrived we have! Now we’re ready to build a simple Twilio application using Laravel. Let’s begin by exploring how we respond to incoming calls and text messages to a Twilio number.

Responding to Incoming Calls and Text Messages

Your web application already has a URL – a unique identifier you can type in your web browser’s address bar to access your site’s content. With Twilio, you can give your app a phone number as well! Your users can call or text your application, and you can present data to them with speech, audio, or text. You can build something as simple as a company directory or text message alerts all the way to a full call center with Twilio and your PHP app.

But let’s start with the basics, shall we? If you haven’t already, you’ll need to sign up for a Twilio account. Once signed up, we can obtain a Twilio phone number to use with our application. You can buy a new number to use with your app, or use an existing one here. Once you have a phone number, click on it to reveal a configuration screen that looks like this:

In the two text fields, you will specify a Request URL for both incoming voice calls and incoming text messages. Twilio will send an HTTP request to these URLs when your Twilio-powered phone number receives a call or text. Your web application then needs to respond with an XML document that contains instructions on how to handle the call or text. You tell Twilio how to behave with a set of XML tags we call TwiML. Using TwiML, you can tell Twilio to send back a text message, use text-to-speech to read a response back to a caller, play the caller an MP3 file, dial a caller into a conference call, and much more.

Let’s use our Laravel app to respond to an incoming call. To help us do that, we’ll install and use the Twilio Helper library for PHP. The latest version of the Twilio helper has been deployed to Packagist, the central repository behind Composer. You can install the latest version of the Twilio helper with “composer require twilio/sdk”. When prompted for a version constraint, you can enter “3.x” to specify the latest in the version 3 line of releases (Twilio’s PHP library should largely adhere to semantic versioning):

The first thing we’ll use the Twilio SDK for is to generate TwiML instructions for an incoming call. In your Laravel app, open “/app/routes.php” – this file contains all the routes that your application will respond to. Laravel is set up to have simple closure-based routes as well as routes that map to methods on controller objects. For the purposes of this example, we’ll use these simple routes rather than full blown controller objects.

Right now routes.php contains a single route for the home page – an HTTP GET request to the root URL “/”. Let’s add another route which will respond to either a GET or a POST request, so we can test it both ways. Just above the route for the home page, add the following route:

Route::match(array('GET', 'POST'), '/incoming', function()
{
  $xml = '<Response><Say>Hello - your app just answered the phone. Neat, eh?</Say></Response>';
  $response = Response::make($xml, 200);
  $response->header('Content-Type', 'text/xml');
  return $response;
});

Here, we’re manually creating an XML string that we are returning using Laravel’s Response object. To test that this is working okay, you can Preview your app again, but this time appending “/incoming” to the URL in the browser. You can see that rather than HTML, we’re rendering an XML document, per the Content-Type header we set on our response.

Manually creating an XML string is pretty gross though, so let’s use the Twilio helper to programmatically assemble a TwiML response. This should scale a little better as we have more complex TwiML responses:

Route::match(array('GET', 'POST'), '/incoming', function()
{
  $twiml = new Services_Twilio_Twiml();
  $twiml->say('Hello - your app just answered the phone. Neat, eh?', array('voice' => 'alice'));
  $response = Response::make($twiml, 200);
  $response->header('Content-Type', 'text/xml');
  return $response;
});

If you refresh your preview browser, you’ll see we still have XML, but this time the <Say> tag has a “voice” attribute – this tells Twilio’s text-to-speech engine which voice should be used to read back a message. Now that we know what we want Twilio to do, let’s configure our Twilio number to ask our web application for instructions when we receive any incoming calls. Copy that preview URL in your web browser, go to your Twilio number configuration, and paste the URL into the Voice Request URL field as shown:

Make sure to save your changes once you add the URL. Now, give your Twilio number a call – you should be greeted by a friendly robot lady telling you how neat your Laravel application is. I, for one, am inclined to agree.

Now that we know how to handle inbound communication, let’s handle some outbound communication and send ourselves a text message.

Outbound Calls and Text Messages

Let’s start things off by creating a simple web form with two fields – one for the text message we’re sending, and another for the phone number we’d like to send the message to. Laravel follows the Model View Controller design pattern, and separates rendering of HTML to “views” – these PHP files live inside the /app/views directory. Inside this directory, create a new file called “home.php” – we will render this view when we preview our site. In that file place the following simple HTML form:

<!doctype html>
<html>
  <head>
    <title>Send A Text</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
  </head>
  <body>
    <div class="container">
      <h1>Send A Text!</h1>
      <form action="https://www.twilio.com/blog/text" method="POST" role="form">
        <div class="form-group">
          <label for="phoneNumber">Phone Number</label>
          <input type="text" class="form-control" id="phoneNumber" placeholder="Enter a mobile phone number">
        </div>
        <div class="form-group">
          <label for="message">Message</label>
          <textarea class="form-control" id="message">Hello There!</textarea>
        </div>
        <button type="submit" class="btn btn-primary">Send Text</button>
      </form>
    </div>
  </body>
</html>

We use Twitter Bootstrap from a CDN to make our page a little more attractive, but other than that, we’re just creating a form with those two text fields we need. Now, let’s go back to our router and change the view for the home page to use this new view file:

Route::get('/', function()
{
    return View::make('home');
});

Preview your site again, and you should see a nice form for collecting a phone number and the contents of a text message. However, the form doesn’t POST to anywhere yet! We still need to implement the /text POST route, which we’ll do soon. But before we can send a text, we’ll need to configure our Twilio account information for the application. Laravel provides a means of storing environment-specific configuration options for your application. You can read more about how it works in their documentation here. At the root of your project, the same level as composer.json, create a new file called “.env.php”. This PHP code will return an associative array of configuration variables that will be made available to your application.

In this app we’ll need three config variables – our Twilio Number which we’ll use as the sender of the text message, plus our account SID and auth token, which are essentially our username and password for the Twilio API. You can find your account SID and auth token on the account dashboard. In the code below, replace XXX with your Twilio account SID, YYY with your auth token, and the 612 number with your own Twilio number:

<?php
  return array(
    'TWILIO_ACCOUNT_SID' => 'XXX ',
    'TWILIO_AUTH_TOKEN' => 'YYY',
    'TWILIO_NUMBER' => '+16129991519'
  );

NOTE: Make sure not to check this file into version control! Add it to your .gitignore file if you’re using git, or take similar steps for other VCS.

Now, open up your /app/routes.php file. We can now create a route that sends a text message, per the form inputs we have in place. Somewhere in routes.php, add the following code – read through the comments to see what’s happening at each step:

Route::post('/text', function()
{
  // Get form inputs
  $number = Input::get('phoneNumber');
  $message = Input::get('message');

  // Create an authenticated client for the Twilio API
  $client = new Services_Twilio($_ENV['TWILIO_ACCOUNT_SID'], $_ENV['TWILIO_AUTH_TOKEN']);

  // Use the Twilio REST API client to send a text message
  $m = $client->account->messages->sendMessage(
    $_ENV['TWILIO_NUMBER'], // the text will be sent from your Twilio number
    $number, // the phone number the text will be sent to
    $message // the body of the text message
  );

  // Return the message object to the browser as JSON
  return $m;
});

Now, preview your website and type your mobile number and a test message into the fields provided. When you hit the button, you should be greeted with a JSON representation of a Message object that’s returned after a successful request to Twilio. More importantly, your phone should start buzzing after it receives the text message you just crafted!

Sometimes, however, things don’t go according to plan. If for some reason there’s an error while attempting to send your message, the Twilio helper will throw an exception. For this reason, you should usually wrap your calls to the Twilio API with a try/catch block, like so:

Route::post('/text', function()
{
  // Get form inputs
  $number = Input::get('phoneNumber');
  $message = Input::get('message');

  // Create an authenticated client for the Twilio API
  $client = new Services_Twilio($_ENV['TWILIO_ACCOUNT_SID'], $_ENV['TWILIO_AUTH_TOKEN']);

  try {
    // Use the Twilio REST API client to send a text message
    $m = $client->account->messages->sendMessage(
      $_ENV['TWILIO_NUMBER'], // the text will be sent from your Twilio number
      $number, // the phone number the text will be sent to
      $message // the body of the text message
    );
  } catch(Services_Twilio_RestException $e) {
    // Return and render the exception object, or handle the error as needed
    return $e;
  };

  // Return the message object to the browser as JSON
  return $m;
});

Wrapping Up

We’ve only just scratched the surface of what’s possible with Twilio and Laravel. With Twilio and your web dev skills, you can build custom call centers to deliver amazing service, automate business processes via voice and text, and enable collaboration across multiple communications channels between your colleagues and customers. Here are some resources that might be useful as you learn more:

If you have any questions, or would just like to dish about something awesome that you built, feel free to find me on Twitter. If you have any tech questions or need help getting started, shoot us a note a help@twilio.com and we’ll do our best to get you unstuck. Good luck, and have fun!

Getting Started with Twilio and the Laravel framework for PHP

Bookmark this post:
Ma.gnolia DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google


customer_service_disasterWe have all had those truly horrific customer service experiences where we’ve called to ask a simple question or get a minor problem fixed and have hung up the phone baffled, angry, and with a negative view of the company we just interacted with. We have waited on hold for what seems like an eternity, potentially talked to multiple people who weren’t able to solve our issue, and ended the call without the resolution we were hoping for. These types of experiences not only leave the caller upset, but also damages the perception of the company, and could lead to decreased revenue from that customer, as well as potential future customers who hear the stories of the customer service disasters their friends or colleagues have gone through. Luckily there are some easy-to-implement solutions out there that can show you how to avoid customer service disasters in the future.

Use an IVR and Call Management

Using an IVR and Call Management platform can help you avoid some of these common customer service nightmare scenarios. With an IVR you can ask your callers some qualifying questions that will allow you to determine who they are so you can better service them. Finding out up front if they are a current customer who needs support, a prospect who is ready to buy your product, or someone who is looking for some general information about your product or service can ensure that you forward them on to the the right part of your customer service team.

Intelligently Route your Calls

Once the customer has been identified and routed to the right part of your customer service team, utilizing a Call Management system can make sure that call goes to the best customer service rep to handle their problem. If you have used your IVR to identify a potential new customer who is interested in one of your higher end products or services you can make sure you route them to your best salesperson. Using call routing technology, that call can also get routed to any phone, anywhere, giving you the best chance to connect them to that best salesperson no matter where they are. Likewise, if you have identified a customer through your IVR who is having service issues and is one of your larger customers, you can make sure the customer is quickly routed to your best available support person, ensuring they get the highest level of support to help solve their issue.

The good news is that there are Cloud-based solutions out there that can be quickly implemented and used with your current phone systems to help avoid customer service disasters. Gone are the days when intelligently identify and routing your callers required costly physical hardware and the setting up of complex routing rules. Now you can set up a system quickly and easily that can make your company customer service All Stars. If you want to learn more about how you easy to create a great customer service experience, we have created a free white paper that can help: Beyond the Cloud: The Next Generation of Virtual Call Center.

 

The post How to Avoid Customer Service Disasters appeared first on Ifbyphone.

Bookmark this post:
Ma.gnolia DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google


September 16, 2014

Have you ever wondered how long your dog sleeps while you’re away at work? I have. As a hacker this seemed like the perfect excuse to strap a microcontroller to my dog, Gif, and see if I could find out. To make it a little more fun I thought I could have it text me when Gif wakes up to let me know how long he slept for. In this post I’ll show how to build your very own sleep tracker for your dog using Tessel and Twilio.

Pre-reqs:

Getting Started With Tessel

Tessel is a Node.js-compatible microcontroller with built-in Wi-Fi. As a JavaScript lover I fell in love with this device as soon as I started using it. If this is your first time working with a Tessel I’d recommend working through their quick start. Before you start make sure your Tessel is running the most recent firmware and connected to a Wi-Fi network. The first thing thing we’ll do is setup your Tessel to send an SMS via Twilio.

Sending an SMS from your Tessel

We’ll start by setting some default values and requiring the libraries we need:

// your Twilio AccountSid and AuthToken
var account_sid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
var auth_token = "YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY";
var twilio_num = "5558675309";
var number = "55555555555"; // The number you want to text the information to
var client = require('twilio')(account_sid, auth_token);

We set our twilio AccountSid and AuthToken and use them to initialize our Twilio Node module so we can send a text message. We then set some variables we’ll want to use when we send our message – the twilio number we texting from and the phone number you want to text to. We also need to install the Twilio library. Even though we’re doing this locally the library will get synced to the device when we push our code to the Tessel.

npm install twilio

We’ll be using the Twilio library to send our message but to make things a bit easier later on we’re going to be wrapping this code in a function called sendText().

sendText( number, twilio_num, "This text message was sent by Tessel. Cool, right?!");
function sendText(to,from,msg) {
  client.sms.messages.create({
    to: to,
    from: from,
    body:msg
  }, function(error, message) {
    if (!error) {
      console.log('Success! The SID for this SMS message is:');
      console.log(message.sid);
      console.log('Message sent on:');
      console.log(message.dateCreated);
    } else {
      console.log('Oops! There was an error.', error);
    }
  });
}

If you’ve worked with the Twilio node library before the rest of this code should look very familiar. We’re using the library to POST to the Messages resource to create a new SMS message. We do some basic error checking so we can make sure nothing went wrong.

Once you’re done, your code should look like this gist. Run this app on your tessel and send yourself a text message.

tessel run twilio.js

Your Lazy Dog

Now that we’ve built the functionality to send a text message from our Tessel we need to write the code to detect just how lazy your dog is being while you’re away. We’ll use the accelerometer to do this. First, plug in your accelerometer module to port A.

Since the accelerometer module isn’t included on the Tessel by default we need to install it. Specifically we’ll be using the accel-mma84 library to interact with the accelerometer:

npm install accel-mma84

Then initialize it in your code:

var accel = require('accel-mma84').use(tessel.port['A']);

Let’s write some basic code to make sure our accelerometer is functioning correctly:

// Initialize the accelerometer
accel.on('ready', function () {
  // Stream accelerometer data
  accel.on('data', function (xyz) {
    console.log( xyz );
  });
});

accel.on('error', function(err){
  console.log('Error:', err);
});

In this code we’re waiting until our accelerometer is ready and then we’re streaming the data as it comes in. The data we get back is an array of floats representing the acceleration on the X, Y and Z axes. If there’s an error, we’re logging that. If you’re getting an error try updating your firmware or resetting the Tessel by pressing the reset button right next to the microusb port.

Once we know our accelerometer is working we can start writing the code that detects if your dog is sleeping. We’ll be using a very basic algorithm to determine if our dog is asleep or awake. We’ll compare the last x-axis changed position to the current value of the x-axis on our accelerometer. If these values differ we know there’s been movement and determine how much time has passed . A movement after any period greater than 5 minutes we’ll consider sleep and send out a message about how long the dog slept.

Let’s set up a couple variables we’ll be using to track the movement intervals:

var last_movement = 0.0;
var last_movement_time = Date.now();

We’ll be using the last_movement and last_movement_time variables to track movement from the accelerometer and see how much time has passed between movements.

Let’s dive into the code we’ll use to detect when there’s movement with our accelerometer:

// Initialize the accelerometer
accel.on('ready', function () {
  // Stream accelerometer data
  accel.setOutputRate(1.56, function rateSet() {
    accel.setScaleRange( 8, function scaleSet() {
      accel.on('data', function (xyz) {
        if( last_movement !== xyz[0].toFixed(1) ) {
          last_movement = xyz[0].toFixed(1);
          var minutes = ( (Date.now() -  last_movement_time)/1000) / 60 ;
          last_movement_time = Date.now();
          if( minutes > 5 ) {
            // send text
            sendText(number, twilio_num, "Your dog slept for " + Math.round( minutes ) + " minutes");
          }
        }
      });
    });
  });
});

We want to update a couple ways our accelerometer is tracking data to optimize for our use case. Output rate determines how often we’re sampling data from the accelerometer. Since we’re interested in larger trends we’ll change the output rate to 1.56 Hz (the lowest available for the accelerometer) to sample less often. Similarly, we aren’t concerned with a super precise reading so we can set our scale to 8 Gs of acceleration. This may vary based on the dog you are using.

After the data starts streaming we compare our last movement to the current position of the x-axis on our accelerometer. We’re trimming this position to 1 decimal point because we’re not interested in very small movements. If there’s been a movement we’ll see how long it’s been since the last movement. This information is in milliseconds so we convert it to minutes. We probably only want to know if our dog has been sleeping for an extended amount of time, so we’re only triggering a text message if it’s been more than 5 minutes since the last movement.

If it’s been more than 5 minutes we call the sendText function we wrote earlier to notify you how long your dog has been sleeping.

Your final code should look like this. Let’s test it out by running it:

tessel run twilio.js

Deploy to Your Dog

Once we’ve tested our app let’s use the tessel push command to push our app into Tessel’s flash memory. This will auto-run the app whenever the Tessel powers up.

tessel push twilio.js

Now strap this puppy on to your puppy (pun intended). I put mine on Gif’s Twilio hoodie so it would be more comfortable:

Now you should be notified how much your puppy sleeps.  Here’s a peek into Gif’s sleeping patterns:

We successfully used the Tessel to enter the world of #DogHacking. What’s next? Maybe you could use the Tessel GPS module to find out your dog is somewhere they shouldn’t be or use the camera module to get updates of what your dog is seeing in real-time. Have any questions or want to show me how cute your dog is? Reach out on twitter or via e-mail.

Building a Sleep Tracker for Your Dog Using Tessel and Twilio

Bookmark this post:
Ma.gnolia DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google


LinkedIn AdvertisingWhat is it that sets LinkedIn advertising apart from Facebook, Twitter, and other paid social network advertising? In my opinion, it is the ability to directly target the decision-makers you are trying to reach, with ads and sponsored content that are relevant to the product or service you are trying to sell.

How is this any different from Google? With Google you are targeting anyone and everyone on the web searching for keywords related to your offering. This often includes people who are unable to make a decision to purchase from your business and many other random outliers. In other words, with LinkedIn the ability to target your niche audience is much greater than with Google. Google = extended reach, LinkedIn = specificity.

The same theory that goes for Google also applies to Bing (millions of searches, less targeted audience) and Facebook (millions of users, more social/consumer focused than LinkedIn).  Now don’t get me wrong, I love advertising on Google, Bing, and Facebook (well, sort of). These networks give me the ability to get my brand and content in front of thousands of relevant Internet searches every single day. I generate a lot of quality leads from these networks. These leads often convert into customers. But what is missing from these networks is the ability to target specific people: decision-makers at companies and in industries that I am trying to tap into, and reach out to them directly. Why?

Ads vs. Sponsored Content on LinkedIn

There are two different ways to reach your target audience on LinkedIn: ads and sponsored content. Creating an ad on LinkedIn is very similar to Google or Bing. Name your campaign, enter your landing page URL, and create a short text headline and ad. If you choose to sponsor content you’ll be given the option to select from a list of recent posts you’ve made on your company LinkedIn page, or you can create a new one.

Advertising Options

Whether you choose to create an ad or sponsor an update, LinkedIn offers advanced targeting capabilities. LinkedIn offers you the ability to target a company specifically by name. You can also choose to target your ads by category such as industry or company size. Once you’ve selected the company and/or industry you want to target, you can select specific job titles to target (the tool recommends similar job titles as well), job functions, or seniority level. Once you’ve selected the criteria you want to target, you can add exclusions to ensure your ad or content is only shown to relevant LinkedIn users.LinkedIn Audience

You can see through this example how easy it is to target a specific audience with your ad or content on LinkedIn. Unlike with Google and Bing, you can use LinkedIn to target specific people such as decision makers, Directors, VPs, CEOs, etc. in the B2B industry to make your message more effective.

In a recent call I had with my LinkedIn account rep, he recommended sponsored content as a better option than ads. He mentioned that sponsored updates tend to see a 0.3% higher CTR compared to ads. He also mentioned that the sponsored updates often receive better inventory as far as the auction is concerned, meaning it’s easier to get your sponsored content in front of your target audience rather than your ad.

LinkedIn Analytics

Once you are up and running with your highly targeted, highly relevant advertising or content campaign, LinkedIn offers intelligent reporting within the campaign manager interface. You can see similar metrics to those you have in Google and Bing such as clicks, impressions, CTR, average CPC, and total spend.

LinkedIn Analytics

While the above metrics are helpful in determining whether or not a campaign is performing well, one glaring metric that is missing from their interface is phone calls. Since the audience you are reaching on LinkedIn is highly targeted and specific, the people viewing your ads probably already know about your company and/or offering. The ad or content you are showing them is probably not the first they’ve seen of you: they may have already visited your website, they may have already interacted with someone on your sales team. They are probably further along in the sales cycle than someone who may see your ad on Facebook or Bing. They don’t need to learn more, they are ready to talk to someone and make their purchase.

To help increase the chance of converting this lead or prospect into a customer as quickly as possible, you can make it easy for the user to reach out to your business by including a call tracking phone number in your ad and/or landing page. In Q2 2014, mobile accounted for 45% of unique visiting members to LinkedIn (LinkedIn), so calling is often the fastest and most convenient way for them to reach you when they see your brand. Once the user calls, the call (and everything that happens after they pick up the phone) can be tracked online so you can track the true ROI of your LinkedIn advertising campaigns.

To learn more about generating and tracking phone leads from LinkedIn and other social networks, download the free guide, “B2B Lead Generation for Social Media: Tips for Generating and Tracking Phone Leads.”

The post How to Reach Your Target Audience With LinkedIn: Advertising, Analytics, and Call Tracking appeared first on Ifbyphone.

        

Bookmark this post:
Ma.gnolia DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google


September 15, 2014

People are okay with all 1,000 of their Facebook friends seeing carefully composed pictures of their morning latte. But pictures of weddings, baby showers, and family reunions are a little more sensitive than the rosetta your barista poured that morning. Jeremy Senn built PicShare Party to give friends and family an easy to share pictures privately via SMS without having to download an app.

When Jeremy went on a family vacation to Hawaii, his whole family snapped photos throughout the trip. Every day they’d text each other photos from the day, spending a ton of time and data trying to make sure everyone had the photos they wanted. Despite the effort, each family member had an incomplete digital photo book of the vacation. Jeremy got home and sought out build an easier way to share photos.

http://www.dreamstime.com/stock-photos-bride-groom-enjoying-meal-wedding-reception-looking-to-camera-smiling-image35609923

Think of PicShare Party as a private photo book that guests/family can add to via text.  Users can text the event’s Twilio number to add photos to the gallery. After the event, the owner of the gallery can curate and download all the pictures, and send the gallery’s link to guests via Twilio SMS.

Jeremy says that keeping everything SMS based eliminates two big barriers to sharing: downloading apps, and giving up privacy. Jeremy built the prototype of PicShareParty himself using Twilio’s docs and a Ruby on Rails stack. After completing the prototype he bought a Twilio MMS shortcode to take PicShareParty to market.

Although PicShareParty has only been live for a few months, Jeremy is actively building out new features for users that allow them to control who sees what photos, and how they get them. He’s currently working on a two-factor authentication style system that will identify  guests who contributed photos versus guests who did not contribute photos by their phone number. That way event organizers will have another way to determine how to share photos.

You can learn more about PicShareParty here

PicShareParty Makes Photo Sharing Easier and More Private with Twilio

Bookmark this post:
Ma.gnolia DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google


marketing automationAt this point, most marketers have heard the term “marketing automation” and the way it can positively impact businesses. But in case you’ve only overheard the benefits, here are three of the most basic ways that marketing automation adds something good to your business.

Marketing Automation Fuels Growth

Anyone running a company knows how there is always something that needs to be done, especially when you’re trying to grow your business. Marketing automation is one way to bring in new customers (and reengage old customers) without devoting too much time to those activities. Email marketing and nurturing campaigns? No problem. Automating those processes means you’re doing more for your marketing department but not doing more work. A couple interesting stats that back up the claim of business growth:

  • 28% of marketers saw an increase in revenue per sale attributable to marketing automation. (Chief Marketer)
  • 75% of companies using marketing automation see ROI within 12 months, 44% within 6 months (Focus Research)
  • Companies using marketing automation source 45% more pipeline than those who don’t use marketing automation. (Marketo)
  • Marketing automation drives a 14.5% increase in sales productivity and a 12.2% reduction in marketing overhead. (Nucleus Research)

Marketing Automation Helps You Keep in Touch With Your Customers

Lately, all I hear is “Your customer service isn’t service unless it’s customer obsessed” and I will be one of the first to agree. Studies continually show that we live in the Era of the Customer. Customers no longer take linear, easily influenced paths to buying; instead, it’s all about building relationships, with customers taking product research into their own hands. With marketing automation, you can send emails or integrate with direct mail for marketing, automate phone calls and voice broadcasts, and more. The customer’s pathway to buying is more varied than it once was, but our means of engaging with customers is also more varied. We have options when it comes to keeping in touch with customers, and automation helps you use all of them.

Marketing Automation Establishes Your Brand

This ties into keeping in touch with your customers, but it deserves a mention of its own. With marketing automation, you’re not just communicating with your customers with the hope that they’ll convert from a marketing email, etc. You’re doing it for the greater purpose of branding. Now, branding is a word that gets thrown around a lot, and people don’t always know what it means, but one thing is certain: effective branding is putting your company in front of your audience strategically and consistently, keeping your business at the front of their minds without overwhelming them. Staying in front of their eyes will eventually create an association with the product or service that you provide, and that is step one of branding. Marketing automation is today’s marketer’s version of running all around town plastering signs on walls. With this tool, you will always work smarter­–not harder.

There are layers to this, of course: different marketing automation strategies and products that do the above three things and more. Want to keep learning? Download this huge guide that breaks down another kind of marketing automation from start to finish: The Definitive Guide to Voice-Based Marketing Automation.

The post 3 Ways Marketing Automation Is Good for Your Business appeared first on Ifbyphone.

Bookmark this post:
Ma.gnolia DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google


September 12, 2014

debra lee chicagoOn Wednesday, the Executives’ Club of Chicago kicked off its Women’s Leadership series by hosting CEO of BET Networks Debra Lee for a discussion on diversity and creating content that has a strong impact. Having been part of the network for 30 years, a network that hosts some of the most popular programs of the season across all adult viewers, Lee was able to offer some valuable advice to the audience about how to create content that can both entertain and empower, and create a brand that is successful in its vision.

“A brand without vision is just a commodity,” Lee started off saying, and commodities come and go. But when a company has a vision, with core values that are supported in their daily action…that is what causes an audience to continue to choose that brand over and over again. BET’s core values, Lee said, are simple: Respect, Reflect, and Elevate. By respecting, reflecting, and elevating their audience through the variety of programming they continue to offer, they have managed to grow their viewership year after year. Your audience will be diverse in many ways, but the key—no matter your industry—is to offer something that brings value to them all.

Once a brand has established their vision, Lee said, the next step to execution is surrounding yourself with a flawless team. The people you hire should be as varied as your audience, and this is where Lee touts the importance of diversity. If your team reflects the many different aspects of your business and audience, then you have a big advantage in seeing your brand vision reach fruition. Lee described one of her early experiences of serving on the corporate board for Revlon. Despite the fact that the brand’s audience is almost entirely women, Lee herself was only one of two women on the board. “What do men really know about lipstick?” she asked, to laughter. But some realizations were made, and now the board seats more women than ever before. Not every brand will have an audience whose makeup (pun intended) is so easily narrowed down, but that’s why diversity is always your friend: teaming up with a variety of voices and experiences can only mean good things for the level of perspective you gain about your audience. Simply put, said, Lee, “Adding women and people of color to your team will strengthen it and bring new, fresh ideas, and help your bottom line.”

BET’s vision is grander than most: the network seeks to create entertaining content that is also a catalyst for Change with a capital C. But what they seek can be applied to any business, even if on a smaller scale: creating change in your industry can mean different things to different businesses, but above all, Lee says, if you want to make change, “you must set it as an objective.”

At the end of her keynote, Lee challenged the audience to do three things:

  • Use brand vision to build an organization that knows its purpose.
  • Embrace diversity to help the organization reach its full potential.
  • Use your voice to empower your audience, consumers, and community.

Challenge accepted, Ms. Lee.

The post Diversity and Successful Brand Vision with BET CEO Debra Lee appeared first on Ifbyphone.

Bookmark this post:
Ma.gnolia DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google


September 11, 2014

Hello fellow Rubyist, I see you have your shiny new Twilio application written, perhaps a Rails app or Sinatra, like in our Ruby quickstart guide. Before you hit that deploy button, you need to stop and ask yourself a couple of questions about that app. Do your webhooks expose sensitive data when they receive a request? Do they change data within your system? If your answer to either of those questions is yes, then you should be making sure that your app only responds to requests that come from Twilio.

You can do this using Twilio’s request validation. Twilio will cryptographically sign all requests that it makes to your application. We create a signature using your callback URL, the request parameters and your auth token then add an HTTP header,

X-Twilio-Signature
, containing that signature. On your server, you can follow the same process to create the signature and check if it matches, if it doesn’t the request can be rejected. There are more details available in the security documentation.

Until recently, if you wanted to secure your endpoints using the twilio-ruby gem you could use the

Twilio::Util::RequestValidator
class. The gem documentation has an example of how to do this, but you have to adapt that to your web framework of choice. If only there was a simple, one line way to add request validation to your app.

Middleware to the Rescue

Rack is an interface for web applications in Ruby and is the foundation on which most of the popular Ruby web frameworks including Rails, Sinatra and even Camping. Further to this, Rack provides support for middleware, filters that can intercept a request and alter the response from a web application.

Middleware is an ideal place to validate our incoming requests from Twilio and other platforms have been using them to simplify that job for quite a while now. For example, Node.js developers have had request validation with middleware for the Express framework since the start of the year. And now I’m pleased to tell you that, with version 3.12.0 of the twilio-ruby gem, there is an easy to use Rack middleware that you can drop into your apps in order to validate that your incoming requests are from Twilio.

So, let’s see how easy it is to put this new middleware to work in a Rack application application.

An Example Application

To show how easy it is to use this middleware, let’s put together a very quick application using Sinatra.

First we need to install the gems that we’ll need.

$ gem install sinatra twilio-ruby

Now, create a file named app.rb and copy in the simple Sinatra application below.

require 'sinatra'
require 'twilio-ruby'

# Create a webhook that handles an incoming SMS and responds with TwiML
post '/messages' do
  response = Twilio::TwiML::Response.new do |r|
    r.Message "Hello from Sinatra!"
  end
  # Render the TWiML response
  response.to_xml
end

This application will respond to any POST request to

/messages
without any request validation whatsoever. It only returns the TwiML to send an SMS in response, but as this is only an example we could imagine it does something a bit more dangerous. Let’s run the app and check that this is working as we expect.

$ ruby app.rb

The application will now be running on localhost on port 4567. Let’s make a post request and get back the TwiML that we defined.

$ curl --data "chunky=bacon" http://localhost:4567/messages

You will have seen the XML response defined in the app proving that we can make a POST request with any data in it and our application will respond. Now let’s add in the Rack middleware provided by the gem and ensure that the application only responds to requests initiated by Twilio.

Securing Our Webhooks with Rack Middleware

When making a webhook request Twilio includes a header,

X-Twilio-Signature
, that is signed with your account auth token. This is what we use to verify the request came from Twilio. In order to do that, our application will need to know our auth token.

Keep the config in the local enviornment

I prefer to store config variables in the application’s environment, following the advice from the Twelve-Factor App. Let’s add in Dotenv to make that easy for us.

To add our auth token to our environment we’ll need to install the Dotenv gem.

$ gem install dotenv

Then we’ll need a .env file with our auth token in. Dotenv config files are written like so:

TWILIO_AUTH_TOKEN=YOUR_AUTH_TOKEN_HERE

Save that file and then add these two lines to our app.rb file:

require 'sinatra'
require 'twilio-ruby'
require 'dotenv'

Dotenv.load

post '/messages' do
  # TwiML response
end

Drop in the middleware

Now we have everything we need to add our middleware to the application and secure our

/messages
endpoint. After you load the config, add the following line:

use Rack::TwilioWebhookAuthentication, ENV['TWILIO_AUTH_TOKEN'], '/messages'

This tells Sinatra to use the

Rack::TwilioWebhookAuthentication
middleware and passes two arguments to it: our auth token and a path to secure. The path ensures that the middleware only validates requests to our Twilio endpoints, since we can’t expect everyone to send a correct
X-Twilio-Signature
with each request.

Let’s test this with curl to make sure we are now receiving the correct response.

$ curl --data "chunky=bacon" http://localhost:4567/messages
Twilio Request Validation Failed.

Excellent! Our app doesn’t respond with potentially sensitive data to just any request now.

We should now test that responding to requests initiated by Twilio does work. This is out of scope for this post, but you can read up on how to test your local webhooks with ngrok in this post by Kevin. When you get that set up, you should find that sending a text to your Twilio number will get a text in response.

You can actually pass multiple paths to the middleware too. If you had another endpoint defined at

/voice
for voice calls then you could set up the middleware like so:

use Rack::TwilioWebhookAuthentication, ENV['TWILIO_AUTH_TOKEN'], '/messages', '/voice'

Now requests to both

/messages
and
/voice
are secured.

What About Rails?

That was a simple example application in Sinatra, but thankfully it is no more difficult to add this functionality to a Rails application.

Let’s assume that you already have a Rails application with the twilio-ruby gem included and an endpoint defined at

/messages
, similar to the Sinatra application.

To add the middleware, you need to open up

config/environments/production.rb
and within the application configure block add the following line:

Rails.application.configure do
  # Other Rails config

  config.middleware.use Rack::TwilioWebhookAuthentication, ENV['TWILIO_AUTH_TOKEN'], '/messages'
end

That’s all there is to it.

We are only adding this to the production environment as that is the only one that is likely to contain sensitive information. You could add the middleware to

config/environment.rb
if you wanted to protect all environments.

Webhooks Secured

If you apply what we’ve gone through here to your Rack based applications your webhooks will be nice and secure. With a bit of setup and a single line of config your application will only process requests to your webhooks from Twilio.

As a bonus, if you had set up request validation before using the

Twilio::Util::RequestValidator
then you can replace that implementation and worry about maintaining a few less lines of code.

Are you interested in how the middleware works compared to the reference implementation of the validator? You’re welcome to check that out on GitHub. Please raise any bugs or feature requests that you may have on the GitHub issues page. Of course, if you just want to chat about how awesome Rack middleware is (what can’t it do?!) then drop me a line on Twitter or shoot me an email.

Securing Your Ruby Webhooks with Rack Middleware

Bookmark this post:
Ma.gnolia DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google


Microsoft is betting that the explosive growth of Internet videos will continue to climb and has unveiled Azure Media Indexer for consumer use.  Instead of continually having to stop and rewind audio and video material to find content, the Indexer does the heavy lifting by using speech recognition. “We provide the ability for customers to […]

Bookmark this post:
Ma.gnolia DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google


If you peeked into one of the 4th grade computer classrooms at the KIPP: Empower Academy you would see a room full of kids spending valuable class time playing Angry Birds. That’s because while they are playing Angry Birds, they’re also learning to code.

Today, Code.org announced they’ve launched Code Studio, an online learning platform that teaches young students (Kindergarten through 8th grade) the basics of computer programming. Code Studio wraps the computer science, math and logic lessons in such a slick environment that most kids think they’re just playing a game — until they realize they’ve caught the programming bug.

K1-3Kids can use Code Studio’s Play Lab to send apps and animations directly to friends, family and other students via Twilio SMS for free, sponsored by Twilio.org. All they have to do is type in the phone number within the Play Lab environment and fire off a text (pictured right).

“We believe passionately that every child who has an opportunity to discover the world around them through the use of a smartphone should also be given the learning capabilities and tools to build their own app,” said Hadi Partovi, founder of Code.org. “Code Studio enables even our youngest students to learn to build a basic animation or app in elementary school, and then share it to a friend’s phone within minutes.”

We can’t wait to see what a new generation of young coders can do with the power of programming at their fingertips.

Learn more about Code.org and their Code Studio initiative by visiting their website here.

The Future of Coding In Kids’ Hands: Code.org Launches Code Studio to Educate, Inspire

Bookmark this post:
Ma.gnolia DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google


mongoose metrics acquisition

I’m delighted today to welcome the Mongoose Metrics team to Ifbyphone. We know the talent and technology they bring will enhance our ability to offer the world’s most innovative call tracking and voice-based marketing automation platform. As a leader in call tracking and analytics, Mongoose Metrics has played a significant role in how marketers and agencies prove and improve ROI from their campaigns, and I know that together we will bring a tremendous amount of value to our combined customer base.

Over the years, Ifbyphone’s unique innovations in call tracking and voice-based marketing automation – including recent additions of new geo-location and keyword spotting technologies – have distinguished us as the leading platform for enterprises and agencies wishing to optimize ROI and revenue from phone calls. By adding Mongoose Metric’s technology and integrations to the Ifbyphone portfolio of products and services, we further distance ourselves from the pack and signal loud and clear that Ifbyphone is the de facto standard in call tracking, analytics, and call management. And by adding Mongoose Metrics’s people to our world-class team of call experts, we have the resources and skills to be the driving force of innovation in our industry today and for years to come.

There is a tremendous amount of synergy between our two groups: both are product-led, entrepreneurial, and customer-focused. We share the same core values and the same core mission of building terrific products that solve real business problems for our customers. Joining our two great companies together makes perfect sense.

I’m truly excited and honored to embark on this journey as we work together and continue to build a world-class company, industry-leading products and services, and deeper relationships with our customers.

-Irv Shapiro, CEO of Ifbyphone

The post Creating the Undisputed Leader in Call Tracking Through Our Mongoose Metrics Acquisition appeared first on Ifbyphone.

Bookmark this post:
Ma.gnolia DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google


September 10, 2014

If you’re reading this, you benefit from an open Internet. You take for granted that the browser you’re using can reach our blog. But that could change.

If you haven’t been following the Net Neutrality news for the past several months, here’s the situation. The Internet is a free (as in speech) and open network, where your mobile or broadband ISP is supposed to transmit bits between any Internet connected server to you without opinion on what those bits mean or whether you should be permitted to access them. It’s a doctrine called net neutrality, and it’s been the basis of innovation on the Internet since pretty much day one.

The FCC is currently considering a reversal of this doctrine, allowing ISPs and carriers to use arbitrary policy to price and police your Internet for those services you use. This action would open the doors for discrimination in who can access its subscribers, at what price, and for what use-cases. While the debate has centered on Netflix, and other high bandwidth applications, this action would affect every Internet service, not just streaming movies that compete with your cable company. See, your ISP has a monopoly on access to you, the subscriber — so now they’d like to exercise control with that monopoly.

Like many young companies born on the Internet, we have benefitted from knowing that our ability to reach customers was guaranteed by the level playing field provided by net neutrality. New services on the Internet don’t have to do laborious business development with each carrier and ISP in order to reach customers. It’s hard to imagine that world, it almost seems insane. Ironically, we at Twilio know what that world looks like because we do it every day to enable voice and SMS communications to the 1200+ carriers of the world. It’s one of our core competencies, and we know — it’s hard work, is tremendously resource intensive, and is the last thing small businesses should worry about on the day of launch.

The power and the promise of the Internet has been its elimination of gatekeepers — and this has worked well as an engine of innovation and entrepreneurship for the last 20+ years. If you agree, and want to continue to enable free speech and the freedom to innovate, then today is the day to take action.

We’re proud to be partnering with Fight for the Future, Demand Progress, and Free Press to power today’s Internet Slowdown, a call to action for people who want a neutral Internet. Days of outreach like todays’ Internet Slowdown work incredibly well to tell your government that you care, and will hold them accountable for their decisions. If you’re an innovator, an entrepreneur, an engineer, or user of the Internet, please take a moment to use this widget to contact your government, both the FCC and your members of Congress, and tell them you care about the Internet and its future.

Day Of Action: Fight Back Against ISP’s Slow Lane #StopTheSlowLane

Bookmark this post:
Ma.gnolia DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google


improve ROILead scoring has become an integral part of lead generation today, especially for larger businesses that generate hundreds of leads each day.

When done well, lead scoring enables sales teams to become more productive by focusing on those prospects most likely to purchase. It can also help guide marketing in the creation of campaigns that deliver more high-quality leads. And for agencies contracted to drive leads to enterprise clients, lead scoring can be an invaluable means of proving the quality, impact, and ROI of your programs.

But while there is no shortage of advice for marketers on how to score leads that convert online, there is very little on how to score the inbound calls your marketing generates. And the two lead types are quite different.

A web lead is someone who filled out a form on your site or landing page and moved on with their day. They might not expect (or even want) your sales team to contact them. But someone who calls you is expecting to speak with you right away, even though it might not be in your best interest to have a sales manager speak with them. Scoring these calls requires a different mindset and a different set of technologies than scoring web leads.

If you are interested in scoring the phone leads you generate for your own business or for clients, below are four ways to do it. I’m presenting them as an integrated, step-by-step process, but you may choose to use just one or two of these techniques, depending on the nature of your campaigns and business.

Step 1: IVR Virtual Receptionist for Filtering Out Bad Calls

While inbound calls are often the most lucrative lead type, it’s important to remember that not every call is created equal. Studies show that 19% of inbound calls are high-quality sales leads, but others are often mundane inquiries for things like business hours and store directions. Many calls will also be job requests, misdials, or solicitations. Wasting marketing budget on campaigns that drive these calls is bad enough, but you don’t want to compound the problem by having your sales staff waste time answering them.

That’s why marketers often send calls to an IVR virtual receptionist first to qualify callers. The IVR will ask callers the questions you determine work best to qualify them. It may be as simple as “press 1 for sales, press 2 for support, press 3 for account information, press 4 for business hours, etc.” Forcing callers to pick an option can weed out the misdials and robocalls, and provide answers to callers inquiring about non-sales related matters or account information.

You can also create a list of more elaborate and campaign-specific questions the IVR can ask each caller to determine if they are really sales-ready. For the ones that are, they can be routed to a sales manager to assist, while the ones that aren’t can be sent to a voicemail box or even a second IVR menu to assist them.

Step 2: Keyword Spotting for Automated Call Quality Scoring

The next step after filtering out the bad calls is to score the quality of the ones sent to sales. Since it obviously isn’t practical to listen to every conversation to access value, you can automate the process with keyword spotting technology. Keyword spotting monitors conversations between callers and sales agent for the keywords you determine best indicate a lead’s quality (if the lead says “buy” or “pricing” or “appointment,” for example). It then scores the call based on the appearance and frequency of those words, and who said them.

The keywords and scoring system you use are customizable for each campaign and can also be adjusted to improve accuracy. It’s a great way for enterprises with high call volumes to measure call quality, and for agencies and lead gen services that need an easy way to prove the quality of the leads they send to clients.

Step 3: Call Recording for Proving Call Value

Hearing really is believing, and sometimes when scoring phones leads there is just no substitute for listening to the actual conversation. That’s why many companies record their sales calls as a way to evaluate quality and measure the effectiveness of sales agent performance.

True, manually examining call recordings is not practical for large marketing campaigns with high call volumes. That’s what keyword spotting is for. But call recordings can come in handy when you need to double-check scores from keyword spotting reports or prove to doubting executives that your scoring data is accurate.

Step 4: Call Tracking and CRM Integration to Follow Phone Leads Through the Sales Cycle

At the end of the day, the ultimate judge of phone lead quality is whether the caller converted to a sales opportunity or a customer. That may be something that can happen on the call, but it might also take weeks or months, even years, depending on the products or services being marketed. So marketers wishing to pass final and definitive judgment on phone lead quality from a campaign need a way to follow each call through the sales cycle to revenue.

To get that data you would first need to use unique call tracking numbers in your marketing that can tie calls back to the specific source and channel that generated them. Then you would need to integrate that call tracking data with your CRM system to follow the lead through the sales cycle. While getting final data for campaigns could take time, that data should provide the final word on if a campaign really worked, how it impacted the business, and whether or not it’s worth redoing.

The post Four Ways Marketers and Agencies Score Phone Leads to Prove (and Improve) ROI appeared first on Ifbyphone.

       

Related Stories

 

Bookmark this post:
Ma.gnolia DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google


Last updated: September 23, 2014 08:01 PM All times are UTC.
Powered by: Planet

Speech Connection and Logos are Trademark of Nu Echo Inc. Copyright 2006-2008.