October 01, 2014

Anyone who knows me will know that Django is my favourite web framework. On the second of September 2014, Django 1.7 was finally released to the public after a much anticipated wait. Some of the new features coming out in 1.7 include App Loading refactoring, custom Queryset methods and a bunch of minor updates to make Django development smoother than it has ever been before.

However, the most exciting feature present in the new version is database schema migration management. This feature update was driven primarily by Andrew Godwin, after a successful Kickstarter campaign to work on the integration. Andrew is the author of the original schema migration package South and the entire community is forever grateful for the contributions he has given to the platform.

When I first used Twilio, I stumbled upon Randall Degges’ helper library for Django, django-twilio. I offered my technical support to Randall after emailing him about the fantastic library he created. After some great Python banter he let me have access to the repository to help continue the work he started.

With the advent of Django 1.7, Django Reusable Apps (the term used to refer to plugins) will need to be updated to support both Django 1.7 migrations and pre-Django 1.7 database migrations.

I recently had to update the django-twilio reusable app to do just this and I decided to document the procedure in order to provide other maintainers with a quick how-to on easily updating their own projects.

This guide only covers database migrations management support for Django 1.7, no other new 1.7 features.

What We’ll Cover

This guide assumes you are familiar with Python, virtualenv, PyPI and Django open source project development. Even so, to keep up with The Zen of Python, I’m going to be explicit about the steps required to reliably update your Django reusable app.

In this guide I’ll cover:

  • Setting up two separate virtual environments for Django 1.7 and Django 1.6 respectively.
  • Updating the migrations files to support Django 1.7 and Django 1.6
  • Running the migrations for your Django reusable app in both versions
  • Updating the documentation to cover both versions of Django

Configuring Virtual Environments

The quickest, most reliable way to test compatibility with both Django 1.7 and Django 1.6 is to install both versions on separate virtual environments. If you are unfamiliar with virtualenv, it is a tool that allows you to “sandbox” Python development environments so you do not encounter dependency issues from multiple projects with multiple versions.

The new virtual environments will be directories within the root of your project. You will need to cd into the root of your project directory.

I am going to be using the word “django-package” to refer to the Django reusable app we are updating, be sure to substitute it with the name of your own reusable app. I’ve also taken screenshots of the procedure with django-twilio, to give you visual support.

With virtualenv installed we can create new virtual environments with the following commands:

$ virtualenv venv1.7
$ virtualenv venv1.6

This will add a bunch of folders into a new venv1.7/ and venv1.6/ directory which will be filled with Python packages later.

Your django reusable app root directory should now have two extra child directories like so:

django-package/
    venv1.6/
    venv1.7/
    ...

Installing Django 1.7 And Django 1.6

To install Django 1.7 into our venv1.7/ directory we first need to activate the virtual environment using this terminal command:

$ . venv1.7/bin/activate

This will prepend your terminal command line with the name of the virtual environment you’re currently in:

We can then install Django1.7 (and any other requirements your project needs) with the following terminal commands:

$ pip install -r requirements.txt
$ pip install django==1.7

You can exit the venv1.7/ virtual environment with the terminal command:

$ deactivate

At this point, you will need to activate the venv1.6/ directory using the same commands as above (but substituting “venv1.7” with “venv1.6”) and then install the latest version of Django 1.6 and other requirements with the following terminal command:

$ . /venv1.6/bin/activate
$ pip install -r requirements.txt
$ pip install django==1.6.7

We’ll also need to install South in this virtual environment too, if it isn’t already installed:

$ pip install South==1.0

Now we have:

  • A virtual environment called venv1.7/ with Django 1.7 installed
  • A virtual environment called venv1.6/ with Django 1.6.7  and South 1.0 installed

With both versions of Django ready we can now start updating our reusable app to support them!

Support All The Djangos!

The nitty gritty of updating a Django reusable app to support both versions of Django migrations boils down to two things:

  • Renaming the old migrations directory to south_migrations
  • Using Django 1.7 to build new migrations for your project

The first step is dead simple: just rename the old migrations folder in your project (usually in the same directory as models.py) to south_migrations. This directory will now be used by South to run migrations for projects that are not on Django 1.7. You will also want to remove all the old .pyc files in this directory using the following terminal command:

$ rm -rf django_package/south_migrations/*.pyc

The second step is a bit more complex: you will need an existing Django project in order to run the makemigrations command used by Django 1.7 to make the new migrations files.

In the Django-twilio project, we use a Django project called test_project that has all the settings needed by Django to build new migrations. This project is a default project with nothing additional added and is used purely for creating or updating migrations files. I’ve found this is a pretty reliable way of updating migrations, but if you know a better way, please tell me!

From within django-package directory, we need to activate the venv1.7 virtual environment:

$ . ../django1.7/bin/activate

We can then build a new Django1.7 project, called test_project, with the following terminal command:

$ python venv1.7/bin/django-admin.py startproject test_project

In the test project, we need to add our Django reusable app to the list of installed apps, in test_project/test_project/settings.py:

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # Our Django reusable app goes here
    'django_package',
)

You may need to copy/paste the django_package directory (your reusable app) into the test_project too, this can be done simply:

$ cp -r django_package test_project/django_package

Finally, we can run the makemigrations command:

$ python test_project/manage.py makemigrations django_package

What Happens?

Based on the project structure we’ve laid out, the following will happen:

  • Python will execute the makemigrations command through the manage.py file in the test_project project.
  • Based on the settings.py in the test_project folder, Django 1.7 will check the django_package reusable app for any changes. Because this is the first time – there will be no migrations, so a new migration file must be created!
  • Django 1.7 will generate the new migrations files:

Here we see the django_twilio example that I did earlier

If Django gives the warning “No changes detected in app” try to remove all the old *.pyc files.

Et voilà: Django 1.7 migration support in your reusable app! Wasn’t that easy?

Testing Everything Out

We’re not done yet however. A good Django reusable app will be fully tested with the latest version. With the Django1.7 virtualenv still active and your django_package in the project settings.py file, we can try to build the new migrations into the database with the terminal command:

$ python manage.py migrate

The output will be something similar to this:

In this example Django 1.7 has detected my django_twilio library and applied the migrations for the models. Perfect.

You should now be able to deactivate the current virtual environment with the terminal command:

$ deactivate

and activate the django1.6 virtual environment with:

$ source venv1.6/bin/activate

We will need to add South to the list of installed apps quickly:

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # Our Django reusable app goes here
    'django_package',
    # South goes here:
    'south',
)

The Django 1.6 style of handling migrations, using South, should still work with the two terminal command. You’re likely to be asked to add an Admin user to Django, you can type “no” in this case, we won’t need to:

$ python test_project/manage.py syncdb
$ python test_project/manage.py migrate django_package

The first command will sync the standard Django models and South. The second command then uses South to migrate your Django reusable app migrations separately. If the old migrations directory has been renamed to south_migrations correctly, you should see a similar successful output like in the image above.

If you have issues, try updating South to South 1.0 and removing old *.pyc files.

Finally, copy the reusable app directory back out of the test_project and over the old root project folder:

$ cp -r test_project/django_package django_package/

You’re now free to commit the changes to git and release a new version.

But We’re Still Not Finished

Documentation is a key part of any good software, and Django reusable apps are no exception. With the advent of Django 1.7, it is crucial that you provide documentation on setting up your reusable app with the new Django 1.7 and older versions. Don’t forget to be verbose about which commands are required for which versions. The documentation for Django-twilio provides details on Django 1.6 and lower:

as well as steps for Django 1.7:

For inspiration, I recommend reading the documentation page for django-twilio.

Uploading to PyPI

This guide assumes you’re well versed in uploading new versions of your Django reusable app to PyPI, the online repository of Python and Django reusable apps. You will now need to upload your updated Django reusable for other developers to take advantage of the new Django 1.7 updates. If you’re a bit rusty or unsure how to properly package and upload a new version to PyPI, there is a fantastic guide on Twilio by my fellow Pythonista Matt Makai. There is no strict rule on what type of version bump you’ll require, but I suggest a 0.N update as this change is significant. If you’re not sure check out the semantic versioning rules.

Final Steps

Today we just worked through what is needed to update your Django reusable app to support the new migrations framework included in Django 1.7. The additional features of Django 1.7 are game changing and are sure to make web application development with Django a smoother and easier experience. If this guide has been useful, or you wish to ask a question, get in touch with me at paul@twilio.com, on twitter, or leave a comment below.

Upgrading Your Django Reusable App To Support Django 1.7

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


iCrackedShotNothing gets an instant reaction from an iPhone owner like a cracked screen. They want their phone fixed, but don’t want to wait three days for a support appointment or send their phone off to be replaced. iCracked solves their problems on-demand, powering a network of technicians who meet the customers to repair their screen at their convenience.

As soon as the iPhone 6 was announced last week, iCracked was flooded with 10x the amount of repair calls and phone trade-in requests from customers. Thousands of customers were eager to repair their old iPhone and trade it in for cash to put towards a new one. With the giant spike in demand, iCracked used Twilio’s newly launched MMS to streamline repairs for customers and technicians alike (pictured right)

No two cracked screens are alike.  When technicians are driving from repair, to repair, having more insight on what type of repair they’re working with helps them plan the day’s repairs and set customer expectation. iCracked integrated Twilio MMS to allow customers to post a picture of their broken phone within the iCracked app.

Martin Amps, CIO of iCracked says that giving customers and technicians the ability to communicate visually, and easily “makes a huge difference” in customer satisfaction and making sure technicians can handle the wave of requests in the wake of the iPhone 6 release.

Just a few days after the MMS launch Martin and his team had their new photo feature up and running in hours. “Twilio made it very simple for us,” said Martin. After updating their API and a few lines of front-end display code, the app was ready for production.

Even though the iCracked team is busier than ever handling the new iPhone launch traffic, they’re still driving their business internationally. The team is working on opening offices in the UK and Germany.

You can learn more about iCracked by visiting their website here and reading their Twilio Case study here.

iCracked Rides The iPhone 6 Wave with Twilio MMS

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


facebook mobileOn Monday Facebook made an announcement around the relaunch of Atlas. It’s an exciting milestone for marketing technology for one primary reason: personalization.

Demand Side Platforms (DSPs) and Data Management Platforms (DMPs) have taken immense amounts of first and third party data, created interconnections between them, and enabled marketers to use that data to serve personalized marketing messages. The ultimate goal of these platforms is to foster true 1-to-1 marketing where every ad, promotion and customer touch point is individualized to the human (not device) on the receiving side of it.

The technology is getting better. It shows real promise. The proliferation of programmatic buying around display ads connected to mobile, social, apps, games and other channels is evidence of it. But the cross device/cross channel problem continues to be a tough nut to crack since many technologies rely on cookies that are inherently tied to a device, not a human being.

Enter Atlas, which has an incredibly powerful asset in the Facebook network. Being logged into Facebook much or most of the time on multiple devices takes the DMP story to the next level by providing accurate (not probabilistic) data around a person versus a device. This supercharges the ability to personalize marketing messages and optimize programs based on their impact, even as people switch devices, shift from online to offline, and do all of the other things common in today’s mobile world.

One of the most personalized touch points a brand can have with a customer is a phone conversation. It starts with leveraging the wealth of data we have on callers to provide unique, personalized phone numbers to a specific customer or visitor. When the customer calls, that information is inputted into a cloud-based routing engine that makes intelligent decisions regarding the optimal endpoint for that call. All of the information surrounding that experience can be factored in—campaign information, web session information, first party data from a CRM or analytics tool, or third party information from a myriad of data sources. All of this is used to get the call to the right person in an organization, and to then arm him or her with contextualized, personalized information to provide an amazing customer experience and close a sale.

At that point, the phone call itself becomes an additional data point marketers can use. For example, the data around what happens on a call—keywords and phrases mentioned on a call, responses to IVR questions, the quality or score of the call, and the like—can all be used to do additional segmentation and targeting.

The benefits are endless: personalized service, increased customer loyalty, improved brand awareness, and increased conversion rates at every step of the sales cycle.

This is not science fiction—this is all possible today. What’s exciting is the new capabilities Atlas promises to deliver take it a step further and give marketers even more transparency into the customer journey.

The post Facebook, Atlas, and the Future of Personalization appeared first on Ifbyphone.

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


September 30, 2014

Have you ever arrived at a movie, flight or concert and realized you’ve forgotten your paper ticket? Imagine how much worse it would be if you showed up at Willy Wonka’s front door, but forgot your golden ticket! To prevent an epic disaster such as this,  we’re going to build an app that delivers Willy Wonka’s golden ticket directly to your phone using MMS. All the Oompa Loompas have to do is scan it. Not Willy Wonka? Don’t worry, this code should be useful for any app or company that distributes tickets. Hopefully computers are more helpful with the golden ticket than last time.

Our Delicious Ingredients:

I Want It Now!

Some people just can’t wait to get what they want. If you want to deploy this app right now use the heroku button below:

Deploy

Laying Our Foundation with Laravel

Laravel is a PHP framework that let’s you write “PHP that doesn’t hurt”. If you haven’t used Laravel before, my fellow evangelist Kevin Whinnery wrote a great post showing you how to get started or you can check out the Laravel installation guide. Once you’ve got Laravel set up, let’s create a new laravel project called goldenticket:

laravel new goldenticket

Let’s hop into our goldenticket directory and start up the basic application to make sure everything looks good. Run the command:

php artisan serve

Now if you browse to http://localhost:8000/ you should see the following screen letting you know “You Have Arrived” and your Laravel project is setup correctly:

Before we start writing code, let’s update our configuration file to show debug info if we encounter any errors. Open up `app/config/app.php’ and update the debug option to true:

'debug' => true,

Now that we have our foundation in place, let’s make a simple form that we can use to send ourselves a new MMS ticket. Create a new view file in ‘app/views/’ called “home.blade.php”, and insert the following HTML:

<!doctype html>
<html>
  <head>
    <title>Golden Ticket Distribution</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
  </head>
  <body>
    <div>
      <h1>Golden Ticket Distribution</h1>
      <form method="POST">
        <input type="text" name="name" placeholder="Name" />
        <input type="text" name="phone_num" placeholder="Phone Number" />
        <input type="submit" name="submit" value="Send" />
      </form>
    </div>
  </body>
</html>

Here we’ve created a basic HTML page that contains a form we’ll submit to create a new ticket.  We’re also including bootstrap CSS to help make things look a bit prettier. By adding the .blade.php extension we’re making our view a Blade template. We won’t taking advantage of the templating till a bit later. Last, let’s make sure our route loads this view. You’ll already have a route for ‘/’ in app/routes.php so just update it to load our new view:

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

Visit http://localhost:8000 and you should now see our golden ticket distribution form:

Screenshot 2014-09-28 22.16.26

Generating QR Codes

Now that we have our Laravel foundation in place, let’s work on generating an image of our golden ticket. In this case our ticket will actually be a black QR code but that just doesn’t sound nearly as cool. We’ll be using the Endroid QRCode library to generate our QR code, so let’s install it using Composer.

composer require endroid/qrcode

First, we’ll create a new route that outputs our QR code image. To make our code a bit cleaner let’s import our QrCode class so we can instantiate it by name only. Open up your ‘app/routes.php’ file and add the following line right after your opening <?php tag:

use Endroid\QrCode\QrCode;

Now let’s add a new ‘/qrcode’ route after our ‘/’ route:

Route::get('/qrcode', function()
{
  $qrCode = new QrCode();
  $qrCode->setText("Golden Ticket");
  $image = $qrCode->get();
  $response = Response::make(
    $image,
    200
  );

  $response->header(
    'content-type',
    'image/png'
  );

  return $response;

});

We’re instantiating a new QR code and using the setText function to set the content we want encoded in the QR code. We then get our image and return it our response making sure we properly set the headers. Kick off your server using ‘php artisan serve’ and browse to http://localhost:8000/qrcode. You should see a beautiful QR code that looks like this:

We don’t want to just show the same QR code all the time though. Fortunately it’s easy to update this code to generate the code based on some data we pass in our query string. For our use case we’ll just be concatenating our name and phone number and base64 encoding it. Let’s update replace the first three lines of route with with the following code:

$name = Input::get('name');
$number = Input::get('phone_num');
$code = base64_encode($name . $number);
$qrCode = new QrCode();
$qrCode->setText($code);
$image = $qrCode->get();

We can now run our server and go to http://localhost:8000/qrcode?name=Charlie&phone_num=5555555 and see our dynamically generated QR code. Try switching the name and number data to see the code change.

Ultimately we’ll need Twilio to be able to access this image. As a result, if you’re running on localhost you’ll need a way to make that happen. Ngrok is a great tool for exposing your localhost to the outside world. If you haven’t used ngrok before you can kick off with our multi-platform or Windows focused tutorials.

Send MMS With Twilio

The next ingredient in our sweet new app is Twilio MMS. We were super excited to launch Twilio MMS on US and Canadian long codes two weeks ago. It allows you to send and receive multimedia messages of many different media types. This new API is just the ticket to securely distribute Wonka’s golden tickets in the form of an image sent over MMS. We’ll be using the Twilio PHP helper library to send our message. Let’s install it using Composer:

composer require twilio/sdk

Remember that form we created at the beginning of this post? We’re going to have that submit to itself to send our ticket. Currently our ‘/’ route only accepts GET requests, so let’s update it to accept GET and POST requests:

Route::match(array('GET', 'POST'), '/', function()

Inside our route let’s check to see if the form has been submitted. If it has, let’s instantiate a new instance of our Twilio helper library and send our message. Replace the code inside your route with this:

if(Input::has(‘submit’)) {
  $AccountSid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
  $AuthToken = "YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY";
  $client = new Services_Twilio($AccountSid, $AuthToken);

  $sms = $client->account->messages->sendMessage(
    "+15555555555", // Your Twilio Number
    Input::get('phone_num'),
    "Congrats! Here's your golden ticket.",
    "http://XXXXX.ngrok.com/qrcode?name=".urlencode(Input::get('name')) . "&phone_num=" . Input::get('phone_num')
  );

}

return View::make('home');

If you’ve sent SMS using the Twilio PHP helper library before this code should look familiar. We instantiate the library using our Twilio credentials. You can find these in your Twilio dashboard. Then we call sendMessage using our from number, to number and body of our message. Make sure to update the from number with your Twilio number. The new part for MMS is the last argument we pass. This is a URL to the media we want to send. This is the publicly accessible URL where Twilio can access our QR code image, make sure you update this to your URL.

After you’ve updated the code with your ngrok url, start your php server up:

php artisan serve

Load up the homepage and submit the form using whatever name you want and your phone number. Shortly, you should receive an MMS on your phone that looks something like this:

Putting the Packaging Together

Our app is now fully functional but all Wonka lovers know that you have to wrap your product up in nice packaging. Let’s do a few small updates to make sure our app is polished. First, let’s add an alert div that lets a user know that they’ve sent the message. Open your home view and add the following code right after the closing tag of your form:

@if(Session::has('alert'))
  <div>
    <h2>{{ Session::get('alert') }}</h2>
  </div>
@endif

This will check our session to see if we have an alert we need to show. If it does, we’ll show this div. We’ll be using flash data to store this alert. Flash data is session data that Laravel only stores for the next request. In our route, let’s add the flash data right after we send our message:

Session::flash('alert', 'Golden Ticket Sent!');

Now that we’re indicating to our user that form was submitted successfully, let’s also add some basic validation to indicate when something goes wrong. It’s our lucky day because Laravel makes validation easy. Let’s create a new validator right after we check that our form was submitted. We’re going to set name and phone_number fields to required:

if(Input::has('submit')) {
  $validator = Validator::make(
    array(
      'name' => Input::get('name'),
      'phone_number' => Input::get('phone_num')
    ),
    array(
      'name' => 'required',
      'phone_number' => 'required'
    )
  );

When you create a new validator you pass two arguments. First, an array containing the data you want to validate. Second, an array containing the validation rules for that data. Now that we have a validator we just need to check if it has failed and display some information about what failed to the user:

if($validator->fails()) {
  $messages = $validator->messages();
  Session::flash('alert', implode($messages->all('<li>:message</li>'))); 
} else { 
  // Code that sends our MMS

We’re using flash data again and reusing the alert div we already created to show our validation messages. Rerun your code and leave the ticket code and/or phone number blank. You’ll now receive a message letting you know that those fields are required.

There’s a lot more we can do with validation but this should be enough to get Grandpa Joe out of bed.

A World of Pure Imagination

We’ve now streamlined the operations at Wonka HQ with our MMS ticket distribution system. What you do next is up to your imagination! You could use a system like this at your next conference, hackathon or Willy Wonka-themed birthday party. Or maybe you own an airline and want to improve the way you distribute boarding passes.  Whatever you build, I’d love to see it. You can find me on twitter or e-mail.

How to Build an MMS Ticketing System Using PHP, Laravel and Twilio

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


French startup RogerVoice has created an Android smartphone app that it says will enable the more than 70 million people around the world who are deaf to hold two-way phone conversations in real time. The application uses speech recognition technology that automatically translates the phone conversation to text in real time. The entire conversion, from start to finish, […]

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


Act-On-IBP-LogoMarketing automation provides marketers with the ability to generate and manage their online leads in a revolutionary way, allowing for optimization of ROI, shorter sales cycles, and increased revenue growth. Act-On has taken the concept of marketing automation and perfected it for small and mid-sized businesses. The Act-On platform ties inbound, outbound, and nurturing programs together, across all digital channels with easy-to-use campaign functionality and program execution. Ifbyphone’s voice-based marketing automation platform provides marketers the ability to connect, measure, and optimize phone leads.

Today, at the SMX East conference in New York, Ifbyphone announced a new partnership with Act-On. By combining the capabilities of Ifbyphone’s Voice360 platform with Act-On marketing automation, Act-On users can now take full advantage of closed-loop marketing automation.

Combined Power of Calls and Clicks

Act-On provides outstanding insight into conversions that occur through digital channels, and by integrating with Ifbyphone, can now provide their customers with that missing piece of marketing data: voice. Phone calls have become more important than ever for modern businesses due to the explosive growth of smartphones and the amount of voice interactions they have stimulated. Smartphone users increasingly are interacting with marketing emails, websites, digital ads, and search inquiries by simply calling the number displayed on their phone. At this point, Ifbyphone picks up the lead with call tracking. This ensures that no lead slips through the crack and provides the conversion data necessary to improve lead generation, nurturing, analysis, and scoring.

Ifbyphone Call Data Merged With Act-On Web Data

By integrating Ifbyphone with Act-On, users will be able to achieve a more complete view into how marketing activities and website content are driving leads. With this new integration, you can view calls from your website in Act-On to improve lead generation, nurturing, and ROI:

  • Include phone calls as filters in Act-On funnels to understand how calls impact campaigns.
  • See which web pages and content drove a prospect to call you by including phone calls within Act-On visitor timelines.
  • Better identify hot prospects by including inbound calls in your Act-On lead scoring metrics.
  • Include inbound calls in custom workflows – for example, have callers automatically entered into email drip campaigns for nurturing.
Act-On-Timeline-with-IBP-Call

View phone calls in Act-On lead timelines to see what events
and content drove prospects to call.

Act-On-Funnel-with-IBP

Include inbound calls in Act-On funnels to see how they impact campaigns.

Act-On marketing automation combined with the power of Ifbyphone’s Voice360 campaign allows for unprecedented insight into the effect your marketing campaigns are having on your business bottom line.

Interested in learning more? Request a demo today. Or if you are attending the SMX East conference in New York this week, stop by the Ifbyphone booth (#427) at the event and speak to one our representatives.

The post Ifbyphone and Act-On Join Forces to Combine Call Tracking With Marketing Automation appeared first on Ifbyphone.

        

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


Logos of Top 200 US NewspapersIn the digital age, text-based content alone is not enough to satisfy the media consumer. The rise of powerful mobile devices with high-speed Internet access allows users to consume every type of content, on demand, anywhere they go. If you want to appeal to users nowadays, you need to offer variety in media content delivery. That means embracing video, audio, text to speech, social media, and all the other digital tools at your disposal.

It’s not just about new content, either. Repurposing existing content by presenting it in different formats is a great way to get the most mileage possible out of your archived content. Using reformatted content adds context to a story, supplementing existing information, or delivering the same story, but in new, interesting ways. Let’s take a look at some media content distribution tools that can boost digital appeal, and maximize the value media owners can get from every piece of content.

Video

These days, video content appears all over the web. Social sites have made it easier to directly embed video, and fast, reliable Internet connections have made buffering a thing of the past.

  • It’s one thing to read an incredible story, and quite another to see the story in action. The visual and audio components of video content give the consumer a more complete, vivid picture of the story.
  • Video content also makes for a great follow-up story on topics already covered. Video can be used to answer questions, advance the conversation, and add new details to existing stories.

Blogging

The term “blog” has come to mean a variety of different things, depending on which sites you frequent.

  • Blogs are a perfect place to put interesting facts that just missed the cut in the initial story, or reply to questions and comments from readers. A well-run blog can turn into a vibrant community where readers directly engage with media organizations.
  • Rethinking existing content by using blogs to break a long story down into short, manageable posts, catering to readers on the go.

Text to Speech

Some people don’t like to read, some don’t have the time, and some face accessibility challenges that keep them from reading. Text to speech allows content owners to reach larger audiences who otherwise wouldn’t be able to consume their content. While video, blogging, and audio all require a time investment, text to speech is an on-demand media content delivery service.

  • There’s no production time involved in offering text to speech. As soon as you publish a new piece of text-based content, your audience will have a one-click option to listen to your latest story.
  • Like video, text to speech is great for consumers on the go, allowing them to listen to latest news on the fly or save your content as an audio file and listen to it at their leisure on the device of their choice.
  • It’s not just about new content. Text to speech also works with your existing content, without any conversion work on your end.

Get Your Free Guide:
Everything You Always Wanted to Know about Speech-Enabling Websites

Download Your Free Guide

Image Credit: Lauren Michell Rabaino

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


September 29, 2014

Living in the greatest city in the world frequently causes me the burst out singing “I Love New York City”. One of my favorite things about living in New York is that each night the Empire State Building lights up in different colors. The tricky part is finding out *why* it lights up in those colors. It was this problem that inspired me to build an app that would send an SMS message every day and let me know the Empire State Building’s colors and the meaning behind them. In this post, I’ll show you how you can use Node.js, Firebase and Twilio to write your very own daily SMS reminder app.

Maybe you don’t need to know about the Empire State Building’s colors. Have no fear! You could build a daily SMS reminder app for many different purpos1es: word of the day, weather reports or even cat facts.

See It Live

Before we get started you can give my app a try. Just text ‘Subscribe’ to 718-690-7372 and every day at 6pm ET you’ll get a text message letting you know today’s colors and why. Don’t want to subscribe? You can text ‘colors’ to get the information on-demand.

List of Ingredients

We’ll be using a few tools to build this app. You’ll want to have these set up before you continue on:

  • Twilio: To send and receive SMS messages. Don’t have a Twilio account? Sign up for Free.
  • Firebase: A realtime database API. We’ll be using it to store the users who have subscribed to our service.
  • Node.js: A platform built on Chrome’s JavaScript runtime for easily building fast, scalable network applications.

Scheduling SMS Messages with Cron

To get started we’ll need to install a couple npm packages. We’ll be using the twilio package to send text messages and we’ll be using the cron package to schedule the time we want to send the text messages. You can install them by running the following commands:

npm install twilio
npm install cron

Create a new file called app.js and require the twilio and cron packages:

var twilio = require('twilio'),
client = twilio('ACCOUNTSID', 'AUTHTOKEN'),
cronJob = require('cron').CronJob;

Let’s write some code that sends a text message at 6pm every day:

var textJob = new cronJob( '0 18 * * *', function(){
  client.sendMessage( { to:'YOURPHONENUMBER', from:'YOURTWILIONUMBER', body:'Hello! Hope you’re having a good day!' }, function( err, data ) {});
},  null, true);

Wait, you’re probably wondering what the string we’re passing as the first argument to our cronJob is. That is a format specific to cron that let’s us define the time and frequency of when we want this job to fire. In this case, at 0 minutes 18 hours every day. This article does a nice job of breaking down cron format.

In the callback to our cronJob, we use the Twilio client library to send a message. We pass the to and from numbers and the body of the message we want to send.

Run this code and wait in anticipation for your text message. If it’s 10am, you probably don’t want to have to wait 8 hours to see if your code works. Just update the Cron format to send at an earlier time. Here’s a hint, to send at 10:13am you’d use this format: “13 10 * * *”.

You now have a basic version of this app, but you most likely don’t want to just send a message to yourself everyday. If you do then congrats! You’re all done! For the rest of us, we can make a couple small code changes to have this send to multiple phone numbers.

First, let’s add a new variable called numbers that contains the phone numbers we want to send messages to:

var numbers = ['YOURPHONENUMBER', 'YOURFRIENDSPHONENUMBER'];

Then let’s update the code in our textJob to loop over these phone numbers and send a message to them:

for( var i = 0; i < numbers.length; i++ ) {
  client.sendMessage( { to:numbers[i], from:'YOURTWILIONUMBER', body:'Hello! Hope you’re having a good day.'}, function( err, data ) {
    console.log( data.body );
  });
}

Receiving SMS Messages

Now that we’re sending an SMS message to different numbers at our desired time, let’s update this code to know when a users send a text message to our app. Twilio uses webhooks to let your server know when an incoming message or phone call comes into our app. We need to set up an endpoint that we can tell Twilio to use for the messaging webhook.

We’ll be using the Express framework to set up our node web server to receive the POST request from Twilio so we’ll need to install the express package. We’ll also be using the body-parser module so we’ll going to install that as well:

npm install express
npm install body-parser

At the beginning of our app.js file we’ll need to require express and initialize it into a variable called app. We’re also going to use the bodyParser middleware to make it easy to use the data we’ll get getting in our POST request.

var express = require('express'),
bodyParser = require('body-parser'),
app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
  extended: true
}));

We’re going to add a route for /message that responds with some TwiML. TwiML is a basic set of instructions you can use to tell Twilio what to do when you receive an incoming call or SMS message. Our code will look like this:

app.post('/message', function (req, res) {
  var resp = new twilio.TwimlResponse();
  resp.message('Thanks for subscribing!');
  res.writeHead(200, {
    'Content-Type':'text/xml'
  });
  res.end(resp.toString());
});

We use the Twilio node library to initialize a new TwimlResponse. We then use the Message verb to set what we want to respond to the message with. In this case we’ll just say “Thanks for subscribing!”. Then we’ll set the content-type of our response to text/xml and send the string representation of the TwimlResponse we built.

Finally, let’s set our server to listen on port 3000.

var server = app.listen(3000, function() {
  console.log('Listening on port %d', server.address().port);
});

Now let’s fire up our app:

node app.js

If you’re running this locally, you’ll want to make sure you’ve got ngrok running before you go to the next step. If you haven’t used ngrok before, my good buddy Kevin has put together a great tutorial to help you get started.

Now that we have our server running, we need to tell twilio to use this messaging url as a our Message Request URL:

Send an SMS message to your Twilio number and you should get a response back. If you don’t, take a look at the Twilio App Monitor to help determine what went wrong.

Saving Users in Firebase

We’ve setup a script that sends out a text message at the same time every day and we’ve given users the ability to send a text message into our app. There’s just one last thing left to do. We need to save our users’ information when they send a text to our app. We’ll be using Firebase as our datastore so we need to install the firebase node module:

npm install firebase

Now that we’ve installed the Firebase module let’s require and initialize it at the top of our app.js file:

var Firebase = require('firebase'),
usersRef = new Firebase('{FIREBASEURL}/Users/');

When you sign for a Firebase account they provide a url for your datastore, make sure you update this code to replace {FIREBASEURL} with this url.

Since we’ll be pulling the phone numbers from Firebase we’ll want to update our numbers variable to be an empty array and then fill it with info from the database. Firebase is a realtime database and built around the premise of subscribing to events as opposed to reading on demand. We’re going to subscribe to an update event whenever a new user is added:

var numbers = [];
usersRef.on('child_added', function(snapshot) {
numbers.push( snapshot.val() );
  console.log( 'Added number ' + snapshot.val() );
});

Now we need to add users to our database when they text in subscribe. Let’s revisit our message route to make this update:

app.post('/message', function (req, res) {
  var resp = new twilio.TwimlResponse();
  if( req.body.Body.trim().toLowerCase() === 'subscribe' ) {
    var fromNum = req.body.From;
    if(numbers.indexOf(fromNum) !== -1) {
      resp.message('You already subscribed!');
    } else {
      resp.message('Thank you, you are now subscribed. Reply "STOP" to stop receiving updates.');
      usersRef.push(fromNum);
    }
  } else {
    resp.message('Welcome to Daily Updates. Text "Subscribe" receive updates.');
  }

  res.writeHead(200, {
    'Content-Type':'text/xml'
  });
  res.end(resp.toString());

});

When the Twilio messages webhook triggers a new POST request to your server we include request parameters with information about the message. We’ll be using the Body parameter to examine the content the user texted in and the From parameter to determine the number they texted from. If they’ve texted in the word ‘subscribe’ and they’re not already in our database we’ll use the push function on our Firebase reference to add them.

Our app is now ready to go, let’s run it and give it a try:

node app.js

What Will You Do

We did it! Now that you’ve built a simple daily SMS reminder app it’s your chance to customize the daily message to whatever you want. Maybe a random Jack Handy quote, headline from the NY Times or a link to a hilarious gif. Once you’re done reach out to me on twitter or e-mail and let me know what you’ve made. I’d love to subscribe.

Send Daily SMS Reminders Using Firebase, Node.js and Twilio

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


A/B Testing StrategySuccessful B2B and B2C companies throughout the world are using A/B testing to optimize marketing campaigns and increase conversions. While it may seem like an easy concept to implement, A/B testing often takes time, resources, and a well-thought out strategy in order to reveal meaningful results.

A proper A/B test has two variations of a web page – the A and the B version. You drive traffic in even proportions to the control (A) and the variation (B). The B variation has sometimes simple, sometimes dramatic changes from the original. Some A/B tests have very minor changes, such as a different colored call to action button, while others have drastically different layouts or color schemes. Either way, an A/B test can validate whether or not the changes your team has made to web pages are having a positive impact on conversion rates.

Below are three of the most important elements of a powerful A/B testing strategy.

Variation and Defined Goals

Oftentimes having the resources to come up with variations of landing pages, ads, and other components of your website is the most challenging part of A/B testing. Once you have a dedicated design or web development resource, you can begin testing everything on your website. From copy to design, testing everything is the best way to understand what is effective for your business.

Below are screenshots of A/B test we are currently running. You’ll see the “Subscribe to RSS Feed” buttons are what we are testing. The goals we have defined for this test are as follows:

  • The original and variation must each have at least 100 unique visitors before a winner can be determined.
  • There must be a minimum of four conversions (on either variation) before a winner can be determined.
  • A conversion in this test is a click on the “Subscribe to RSS Feed” button.
  • We are also tracking the number of new signups we receive during this test to our RSS feed.

Original (A):

ab-testing-original

Variation (B):

ab-testing-variation

Once we have reached the amount of traffic and conversions defined for this A/B test, we will be able to determine which version of the RSS feed button works better at converting blog readers into blog subscribers on our site.

Accurate Data

Skewed data in an A/B test can impact the decisions your marketing teams makes about design and layout in the future, leading to poor conversion rates. Ensuring that the data you collect from your A/B tests is accurate is one of the most important aspects in determining meaningful results. Tracking the number of unique visitors to each page must not be skewed by visits to those pages made by your own team – to combat this, you can block specific IP addresses from being included in analytics data.

It is also important that any tests you make on your A/B tests do not get counted in the conversions you track towards your results.

One often-overlooked conversion metric in A/B testing is the phone calls your web pages generate. For example, if you are testing two versions of a paid search landing page you may want to include calls, along with form fills, as a conversion metric in determining a winner. A page may seem to be performing poorly at generating form fills, but perhaps instead of filling out the form people are picking up the phone and calling. If you aren’t using call tracking phone numbers on your original and variation page of your A/B test, you’ll never know which page is actually producing the higher number of conversions.

In the example below, we are testing variations of a paid search landing page. If you look in the upper right hand corner of each image, you’ll see that there are different phone numbers for each variation. Using call tracking and dynamic number insertion, we track the number of phone calls each page generates, in addition to the number of form fills each page receives.

Original (A):

lp-ab-testing-original

Variation (B):

lp-ab-testing-variation

Accurately tracking visits to each page running in an A/B test, along with the true number of conversions generated by each, is key to understanding and proving what works best in your marketing campaigns.

To learn more about tracking phone leads from A/B tests download the free guide, “Tracking Phone Leads: The Missing Piece of Marketing Automation.

Tools for Implementing Tests and Tracking Results

It can be difficult to implement and track the results of A/B tests without the proper tools. Splitting traffic evenly to the original and variation of an A/B test can be very tricky to do properly, and tracking the number of conversions to each is also challenging. That’s why having the proper tools to implement and track an A/B test is key to success.

At Ifbyphone we use Optimizely to structure many of our non-paid search related A/B tests. This testing platform enables you to run A/B tests with traffic split evenly between as many variations of a page as you wish to run (A/B/C/D: you get the picture). You then set up goals to track on each page – as many elements as you would like to track. If you don’t have the design or web developer resources we talked about earlier, Optimizely enables you to build a variation to your web pages within their interface. Optimizely also integrates with Ifbyphone’s call tracking technology, enabling marketers to include call conversion data within their Optimizely A/B testing platform.

Below is just one of the dashboards Optimizely offers per each A/B test you run.

Optimizely-Dashboard

One of the things I find most challenging in A/B testing is coming up with the next test to run. Leave your ideas for A/B tests in the comments section below. Thanks for reading!

The post Three Important Elements of a Powerful A/B Testing Strategy appeared first on Ifbyphone.

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


September 26, 2014

On Wednesday morning, September 24, 2014, the Twilio security team became aware of a code-injection vulnerability in bash dubbed CVE-2014-6271 and nicknamed “Shellshock.” While Twilio does not expose any of the services identified as vulnerable in this disclosure to the public Internet, our operations team responded immediately to upgrade affected bash versions across the Twilio infrastructure.  That effort was completed in the afternoon on Wednesday.

Our current reporting suggests it is unlikely Twilio infrastructure was exposed directly, however our security team is monitoring the situation closely as research continues to become available.  The Twilio Operations team will continue to monitor the disclosure and its related issue dubbed CVE-2014-7169 and take appropriate mitigation steps as they become available.

We urge our customers to mitigate this vulnerability by upgrading their bash installs.  Customers deploying services exploitable by the vulnerability without authentication such as Apache’s mod_cgi or dhcpd are suggested to upgrade their affected systems immediately.

This is an overview of the vulnerability, according to US-CERT/NIST:

GNU Bash through 4.3 processes trailing strings after function definitions in the values of environment variables, which allows remote attackers to execute arbitrary code via a crafted environment, as demonstrated by vectors involving the ForceCommand feature in OpenSSH sshd, the mod_cgi and mod_cgid modules in the Apache HTTP Server, scripts executed by unspecified DHCP clients, and other situations in which setting the environment occurs across a privilege boundary from Bash execution.

One test that has emerged in the research around this disclosure can be executed from a bash session of an affected host by executing the following:

env X="() { :;} ; echo vulnerable" /bin/sh -c "echo test"

If this command contains “vulnerable” in its return, the host is likely affected and should be upgraded.

For more information about this vulnerability, determining whether you are vulnerable, and to get started mitigating it, please visit the following resources:

As always, for any questions or concerns regarding this vulnerability, please reach out to help@twilio.com.

Security Update for CVE-2014-6271 (Shellshock)

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


Feature Friday is a bi-weekly blog featuring a new video brought to you by our Customer Success Team (CST). CST focuses on tutorials and feature enhancements that help our customers gain a clear understanding of how exactly they can make their Ifbyphone experience perfect. After all, we strive to be the easiest company you’ll work with!

There are several ways for callers to find you, but watch this video to learn which one is right for you. Ifbyphone even added a new look-up method to your Store Locator application a little while back to make it ultra easy and efficient for your callers. Whether it’s manual or automatic, we’ve got a solution for your Store Locator ready for use.

Have another idea for a video?  Tweet us at @IfbyphoneCST today!

The post Feature Friday: Store Locator Look-Up Methods appeared first on Ifbyphone.

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


September 25, 2014

I turned off GMail alerts on my phone a while ago. It just doesn’t make sense for my phone to beep every time someone comments on someone else’s status. That said, not all emails are created equal. There are some messages for which I would like to know right now when they show up in my inbox. SMS alerts are great for customized, urgent notifications like this.

This is a two part tutorial on how to build SMS email alerts in Ruby on Rails using the GMail API and Twilio. Part One is on how to authenticate your Rails app with a Google API using OAuth — and though our app uses GMail, the OAuth process is the same for all Google APIs, so all this will work for the Calendar API, the Drive API, etc. with only minor adjustments. Part Two will teach you how to retrieve emails from the GMail API and how to send SMS alerts using Twilio.

Google APIs and OAuth

The goal of this series is to write a script that checks our e-mail. To do that, we’ll first need to authenticate with Google via OAuth to access our account data. Even if you’ve never written an OAuth authorization before, you’ve undoubtedly used it. OAuth is what’s happening in the background when you encounter this screen:

Gmail OAuth Permission Dialog

From the developer’s perspective, the OAuth process looks like this:

  1. You set up an app within Google’s developer portal and tell it what APIs you’d like to use and Google gives you a Client ID and Client Secret (basically, a username and password).
  2. When a user signs into your app, your app redirects them to Google and passes along the client id/secret.
  3. Google asks the user permission to access their GMail data
  4. Google calls back to your app and sends a code which you can use, along with your credentials, to retrieve an access token with which you can make authenticated API calls.

Now you could write this OAuth process flow by hand, but why reinvent that rather complicated wheel? Omniauth is the de facto standard way to perform OAuth authentication in the Ruby world. Fortunately, there’s an add-on gem (“swappable strategy” in Omniauth speak) written specifically for the the Google API. In the rest of this post, we’ll talk about how to:

  • Create a Rails app with the the gems needed to connect to a Google API
  • Configure Omniauth to perform the Oauth dance with Google
  • Set up your app on the Google developer portal
  • Save and refresh your Google API access token

Sound good? Then let’s get started…

Create a Rails project for Omniauth and the GMail API

Open a terminal, navigate into your code directory and type:

rails new gmail-alerts
cd gmail-alerts

You won’t be needing most of the stock Rails gems, so replace your Gemfile with:

#Gemfile
source 'https://rubygems.org'
gem 'rails', '4.1.5'
gem 'omniauth', '~> 1.2.2'
gem 'omniauth-google-oauth2'
gem 'json'
gem 'sqlite3'

I’m using the most recent version of Rails at the time of writing, but all this should work with Rails 3 as well. Aside from Rails, the only gems here are Omniauth, the Google API add-on for Omniauth, JSON to parse the data that Google sends back to your app and sqlite to save your access tokens.

To install your gems, run:

bundle install

Now you’re ready to write some real code.

Google APIs and Omniauth

To set up Omniauth, create a new file at config/initializers/omniauth.rb:

#config/initalizers/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
  provider :google_oauth2, ENV['CLIENT_ID'], ENV['CLIENT_SECRET'], {
  scope: ['email',
    'https://www.googleapis.com/auth/gmail.readonly'],
    access_type: 'offline'}
end

PSA: any time you modify a file in the config/initializers directory, you must restart your Rails server for the changes to take effect.

Here’s what we’re doing there:

provider…
tells Omniauth to initialize the google_oauth2 strategy with a Client ID and Client Secret that you will get from the Google Developer Console shortly.

scope…
tells Google which APIs you want to access — in our case, the GMail API. If you omit the email scope you will receive an insufficientPermission error when you try to authenticate. It throws a similar error even if you’re trying to connect to, e.g., the Google Calendar API, so leave that email bit in there in addition to whatever Google API you’re connecting to.

access_type: ‘offline’
tells Google that you want to access the GMail account even if the account holder is away from the browser.

Omniauth is going to automatically create a route at localhost:3000/auth/google_oauth2  — no need to define it yourself in the routes file. When a user visits that URL, Omniauth redirects them to Google to authorize their account. After they grant permission, Google redirects them back to your app’s callback URL, and sends along an access token in the HTTP request parameters.

You do need to set up the callback url. Replace all of the default code in config/routes.rb with:

# config/routes.rb
GmailAlerts::Application.routes.draw do
  root to: 'sessions#new'
  resources :sessions, only: :index
  get "/auth/:provider/callback" => 'sessions#create'
end

Those first two routes set up a convenient but unnecessary way for us to kick off the authorization process. The third is the important one — it routes to the create action of the Sessions controller when Google makes an HTTP GET request to localhost:3000/auth/google_oauth2/callback.

Create the SessionsController at app/controllers/sessions_controller.rb:

# app/controllers/sessions_controller.rb
class SessionsController < ApplicationController
  layout false

  def new
  end

  def create
    @auth = request.env['omniauth.auth']['credentials']
  end
end

This is just a temporary controller to make sure that the authentication flow is working so far — we’ll update it in a moment. Create a simple view to kick things off at app/views/sessions/new.html.erb:

<%# app/views/sessions/new.html.erb %>
<%= link_to "Authenticate with Google!", '/auth/google_oauth2' %>

And, for the sake of instant gratification, create a view at app/views/sessions/create.html.erb to display the token information passed back to Omniauth from Google:

<%# app/views/sessions/create.html.erb %>
<% @auth.each do |key, value| %>
  <h1><%= key %> </h1>
  <p><%= value %> </p>
<% end %>

Make your callback URL publicly accessible

We’ve been talking about localhost:3000, but that URL doesn’t do Google any good — Google needs a URL on the public Internet that it can access after the authentication step. Now, you could just deploy your app to, say, Heroku, but that means redeploying every time you make a change which is so incredibly suboptimal and unfun that it’s not worth considering. One solution is to use tunneling software such as ngrok – here’s a quick post by Kevin Whinnery on how to set it up (it will take you about four minutes). Make sure you register for a free account so that you can use the incredibly helpful subdomain flag.

Once set up, start ngrok in a new terminal window on port 3000:

./ngrok -subdomain=example 3000

You should see something like:

ngrok

So long as ngrok stays running, Google can access your localhost:3000 via your ngrok subdomain. I’m going to use example.ngrok.com from here on out — replace that with whatever URL ngrok gives you.

Create a new app in your Google API console

Your Rails app is all set to receive an access token, now you need to set up your app in the Google Developer’s Console. Click Create Project and name your app Gmail Alerts. Google’s going to think for a few minutes. When it’s done, click into your project, click Enable an API and flip the toggles next to Gmail API, Google Contacts CardDAV API, and Google+ API. If you’re the tidy type, you can turn off the rest of the APIs. Or not. It’s cool either way.

google-apis-on

Now go to the Consent Screen section, under Credentials, and add you email address and a Product Name (perhaps ‘Gmail Alerts’). If you don’t, you’ll get a 401 invalid client error.

After that, create your Google OAuth 2.0 credentials:

  1. Click Credentials under APIs & auth on the left navbar
  2. Click Create new Client ID.
  3. In the popup window, select Web Application
  4. Enter http://example.ngrok.com under authorized javascript origins
  5. Enter http://example.ngrok.com/auth/google_oauth2/callback under Authorized Redirect URI
  6. Click the blue Create Client ID button

Google Developer Console - New app API settings

A Client ID and Client Secret appear on your dashboard:

google-secrets

Open a new terminal (don’t touch the one running ngrok!) and export these values as sessions variables:

export CLIENT_ID=123456789.apps.googleusercontent.com
export CLIENT_SECRET=abcdefg

Alternatively, to avoid retyping that everytime you start a new terminal session you can:

  • add those same two lines to your ~/.terminalofchoicerc and restart your terminal
  • drop those values into Rails 4.1’s settings.yml and use Rails.application.secrets.client_id instead of ENV[‘CLIENT_ID’] in your omniauth.rb.

What you shouldn’t do is hardcode these values and/or commit them to a Github repository… that’s bad form.

Alright, let’s try it out:

  • Start your Rails server from the same terminal window in which you set your environment variables
  • Visit http://example.ngrok.com in a broswer
  • Click the authorization link
  • Say ‘yes’ to The Google

Google will redirect back to your callback URL. If you see something like this:

Output from Omniauth connecting to the GMail API

… then you have successfully performed an OAuth authorization with GMail. Now, if you want to do anything with that accomplishment, you’re gonna have to save some of that data Google just sent you. (And if everything seems to work but you don’t see a refresh_token, read the part in the next section about revoking app access.)

Save the OAuth tokens

The three most important bits of information that Google sent back to your app are found in:

request.env['credentials']['access_token']
request.env['credentials']['refresh_token']
request.env['credentials']['expires_at']

That access token is what you’ll use to make requests against the GMail API later on, however, it’s only good for 60 minutes. Once it expires, you’ll request a new one by sending Google the refresh_token along with your client_id and client_secret. Unfortunately, Google only sends the refresh token once so you have to save it the first time you authorize your app… and we just blew that opportunity. Head over to your Google Account Permissions and revoke access to your Gmail Alerts app. We’ll be ready next time.

Let’s first save those tokens and the expiration time. Initialize your database and create a Token ActiveRecord model. From the terminal:

rake db:create
rails g model Token access_token:string refresh_token:string expires_at:datetime
rake db:migrate

Update SessionsController to save the tokens that Google sends to the callback url:

# app/controllers/sessions_controller.rb

class SessionsController < ApplicationController
  layout false

  def new
  end

  def create
    @auth = request.env['omniauth.auth']['credentials']
    Token.create(
      access_token: @auth['token'],
      refresh_token: @auth['refresh_token'],
      expires_at: Time.at(@auth['expires_at']).to_datetime)
  end

end

Revisit example.ngrok.com and reauthorize your account. Check your database and ensure that a new record was created in your tokens table with access_token, refresh_token, and expires_at all populated. An easy way to do this is via the Rails console:

puts Token.last.inspect

Refresh your Google API Access Token

Now you’ve got an access token, but it’s only good for 60 minutes (probably 57 minutes by this point). Unfortunately, neither the Google API gem nor Omniauth have a built in method to refresh access tokens so you’re going to have to write (copy) that yourself. Replace your token model at app/models/token.rb with the code below, then we’ll talk about what it all does:

# app/models/token.rb

require 'net/http'
require 'json'

class Token < ActiveRecord::Base

  def to_params
    {'refresh_token' => refresh_token,
    'client_id' => ENV['CLIENT_ID'],
    'client_secret' => ENV['CLIENT_SECRET'],
    'grant_type' => 'refresh_token'}
  end

  def request_token_from_google
    url = URI("https://accounts.google.com/o/oauth2/token")
    Net::HTTP.post_form(url, self.to_params)
  end

  def refresh!
    response = request_token_from_google
    data = JSON.parse(response.body)
    update_attributes(
    access_token: data['access_token'],
    expires_at: Time.now + (data['expires_in'].to_i).seconds)
  end

  def expired?
    expires_at < Time.now
  end

  def fresh_token
    refresh! if expired?
    access_token
  end

end

That a lot to take in all at once, but each method is pretty straightforward:

to_params
Converts the token’s attributes into a hash with the key names that the Google API expects for a token refresh. For more information on why these are the way they are, check out the docs for how to refresh a Google API token.

request_token_from_google
Makes a http POST request to the Google API OAuth 2.0 authorization endpoint using parameters from above. Google returns JSON data that includes an access token good for another 60 minutes. Again, the the Google API docs have more information on how this works.

refresh!
Requests the token from Google, parses its JSON response and updates your database with the new access token and expiration date.

expired?
Returns true if your access token smells like spoiled milk.

fresh_token
A convenience method to return a valid access token, refreshing if necessary.

One last note about the tokens table: for simplicity’s sake I wrote this tutorial to only work with a single email address but it won’t be difficult to add support for multiple accounts if you build a service for multiple users. Google sends the users’s email address to the callback url. Add an email column to the tokens table, and save the email address in sessions#create, then retrieve the corresponding token when needed.

However, for the purpose of this tutorial, your token will always be found at Token.last. To make sure this all works, open a Rails console and type:

t = Token.last
puts t.access_token
t.refresh!
puts t.access_token

You should see two different values. Then type:

t.fresh_token

And you should see the same value as t.access_token. Now whenever you’re trying to pull data from a Google API, you don’t have to worry if the token is expired or not – token.last.fresh_token takes care of that automagically.

Onward!

You can now authorize Rails your app with any Google API — pull appointments from Google Calendar, edit documents on Google Drive, retrieve pictures from Google+. Opportunities abound!

In Part 2, we’ll learn how to get emails from the GMail API and send SMS alerts using Twilio. If you’ve got any ideas for integrating Google and Twilio, or have any questions, hit me up at gb@twilio.com or on Twitter at @greggyb.

Authorize Your Rails App with a Google API and Twilio SMS

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


social media weekSo much of what gets discussed at Social Media Week is “fun stuff”: how to engage your customers with exciting new interactive campaigns, how to use the latest technology, etc. That’s why we decided to attend an event that was a little more serious, focused on something that marketers know the importance of but often overlook: stats. We sat with Pat Kopisckie from HY Connect and Greg Kirkorsky from STATS and learned how even though a picture is worth a thousand words, stats might be worth more.

Data Drives Us

Data drives almost everything we do, says Kirkorsky. Whether it’s looking at the stock market or deciding whether to carry an umbrella based on weather information, data affects the decisions we make daily. We’ve seen the way data has become the must-have element of any successful marketing campaign: from the popularity of Nate Silver to the rise of Moneyball, we see that 2009 Google Chief Economist Hal Varian was correct when he said “The sexy job in the next ten years will be statisticians.”

Stats Have Multiple Personalities

While I mentioned above that stats are the more serious side of social media marketing efforts, they don’t necessary have to be. While statistics bring credibility to the content you create, they can also contribute to a nice visual experience. Infographics, for example, which are some of the most shareable pieces of visual marketing incorporated into social media campaigns, are generally built on stats. Every great infographic is pieced together with data transformed into a visual.

Even infographics can be stale when poorly executed, but they don’t have to be. Kirkorsky cited an infographic Netflix created based on “fun” data about people who “cheat” on their significant other, streaming the shows they watch together when they’re apart. The infographic wasn’t necessarily for prompting a purchasing decision based on it alone, but it was a great shareable asset that generated a lot of conversation for Netflix. Call that a social media win.

Infographics, Listicles, and Kinetic Text Videos

Infographics are the go-to content for many marketing teams: they’re 30% more likely to be read than a text article, after all, and brands that use them see significantly more web traffic. A plus about infographics is that they can be designed with social media consumption in mind, arranged in bite-sized arrangements so that the different sections can be easily viewed on the screen of a smartphone.

Listicles, too, are a great way to incorporate data into a digestable format. Look at BuzzFeed: they’ve managed to generate sky-high traffic merely by aggregating data into fun, shareable listicles. While your content may not be “10 Ways Cats Are Man’s Real Best Friend,” you can find a way to make the listicle format work for you.

Kopisckie also discussed the emergence of kinetic text videos. You’ll know it when you see it: we made one! These videos are a great way to appeal to visual learners and provide a big chunk of information about your service or product while still making it…pretty. More than 1 billion unique users visit YouTube each month, but only 2% of the top 5,000 channels are brands, so there’s a lot of room for elbowing in.

Content may be king, but stats and data are the throne. Let the two work together and your marketing is guaranteed to be royal.

The post Social Media Week Chicago: How to Integrate Stats into Your Marketing appeared first on Ifbyphone.

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


September 24, 2014

Share This: Cloud services offer infrastructure without administration, predictable costs and lower capital risk. But getting to that promised land from your island of in-sourced […] …read more

The post Moving to Cloud-Based Services appeared first on Plum Voice.

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


Oracle OpenWorld and JavaOne are coming to San Francisco September 28th – October 2nd, bringing leading software companies together for four days. Twilio partners BlueLeap, OpenMethods, and SureShot are joining us in the booth at OpenWorld to share their Oracle-integrated communications solutions with you. We’ll be giving away Twilio-Powered Weekends, hosting talks, giving tutorials, and more. Get the full scoop below.

Where To Find Twilio and Partners

OpenWorld Expo
Booth #637
Moscone South

JavaOne Expo
Booth #5400
Hilton Hotel

OpenWorld Expo
Stop by our booth and learn how you can use Twilio to better connect with your customers, suppliers, and employees. We make it possible to add voice, SMS, and MMS to Oracle Marketing Cloud, Sales Cloud, and Service Cloud. Build a full communications solution from the ground up or leverage one of our partners if you’re looking to buy or integrate. Below you can learn more about the Twilio Partners who will be demoing their Oracle integrations in our booth.

JavaOne
Come say hi to your friendly Twilions at the JavaOne Expo.

  • Together with our friends from Spark, we will be showing off an SMS-powered LED Torch.
  • We will be giving live demos on how to use Twilio in your Java environments.
  • Find Twilio-powered devices in the Java IoT Showcase

Twilio Partners

  • OpenMethods

OpenMethods will be demoing their PopFlow Studio visual designer, showing you how to create apps using a drag and drop interface without writing any code.

  • BlueLeap

BlueLeap enables you to quickly add voice and SMS into your business processes, automating communication and reducing customer wait time via the BlueLeap Connector.

  • SureShot

SureShot Media specializes in bringing companies’ marketing ideas to life. They use Twilio to build apps, content, and user engagement for companies of all types.
Learn more about the Twilio Partners here.

Win A Twilio Powered Weekend

Together with Twilio partners BlueLeap, OpenMethods, and SureShot, we will be giving away three Twilio-Powered Weekends at Oracle OpenWorld – your transportation, hotel, dining, and shopping needs are covered!

The Twilio-powered weekend includes $500 of Uber credit, $600 of AirBnB credit, a $400 OpenTable gift card, and a $350 GILT gift card. You pick a destination then ride in style, stay in a swanky local flat, make reservations at the best restaurants in town, and splurge on some new clothes for the weekend. Stop by the Twilio booth at Oracle OpenWorld to enter to win a Twilio-Powered Weekend.

Terms and conditions apply.

Don’t Miss These Talks

  • Learn How to Create Your Own Java and Internet of Things Workshop: Our friends from the Oracle AppsLab will show you how to build an interactive IoT platform with Rasberry Pi and Embedded Java. The platform connects a series of inputs and outputs that can range from sensors connected to the Rasberry Pi to tweets and hashtags to SMS and Voice calls from Twilio. In their words: “Expect to play with robots, lights … and come prepared to have some fun.”
  • Mon, Sept 29, 4pm, Parc 55 – Powell I/II

  • Achieving Excellence in Customer Service: In this panel, BlueLeap CEO Raleigh Burgess, IDP Education Client Relationship Manager John Green, and Oracle Service Cloud VP of Product Management Stephen Fioretti will will show you how BlueLeap worked with IDP to design a new service approach to meet their agents’ requirements and open new communication channels to engage their customers.
  • Wed, Oct 1, 2pm, Moscone West – 3001

    We’ll see you at Oracle OpenWorld!

     

    Find Twilio At Oracle Open World

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


    When I get together with my siblings (one younger sister, and two little brothers- 12 and 9) I tend to come up with crazy ideas. A couple years ago in Northern California I was visiting my little brothers and had the grand idea to create a scavenger hunt for them when they woke up in the morning. Of course, this blew their mind and we had a great time. So, when I ended up visiting for an extended period a couple months ago, I decided it was time to reprise the scavenger hunt– MMS Style.

    Hunt Photo

    Left: Simon showing one of the picture clues. Middle: Brenden trying to find a keyword. Right: Jacob pondering the meaning of the clue he just received.

     

    How will the game work?

    There are lots of ways to set up a scavenger hunt. You could take pictures of locations, and then ask people to send pictures back at those locations. But then you have to figure out how to verify the location, which would be tricky. In this case, the way I verified that the player found the location was to plant a keyword somewhere in the vicinity of the location.

    Image of Keyword

    Most of the keywords I wrote were 80’s bands since I wanted keywords that the boys were unlikely to know or guess :) If you are building this for a younger audience, definitely be sure to make the keywords easier.

    Once the player finds the keyword, they text it back to the number, which checks it and then sends the next clue. Here is a diagram of the entire interaction:

    diagram.png

    If you’d like to interact with the demo app you can text 619.555.5555. Seems pretty simple right? Now let’s build the dang thing.

    Setting Up

    It might make sense to download all of the sample code and follow along in your IDE of choice. If you’d like to checkout the code you can get it here: Github

    Before we can start building an interactive scavenger hunt, 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, 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 “scavenger-demo”. Change into this directory – we’ll put all our application code here. Next, let’s install some Ruby gems (in the github directory I use bundler and a gemfile)

    [sudo] gem install twilio-ruby sinatra shotgun
    [sudo] gem install haml sanitize

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

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

    For this application, we will be using the lightweight Ruby web framework Sinatra. 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.

    Now that our project is all set up, let’s write some logic to manage the scavenger hunt.

    Server-side game mechanics

    I chose to use Sinatra as the scavenger hunt Server. Sinatra allows us to write a simple one-page Ruby file that runs the whole shebang. In this case our server only needs to do two things:

    • Send and Receive texts and parse the Body
    • Maintain a database of Players to track clues completed

    First let’s setup our Sinatra file with all of the requirements. Github ➭

    require "bundler/setup"
    require "sinatra"
    require "data_mapper"
    require "twilio-ruby"
    require "sanitize"
    require "haml"
    
    # Load up our necessary requirements before each function
    before do
      @game_commander = ENV['SCAVENGER_NUMBER']
      @client = Twilio::REST::Client.new ENV['TWILIO_ACCOUNT_SID'], ENV['TWILIO_AUTH_TOKEN']
    end

    Here we include our requirements and initialize a Twilio client that will handle all of our Message sending and receiving.

    Next we need to create a database to store some players in, and in this case we’re going to use Data Mapper. I like using Data Mapper (DM) for small projects like this since I don’t need to write any migrations and I can define the model once in ruby and datamapper will create the necessary layout in the datastore. It also works with a bunch of different datastores, in this case we’ll be using Postgres.

    # Using DataMapper for our psql data manager
    DataMapper::Logger.new(STDOUT, :debug)
    DataMapper::setup(:default, ENV['DATABASE_URL'] || 'postgres://localhost/YOUR_DB_NAME')
    
    class Player
      include DataMapper::Resource
    
      property :id, Serial
      property :phone_number, String, :length => 30, :required => true
      property :name, String
      property :current, String
      property :status, Enum[ :new, :naming, :hunting], :default => :new
      property :missed, Integer, :default => 0
      property :complete, Integer, :default => 0
      property :remaining, Object
    
    end
    
    DataMapper.finalize
    DataMapper.auto_upgrade!

    The only thing we actually need from the player to start is a phone number, so we define it as required. This will prevent us from creating a model without a phone number. Also notice that status is an enum, this allows us to quickly access this property by name even though it’s stored as an int in the DB. The Player.status needs to be 0 or ‘new’ when we begin.

    Lastly we call two magical methods on datamapper, finalize and auto_upgrade!. Finalize checks the models for validity and initializes the necessary properties, while auto_upgrade! runs any migrations needed to update the datastore while not removing any existing entries. Great, so we have somewhere to store the players, now let’s build the interface for the players.

    Sending picture clues and checking their validity

    First we need to define a set of clues that the user will receive as the hunt progresses. Let’s store these inside a Ruby Hash for easy access throughout the code.

    $CLUES = {
      "clue1" => {
        "keyword" => 'boygeorge',
        "riddle" => 'Humdinger of a clue',
        "url" => 'https://dl.dropboxusercontent.com/u/123971/scavenger-hunt/clue01.jpg'
      },
      "clue2" => {
        "keyword" => 'scumbucket',
        "riddle" => 'Let this clue float in your head for a bit.',
        "url" => 'https://dl.dropboxusercontent.com/u/123971/scavenger-hunt/clue02.jpg'
      },
    }

    The riddle will accompany the image so that you can give your hunters a little more context for what they might be looking for… in my case some of the clues were pretty abstract so it was important to include this. You could drop the riddle and just send pictures however.

    Init the player and kick-off the hunt!

    When I kicked off my scavenger hunt I got all the kids in a room and told them to type the number into their messaging app but not send anything. Then on my mark they all texted “let’s hunt!” to the number I gave them. When they texted what actually ended up happening is my Twilio number made a request to my master route which then kicked off the game.

    The first thing it did was create our players in the database and then prepare to listen for incoming texts.

    get '/scavenger/?' do
      # Decide what do based on status and body
      @phone_number = Sanitize.clean(params[:From])
      @body = params[:Body].downcase
    
      # Find the player associated with this number if there is one
      @player = Player.first(:phone_number => @phone_number)
    
      # if the player doesn't exist create a new player.
      if @player.nil?
        @player = createPlayer(@phone_number)
      end
    
      # more code here ...
    end

    At the beginning of our master route ‘scavenger/’ we’ll throw the phone_number into a global var so that other methods can access it. Next the router checks to see if this user exists by the phone_number, and if she doesn’t exist it creates a new one.

    def createPlayer(phone_number)
      clues = ($CLUES.keys).join(',')
      player = Player.create(
        :phone_number => phone_number,
        :remaining => clues,
      )
      player.save
      return player
    end

    Now that we have a player we can send them their first clue.

    Send a picture clue

    First we need to select a clue. When we created the user we also stored an array of clue keys (‘clue1’, ‘clue2’, etc) under their profile that shows us which clues are remaining to be sent. Now all our program needs to do is choose one and send it.

    # more code here...
      sendNextClue(@player)
    end

    def sendNextClue(user)
      remaining = (user.remaining).split(',')
      next_clue = remaining[rand(remaining.length)]
    
      clue = $CLUES[next_clue]
      sendPicture(@phone_number, clue['riddle'], clue['url'])
    
      @player.update(:current => next_clue)
    end

    Aside from selecting a random clue, this snippet also stores the current clue that the player is hunting and calls sendPicture():

    def sendPicture(to, riddle, mediaUrl)
      message = @client.account.messages.create(
        :from => ENV['SCAVENGER_NUMBER'],
        :to => @phone_number,
        :body => riddle,
        :media_url => mediaUrl,
      ) 
      puts message.to
    end

    Notice we’re using our handy global objects @client and @phone_number. By using the Twilio Ruby library we can send an MMS by using the same messages.create() method we always used to send SMS, we just include a media_url parameter and it’s a picture message  (as long as the phone number is MMS enabled).

    Okay, to recap our user has been created in the database, along with some state about where in the game she is and fired off the first picture clue. As far as we know the hunt is on and we should probably setup something to listen for those incoming texts.

    Finding clues!

    If you remember, the way this particular scavenger hunt works is by sending the user a picture clue and then waiting for them to send a keyword back. This keyword is hidden somewhere around where the picture was taken. This could be on a conference table, written on the back of playing cards, or tattooed on the belly of a miniature pig. However it’s delivered, we need a way to verify that the keyword sent is correct.

    Next, inside of our master router ‘/scavenger/?’ we need to add these lines:

    # check what the current clue is
          current = @player.current
          clue = $CLUES[current]
    
          # Turn the remaining object into a proper array, to remove
          # the correct clue from it later.
          remaining = (@player.remaining).split(',')
    
          if @body == clue['keyword']
    
            # Score this point
            complete = @player.complete++
    
            # Remove the clue that was just completed
            remaining.delete(current)
    
            # UPDATE THE player
            @player.update(:complete => complete, :remaining => remaining.join(','))
    
            # If the player has no more clues, they are done. Send a nice wrap-up message.
            if remaining.length == 0
              output = "Congratulations #{@player.name}! You've finished the game and found #{@player.complete} clues! Your fastest time was #{@minutes}, which is pretty good! Now just wait for the others to finish and a special rewards ceremony."
            else
            # Other wise send the next clue
              output = "Well done #{@player.name}! You've just found a treasure! Now here's the next clue!"
    
              # Get next clue and send it.
              sendNextClue(@player)
            end
    
          else
            # Player missed one, increment
            missed = @player.missed++
            @player.update(:missed => missed)
    
            output = "That's not completely right (in fact it's wrong). Here's another clue, see if you can find it."
    
            # Get next clue and send it.
            sendNextClue(@player)

    You can view the master route in it’s entirety here: Github ➭.

    Okay we are mostly done with the heavy lifting code wise, now we just need to connect it all to Twilio and we’re ready to hunt.

    Connecting to Twilio

    Now that we have our master route, we need to tell Twilio to send all of our messaging traffic to that endpoint. Once you login to Twilio go to your numbers portal. Once you’re there you can click on the number you provisioned for the scavenger hunt and point it to your server. It should look like this:

    Screen Shot 2014-09-22 at 7.20.07 PM.png

     Great you’re all ready! Now all you have to do is arguably the hardest part– build the actual scavenger hunt!

    Building the Arena

    If you’re me and you’re building this for some exceptionally clever young men, you should probably take the weirdest pictures possible and hide them in the hardest spots imaginable.

    blog-clues

    Left: Brenden looking for a clue hidden inside the head of a hose attachment. Right: one of the actual picture clues.

    But it might be a better approach to take pictures of obvious landmarks, with clear instructions. That way your participants are guaranteed to enjoy themselves.

    Happy Hunting Compadres

    Now you are competently armed with the tools to write an interactive scavenger hunt using Twilio and Sinatra. Feel free to tweak the experience to your liking, in fact you can checkout a more “game-ified” version on a branch of the repo I shared earlier, including injuries, fastest hunter and a console dashboard. Some other improvements would be:

    • 2-factor auth
    • Picture submission in place of keywords
    • A live dashboard of all the teams/players progress
    • Virtual “pitfalls” that players can use on one another

    I’ve always loved scavenger hunts, and I would love to see a whole new generation of hunts arise with all of the technology we developers have at our fingertips. If you have ideas about the next great MMS hunt, or you just want to wax poetic about the illustrious brilliance and inevitable demise of Steve Irwin, shoot me an email or find me on twitter.

    Until next time, happy hunting!

    How to Build a Picture Scavenger Hunt Using Twilio MMS, Twilio and Sinatra

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


    smartphone userProgrammatic advertising’s booming entry into the media buying market has revolutionized the way we can purchase digital advertising. It is projected that by 2018, programmatic will account for 50% of all digital ad sales. The ability to automate your media buying while still driving quality leads furthers the ever-present need to prove and manage the value of your advertising choices.

    With programmatic a new digital advertising landscape is emerging. Which, tied to the growing number of people who will be viewing programmatic advertising on their mobile devices, will ultimately be directing more calls to your business. Tracking and managing these calls is vital to the success of your programmatic advertising.

    Not exactly sure what programmatic is? Let’s breakdown some programmatic basics, how it is already being embraced, and the implication it has on marketers’ advertising decisions.

    Programmatic 101

    Programmatic advertising can be summed up in three words: automated ad buying. The decision-making process is taken directly out of the hands of humans and placed instead with artificial intelligence technology. Parameters are created that enable you to specify price, network reach, and targeted audience preferences, before software algorithms are used to automate and optimize the buying process.

    At its core, programmatic advertising is all about data. It uses data to guide the automated buying process and creates data through campaign results. More data allows for greater systematic customization of campaigns, with programmatic buying taking a large portion of the human factor and manual work out of the traditional optimization process.

    Its growing popularity is helping marketers shift more ad dollars to digital as well as create efficiencies in their overall media buying process. This is a key way in which call tracking can help marketers make decisions about how to allocate their digital investments.

    What’s in It For Me?

    Taking advantage of programmatic advertising enables marketers to build more well-rounded and effective advertising strategies. While not necessarily cheaper, programmatic makes your dollars work more efficiently and ultimately allows you greater range in your overall investment. Campaigns gain:

    • Speed: bringing efficiency to your ad buying process
    • Data: making data work harder for your business
    • Optimization: enabling up front, automatic campaign customization
    • Resources: freeing up your employees’ (or agency’s) time to spend more productively

    Programmatic strategy is only the first half; voice-based marketing automation tools will help you manage the conversations with your customers that come next. Interactive voice response (IVR) can help you qualify customers and intelligent call routing offers your business flexibility in routing calls based on your needs.

    The Proof is in the Pudding

    According to a recent AOL survey, 76% of brand marketers stated their companies are buying display ads through programmatic buying. The growing proof is evident: several prominent companies can be seen actively embracing this new form of media buying, through both their increased emphasis on the tool and the growth in sales they’ve already experienced:

    • Procter & Gamble wants 75% of their digital media to be bought programmatically by the end of 2014 (AdAge)
    • AOL’s ad business was up 20% in Q2 2014 due to its programmatic ad buying platform (AdWeek)
    • MagnaGlobal has stated they plan to automate 50% of their clients’ budgets by 2016 (AdAge)
    • Nearly all (98%) of U.S. publishers are exploring a programmatic marketing approach (IAB)

    Programmatic advertising ultimately means a new way to interact with your customers. Combine that with 53% of brands and agencies that plan to increase programmatic spending specifically in mobile within the next six months (AOL Platforms study) and the result is a mobile audience that is increasingly exposed to your message. A valuable audience with “click to call” and “call us now” features at their fingertips. Make sure you know how they are engaging with your advertising and that you are having the most successful conversations as a result.

    To learn everything you need to know and more on the ways VBMA can help your programmatic advertising, you can download the white paper, The Definitive Guide to Voice-Based Marketing Automation.

    The post Programmatic Advertising: Why Tracking and Managing Calls Is Critical to Its Success appeared first on Ifbyphone.

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


    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


    Last updated: October 02, 2014 12:01 PM All times are UTC.
    Powered by: Planet

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