The Subscriber model

This is the endpoint that will be called every time our application receives a message.

It checks if the command sent in the message is one of the commands that we are expecting. Depending on that it returns a message formatted in TwiML - either a confirmation or a helpful message with our legal commands.

require'sinatra'require'data_mapper'require'json'require'rack/contrib'require'tilt/erb'require_relative'model/subscriber'database_url='postgres://postgres:postgres@localhost/marketing_notifications'DataMapper.setup(:default,database_url)DataMapper.finalizeSubscriber.auto_upgrade!use::Rack::PostBodyContentTypeParserSUBSCRIPTION_MESSAGE='You are now subscribed for updates.'UNSUBSCRIPTION_MESSAGE=%( You have unsubscribed from notifications. Test 'add' to start receiving updates again.)INSTRUCTIONS_MESSAGE=%( Thanks for contacting TWBC! Text 'add' if you would want to receive updates via text message.)get'/'doerb:index,locals:{message:nil}endpost'/messages'doSubscriber.subscribed.eachdo|subscriber|subscriber.send_message(params['message'],params['image_url'])enderb:index,locals:{message:'Messages Sent!!!'}endpost'/subscriber'docommand=params[:Body].downcaseifvalid_command?(command)subscriber=create_or_update_subscriber(params)ifsubscriber.subscribedformat_message(SUBSCRIPTION_MESSAGE)elseformat_message(UNSUBSCRIPTION_MESSAGE)endelseformat_message(INSTRUCTIONS_MESSAGE)endenddefsubscription?(command)command=='add'enddefvalid_command?(command)command=='add'||command=='remove'enddefformat_message(message)response=Twilio::TwiML::MessagingResponse.newresponse.message(body:message)response.to_senddefcreate_or_update_subscriber(params)subscriber=Subscriber.first(phone_number:params[:From])command=params[:Body].downcaseifsubscribersubscriber.update(subscribed:subscription?(command))subscriberelseSubscriber.create(phone_number:params[:From],subscribed:subscription?(command))endend

app.rb

SMS and MMS Marketing Notifications

On an incoming message, we look in the database for a matching number. If there isn't one, we create a new Subscriber. If it does, we validate the command from the message body and send an appropriate TwiML response.

And that's all we want at this step! We've created a Subscriber model to keep track of the people that have requested our messages. We also have saved their information on the database after receiving a text message with an 'add' command.

require'sinatra'require'data_mapper'require'json'require'rack/contrib'require'tilt/erb'require_relative'model/subscriber'database_url='postgres://postgres:postgres@localhost/marketing_notifications'DataMapper.setup(:default,database_url)DataMapper.finalizeSubscriber.auto_upgrade!use::Rack::PostBodyContentTypeParserSUBSCRIPTION_MESSAGE='You are now subscribed for updates.'UNSUBSCRIPTION_MESSAGE=%( You have unsubscribed from notifications. Test 'add' to start receiving updates again.)INSTRUCTIONS_MESSAGE=%( Thanks for contacting TWBC! Text 'add' if you would want to receive updates via text message.)get'/'doerb:index,locals:{message:nil}endpost'/messages'doSubscriber.subscribed.eachdo|subscriber|subscriber.send_message(params['message'],params['image_url'])enderb:index,locals:{message:'Messages Sent!!!'}endpost'/subscriber'docommand=params[:Body].downcaseifvalid_command?(command)subscriber=create_or_update_subscriber(params)ifsubscriber.subscribedformat_message(SUBSCRIPTION_MESSAGE)elseformat_message(UNSUBSCRIPTION_MESSAGE)endelseformat_message(INSTRUCTIONS_MESSAGE)endenddefsubscription?(command)command=='add'enddefvalid_command?(command)command=='add'||command=='remove'enddefformat_message(message)response=Twilio::TwiML::MessagingResponse.newresponse.message(body:message)response.to_senddefcreate_or_update_subscriber(params)subscriber=Subscriber.first(phone_number:params[:From])command=params[:Body].downcaseifsubscribersubscriber.update(subscribed:subscription?(command))subscriberelseSubscriber.create(phone_number:params[:From],subscribed:subscription?(command))endend

app.rb

Register a new subscriber in the database

We want to provide our users with two SMS commands to manage their subscription status: add and remove.

These commands will toggle a boolean flag for a Subscriber record in the database and will determine whether or not our user will receive messages from our marketing campaign. We don't opt them in automatically - rather, we have them confirm that they want to receive our messages.

To make this happen, we will need to update the controller logic which handles the incoming text message to do a couple things:

If it is an add command or remove command, then create/update her or his subscription with the right status in the database.

If it is a command we don't recognize, then send a message explaining our available commands.

require'sinatra'require'data_mapper'require'json'require'rack/contrib'require'tilt/erb'require_relative'model/subscriber'database_url='postgres://postgres:postgres@localhost/marketing_notifications'DataMapper.setup(:default,database_url)DataMapper.finalizeSubscriber.auto_upgrade!use::Rack::PostBodyContentTypeParserSUBSCRIPTION_MESSAGE='You are now subscribed for updates.'UNSUBSCRIPTION_MESSAGE=%( You have unsubscribed from notifications. Test 'add' to start receiving updates again.)INSTRUCTIONS_MESSAGE=%( Thanks for contacting TWBC! Text 'add' if you would want to receive updates via text message.)get'/'doerb:index,locals:{message:nil}endpost'/messages'doSubscriber.subscribed.eachdo|subscriber|subscriber.send_message(params['message'],params['image_url'])enderb:index,locals:{message:'Messages Sent!!!'}endpost'/subscriber'docommand=params[:Body].downcaseifvalid_command?(command)subscriber=create_or_update_subscriber(params)ifsubscriber.subscribedformat_message(SUBSCRIPTION_MESSAGE)elseformat_message(UNSUBSCRIPTION_MESSAGE)endelseformat_message(INSTRUCTIONS_MESSAGE)endenddefsubscription?(command)command=='add'enddefvalid_command?(command)command=='add'||command=='remove'enddefformat_message(message)response=Twilio::TwiML::MessagingResponse.newresponse.message(body:message)response.to_senddefcreate_or_update_subscriber(params)subscriber=Subscriber.first(phone_number:params[:From])command=params[:Body].downcaseifsubscribersubscriber.update(subscribed:subscription?(command))subscriberelseSubscriber.create(phone_number:params[:From],subscribed:subscription?(command))endend

app.rb

Validate and execute a subscriber's command

When we receive a form submission from the frontend, we first grab the message text and optional image URL. Second, we loop through all Subscribers and call the send_message method to send the message out.

When the messages are on their way, we render back the index page with a success message (and make the marketing team happy).

require'sinatra'require'data_mapper'require'json'require'rack/contrib'require'tilt/erb'require_relative'model/subscriber'database_url='postgres://postgres:postgres@localhost/marketing_notifications'DataMapper.setup(:default,database_url)DataMapper.finalizeSubscriber.auto_upgrade!use::Rack::PostBodyContentTypeParserSUBSCRIPTION_MESSAGE='You are now subscribed for updates.'UNSUBSCRIPTION_MESSAGE=%( You have unsubscribed from notifications. Test 'add' to start receiving updates again.)INSTRUCTIONS_MESSAGE=%( Thanks for contacting TWBC! Text 'add' if you would want to receive updates via text message.)get'/'doerb:index,locals:{message:nil}endpost'/messages'doSubscriber.subscribed.eachdo|subscriber|subscriber.send_message(params['message'],params['image_url'])enderb:index,locals:{message:'Messages Sent!!!'}endpost'/subscriber'docommand=params[:Body].downcaseifvalid_command?(command)subscriber=create_or_update_subscriber(params)ifsubscriber.subscribedformat_message(SUBSCRIPTION_MESSAGE)elseformat_message(UNSUBSCRIPTION_MESSAGE)endelseformat_message(INSTRUCTIONS_MESSAGE)endenddefsubscription?(command)command=='add'enddefvalid_command?(command)command=='add'||command=='remove'enddefformat_message(message)response=Twilio::TwiML::MessagingResponse.newresponse.message(body:message)response.to_senddefcreate_or_update_subscriber(params)subscriber=Subscriber.first(phone_number:params[:From])command=params[:Body].downcaseifsubscribersubscriber.update(subscribed:subscription?(command))subscriberelseSubscriber.create(phone_number:params[:From],subscribed:subscription?(command))endend

app.rb

Webhook to send a message to all active subscribers

app.rb

Let's take an even closer look at how to send SMS or MMS notifications.

In the method send_message we create a Twilio REST API client that can be used to send SMS and MMS messages. The client requires your Twilio account credentials (an account SID and auth token), which can be found in the console:

Next all we need to do is call create on the client.messages object in order to send our message. The Twilio Message API call requires a from, to and body parameter. The media_url is optional.

require'sinatra'require'data_mapper'require'json'require'rack/contrib'require'tilt/erb'require_relative'model/subscriber'database_url='postgres://postgres:postgres@localhost/marketing_notifications'DataMapper.setup(:default,database_url)DataMapper.finalizeSubscriber.auto_upgrade!use::Rack::PostBodyContentTypeParserSUBSCRIPTION_MESSAGE='You are now subscribed for updates.'UNSUBSCRIPTION_MESSAGE=%( You have unsubscribed from notifications. Test 'add' to start receiving updates again.)INSTRUCTIONS_MESSAGE=%( Thanks for contacting TWBC! Text 'add' if you would want to receive updates via text message.)get'/'doerb:index,locals:{message:nil}endpost'/messages'doSubscriber.subscribed.eachdo|subscriber|subscriber.send_message(params['message'],params['image_url'])enderb:index,locals:{message:'Messages Sent!!!'}endpost'/subscriber'docommand=params[:Body].downcaseifvalid_command?(command)subscriber=create_or_update_subscriber(params)ifsubscriber.subscribedformat_message(SUBSCRIPTION_MESSAGE)elseformat_message(UNSUBSCRIPTION_MESSAGE)endelseformat_message(INSTRUCTIONS_MESSAGE)endenddefsubscription?(command)command=='add'enddefvalid_command?(command)command=='add'||command=='remove'enddefformat_message(message)response=Twilio::TwiML::MessagingResponse.newresponse.message(body:message)response.to_senddefcreate_or_update_subscriber(params)subscriber=Subscriber.first(phone_number:params[:From])command=params[:Body].downcaseifsubscribersubscriber.update(subscribed:subscription?(command))subscriberelseSubscriber.create(phone_number:params[:From],subscribed:subscription?(command))endend

require'sinatra'require'data_mapper'require'json'require'rack/contrib'require'tilt/erb'require_relative'model/subscriber'database_url='postgres://postgres:postgres@localhost/marketing_notifications'DataMapper.setup(:default,database_url)DataMapper.finalizeSubscriber.auto_upgrade!use::Rack::PostBodyContentTypeParserSUBSCRIPTION_MESSAGE='You are now subscribed for updates.'UNSUBSCRIPTION_MESSAGE=%( You have unsubscribed from notifications. Test 'add' to start receiving updates again.)INSTRUCTIONS_MESSAGE=%( Thanks for contacting TWBC! Text 'add' if you would want to receive updates via text message.)get'/'doerb:index,locals:{message:nil}endpost'/messages'doSubscriber.subscribed.eachdo|subscriber|subscriber.send_message(params['message'],params['image_url'])enderb:index,locals:{message:'Messages Sent!!!'}endpost'/subscriber'docommand=params[:Body].downcaseifvalid_command?(command)subscriber=create_or_update_subscriber(params)ifsubscriber.subscribedformat_message(SUBSCRIPTION_MESSAGE)elseformat_message(UNSUBSCRIPTION_MESSAGE)endelseformat_message(INSTRUCTIONS_MESSAGE)endenddefsubscription?(command)command=='add'enddefvalid_command?(command)command=='add'||command=='remove'enddefformat_message(message)response=Twilio::TwiML::MessagingResponse.newresponse.message(body:message)response.to_senddefcreate_or_update_subscriber(params)subscriber=Subscriber.first(phone_number:params[:From])command=params[:Body].downcaseifsubscribersubscriber.update(subscribed:subscription?(command))subscriberelseSubscriber.create(phone_number:params[:From],subscribed:subscription?(command))endend

require'sinatra'require'data_mapper'require'json'require'rack/contrib'require'tilt/erb'require_relative'model/subscriber'database_url='postgres://postgres:postgres@localhost/marketing_notifications'DataMapper.setup(:default,database_url)DataMapper.finalizeSubscriber.auto_upgrade!use::Rack::PostBodyContentTypeParserSUBSCRIPTION_MESSAGE='You are now subscribed for updates.'UNSUBSCRIPTION_MESSAGE=%( You have unsubscribed from notifications. Test 'add' to start receiving updates again.)INSTRUCTIONS_MESSAGE=%( Thanks for contacting TWBC! Text 'add' if you would want to receive updates via text message.)get'/'doerb:index,locals:{message:nil}endpost'/messages'doSubscriber.subscribed.eachdo|subscriber|subscriber.send_message(params['message'],params['image_url'])enderb:index,locals:{message:'Messages Sent!!!'}endpost'/subscriber'docommand=params[:Body].downcaseifvalid_command?(command)subscriber=create_or_update_subscriber(params)ifsubscriber.subscribedformat_message(SUBSCRIPTION_MESSAGE)elseformat_message(UNSUBSCRIPTION_MESSAGE)endelseformat_message(INSTRUCTIONS_MESSAGE)endenddefsubscription?(command)command=='add'enddefvalid_command?(command)command=='add'||command=='remove'enddefformat_message(message)response=Twilio::TwiML::MessagingResponse.newresponse.message(body:message)response.to_senddefcreate_or_update_subscriber(params)subscriber=Subscriber.first(phone_number:params[:From])command=params[:Body].downcaseifsubscribersubscriber.update(subscribed:subscription?(command))subscriberelseSubscriber.create(phone_number:params[:From],subscribed:subscription?(command))endend

require'sinatra'require'data_mapper'require'json'require'rack/contrib'require'tilt/erb'require_relative'model/subscriber'database_url='postgres://postgres:postgres@localhost/marketing_notifications'DataMapper.setup(:default,database_url)DataMapper.finalizeSubscriber.auto_upgrade!use::Rack::PostBodyContentTypeParserSUBSCRIPTION_MESSAGE='You are now subscribed for updates.'UNSUBSCRIPTION_MESSAGE=%( You have unsubscribed from notifications. Test 'add' to start receiving updates again.)INSTRUCTIONS_MESSAGE=%( Thanks for contacting TWBC! Text 'add' if you would want to receive updates via text message.)get'/'doerb:index,locals:{message:nil}endpost'/messages'doSubscriber.subscribed.eachdo|subscriber|subscriber.send_message(params['message'],params['image_url'])enderb:index,locals:{message:'Messages Sent!!!'}endpost'/subscriber'docommand=params[:Body].downcaseifvalid_command?(command)subscriber=create_or_update_subscriber(params)ifsubscriber.subscribedformat_message(SUBSCRIPTION_MESSAGE)elseformat_message(UNSUBSCRIPTION_MESSAGE)endelseformat_message(INSTRUCTIONS_MESSAGE)endenddefsubscription?(command)command=='add'enddefvalid_command?(command)command=='add'||command=='remove'enddefformat_message(message)response=Twilio::TwiML::MessagingResponse.newresponse.message(body:message)response.to_senddefcreate_or_update_subscriber(params)subscriber=Subscriber.first(phone_number:params[:From])command=params[:Body].downcaseifsubscribersubscriber.update(subscribed:subscription?(command))subscriberelseSubscriber.create(phone_number:params[:From],subscribed:subscription?(command))endend