Skip Navigation
Show nav
Heroku Dev Center
  • Get Started
  • Documentation
  • Changelog
  • Search
  • Get Started
    • Node.js
    • Ruby on Rails
    • Ruby
    • Python
    • Java
    • PHP
    • Go
    • Scala
    • Clojure
  • Documentation
  • Changelog
  • More
    Additional Resources
    • Home
    • Elements
    • Products
    • Pricing
    • Careers
    • Help
    • Status
    • Events
    • Podcasts
    • Compliance Center
    Heroku Blog

    Heroku Blog

    Find out what's new with Heroku on our blog.

    Visit Blog
  • Log inorSign up
View categories

Categories

  • Heroku Architecture
    • Dynos (app containers)
    • Stacks (operating system images)
    • Networking & DNS
    • Platform Policies
    • Platform Principles
  • Command Line
  • Deployment
    • Deploying with Git
    • Deploying with Docker
    • Deployment Integrations
  • Continuous Delivery
    • Continuous Integration
  • Language Support
    • Node.js
    • Ruby
      • Working with Bundler
      • Rails Support
    • Python
      • Background Jobs in Python
      • Working with Django
    • Java
      • Working with Maven
      • Java Database Operations
      • Working with the Play Framework
      • Working with Spring Boot
      • Java Advanced Topics
    • PHP
    • Go
      • Go Dependency Management
    • Scala
    • Clojure
  • Databases & Data Management
    • Heroku Postgres
      • Postgres Basics
      • Postgres Getting Started
      • Postgres Performance
      • Postgres Data Transfer & Preservation
      • Postgres Availability
      • Postgres Special Topics
    • Heroku Data For Redis
    • Apache Kafka on Heroku
    • Other Data Stores
  • Monitoring & Metrics
    • Logging
  • App Performance
  • Add-ons
    • All Add-ons
  • Collaboration
  • Security
    • App Security
    • Identities & Authentication
    • Compliance
  • Heroku Enterprise
    • Private Spaces
      • Infrastructure Networking
    • Enterprise Accounts
    • Enterprise Teams
    • Heroku Connect (Salesforce sync)
      • Heroku Connect Administration
      • Heroku Connect Reference
      • Heroku Connect Troubleshooting
    • Single Sign-on (SSO)
  • Patterns & Best Practices
  • Extending Heroku
    • Platform API
    • App Webhooks
    • Heroku Labs
    • Building Add-ons
      • Add-on Development Tasks
      • Add-on APIs
      • Add-on Guidelines & Requirements
    • Building CLI Plugins
    • Developing Buildpacks
    • Dev Center
  • Accounts & Billing
  • Troubleshooting & Support
  • Integrating with Salesforce
  • Add-ons
  • All Add-ons
  • Till
Till

This add-on is operated by Till Mobile

Build two way SMS apps

Till

Last updated May 01, 2017

Table of Contents

  • Provisioning the Till add-on
  • Using with Python / Django or Node.js
  • Dashboard
  • Migrating between plans
  • How many renders do I need?
  • Removing the add-on
  • Support

Use the Till add-on to ask questions via SMS and receive validated responses via webhook, enabling instant alerts, flash surveys, and real-time two-way communication with a simple HTTP API.

Learn more about the Till platform.

Provisioning the Till add-on

Renders vs. Messages - Control your Budget

One key Till objective is to help your business users control their budgets. We do this by charging only for “Renders”.

  • A “render” is content that is converted into a message and sent
  • There is no charge for inbound communication i.e. responses to questions
  • The benefit to this approach is that the budget for any project is constrained by the number of renders created regardless of the response rate.

Note: Invalid responses to questions can incur extra renders as it may require asking questions multiple times. Clear, simple questions that users can easily respond to will produce better results with more efficient spend.

A list of all plans available can be found here.

Provisioning

Till can be attached to a Heroku application via the CLI:

$ heroku addons:create till
-----> Adding till to sharp-mountain-4005... done, v18 (free)

Once till has been added a TILL_URL setting will be available in the app configuration and will contain the canonical URL used to access your till account. This can be confirmed using the heroku config:get command.

$ heroku config:get TILL_URL
https://platform.tillmobile.com/rpc/send/4083h0384hw0dnsvslkdnv304n30434/

After installing till your application should be configured to fully integrate with the add-on.

Using with Python / Django or Node.js

Check out the example app in Python, or deploy it:

Deploy

Check out the example app in Node.js, or deploy it:

Deploy Example

For Python We recommend using the requests library when accessing the Till HTTP API.

$ pip install requests

For Node.js we recommend using the request-json library when accessing the Till HTTP API.

$ npm install request-json --save

Ask your first question over SMS with Till

Ask one or more users via passed phone numbers a set of questions over SMS. Have the valid responses sent to a web hook.

Python

import os, requests

TILL_URL = os.environ.get("TILL_URL")

requests.post(TILL_URL, json={
    "phone": ["15558675309", "15558675308"],
    "questions" : [{
        "text": "Favorite color?",
        "tag": "favorite_color",
        "responses": ["Red", "Green", "Yellow"],
        "webhook": "https://yourapp.herokuapp.com/results/"
    }],
    "conclusion": "Thank you for your time"
})

Node.js

var request = require("request-json");
var url = require("url");

var TILL_URL = url.parse(process.env.TILL_URL);
var TILL_BASE = TILL_URL.protocol + "//" + TILL_URL.host;
var TILL_PATH = TILL_URL.pathname;

if(TILL_URL.query != null) {
  TILL_PATH += "?"+TILL_URL.query;
}

request.createClient(TILL_BASE).post(TILL_PATH, {
  "phone": ["15558675309", "15558675308"],
  "questions": [{
  "text": "Favorite color?",
    "tag": "favorite_color",
    "responses": ["Red", "Green", "Yellow"],
    "webhook": "https://yourapp.herokuapp.com/results/"
  }],
  "conclusion": "Thank you for your time"
}, function(err, res, body) {
  return console.log(res.statusCode);
});

Sending the POST request will result in a launch to be created in Till. The POST will return JSON containing a project_launch_guid to identify the launch and corresponding URLs for tracking results and stats via the Till API:

Send API Response

{
  "project_launch_guid": "ed45h45hf60f0-46bb-468a-b80a-14ad95138e83",
  "stats_url": "https://platform.tillmobile.com/api/stats/ed45h45hf60f0-46bb-468a-b80a-14ad95138e83?username=45g4545g&api_key=dfdfgdg",
  "results_url": "https://platform.tillmobile.com/api/results?username=343434&api_key=erergergerg&project_launch_guid=ed45h45hf60f0-46bb-468a-b80a-14ad95138e83"
}

/api/stats/

The stats API returns statistics regarding your launch and its progress.

{
  // The number of "Sessions" i.e. channels of communication open between
  // your phone number and your user's phone numbers. Active sessions are
  // in progress i.e. questions are being answered.
  "num_active_sessions": 0,

  // The number of queued sessions i.e. when multiple sets of questions are sent to
  // a user's phone via the same phone number. The set(s) of questions not being answered
  // will be queued waiting for the user to finish the first set of questions or for 1hr
  // to pass and the session to expire. This causes the active session to complete and the
  // next queued session to become active.
  "num_queued_sessions": 0,

  // Complete sessions occur when a user has answered all their questions or
  // they had a queued session that timed the active session out.
  "num_complete_sessions": 1,

  // The total number of questions asked
  "num_questions": 0,

  // The number of renders consumed when asking the user(s) questions.
  // Note: Extra renders are consumed each time an invalid response is received
  // and the question must be asked an additional time
  "num_renders": 1,

  // The number of valid results captured from all users
  "num_results": 0,

  // The identifier for the launch
  "project_launch_guid": "34gg34g34g-sd2sdfsdf51a-34g34g-v343v44v-34vdvsdvsv",

  // When did this launch start i.e. first render occurred
  "project_launch_start": "2016-11-27T11:47:17.939926"
}

/api/results/

The results API returns results in the same format as the web hook with some additional meta data. Use this API call to poll for results or retrieve results from multiple launches.

{
  // Meta data
  "created": "2016-11-27T11:57:14.060474",
  "updated": "2016-11-27T11:57:14.060538",
  "guid": "wegweg-5d42-sdf-sdfsdf-sdf",

  // Launch
  "project_launch_guid": "445c481f-g4g-49e5-dfgdg-b96b1a5cae0f",

  // Participant
  "participant_guid": "34g34g43-2c30-43f5-8f6b-34g3434g",
  "participant_phone_number": "+15558675309",

  // Question
  "question_guid": "ergeg-2c30-34g34g34g-8f6b-dffgdfgdfg",
  "question_tag": "favorite_color",
  "question_text": "Favorite color?",

  // Result
  "result_guid": "dfbdfb-2c30-43f5-8f6b-ergerg",
  "result_timestamp": "2016-11-27T11:57:14.060474",
  "result_answer": "2",
  "result_response": "Green"
}

SMS UX Flow

The phone attached to 15558675309 should see the SMS message:

Favorite color? Please respond [1] Red, [2] Green, [3] Yellow.

Response Validation

If valid input e.g. 1, 2, 3, Red, Green, or Yellow is NOT entered then a retry message will be sent. Note: This will incur additional renders:

Invalid response.

Favorite color? Please respond [1] Red, [2] Green, [3] Yellow.

If valid input is received and all questions in the questions array have been answered the optional conclusion text will be rendered:

Thank you for your time

Note: questions can have an optional conclude_on attribute. If the provided value matches the user’s input will skip all remaining questions and render the conclusion message completing the session e.g.

"questions: [{
  "text": "Continue with questions?",
  "responses": ["Yes", "No"],
  "conclude_on": "No"
}]

Web Hook Data Collection

Valid user responses will be sent to the webhook defined in the request e.g. https://yourapp.herokuapp.com/results/ via application/json POST data in the form:

{
  // Launch
  "project_launch_guid": "445c481f-c19c-49e5-9e84-b96b1a5cae0f",

  // Participant
  "participant_guid": "585897f2-2c30-43f5-8f6b-7c243e8ac4b0",
  "participant_phone_number": "+15558675309",

  // Question
  "question_guid": "685897f2-2c30-43f5-8f6b-7c243e8ac4b0",
  "question_tag": "favorite_color",
  "question_text": "Favorite color?",

  // Result
  "result_guid": "885897f2-2c30-43f5-8f6b-7c243e8ac4b0",
  "result_timestamp": "2016-11-27T11:57:14.060474",
  "result_answer": "2",
  "result_response": "Green"
}

Or, send an alert

Don’t ask a question, send an alert to one or more phone numbers.

Python

import os, requests

TILL_URL = os.environ.get("TILL_URL")

requests.post(TILL_URL, json={
    "phone": ["15558675309", "15558675308"],
    "text" : "Hello Heroku!"
})

Node.js

var request = require("request-json");
var url = require("url");

var TILL_URL = url.parse(process.env.TILL_URL);
var TILL_BASE = TILL_URL.protocol + "//" + TILL_URL.host;
var TILL_PATH = TILL_URL.pathname;

if(TILL_URL.query != null) {
  TILL_PATH += "?"+TILL_URL.query;
}

request.createClient(TILL_BASE).post(TILL_PATH, {
  "phone": ["15558675309", "15558675308"],
  "text": "Hello Heroku!"
}, function(err, res, body) {
  return console.log(res.statusCode);
});

Phone Number Format

For both examples note the phone number format. Till will attempt to normalize phone numbers into E.164 format.

Dashboard

The Till dashboard allows you to monitor usage (renders) and response rate for the current month and all time.

The dashboard can be accessed via the CLI:

$ heroku addons:open till
Opening till for sharp-mountain-4005

or by visiting the Heroku Dashboard and selecting the application in question. Select Till from the Add-ons menu.

Migrating between plans

Application owners should carefully manage the migration timing to ensure proper application function during the migration process.

Use the heroku addons:upgrade command to migrate to a new plan.

$ heroku addons:upgrade till:newplan
-----> Upgrading till:newplan to sharp-mountain-4005... done, v18 ($49/mo)
       Your plan has been updated to: till:newplan

How many renders do I need?

Renders have per month maximums e.g. 5,000 for each plan. However, to help ensure the reliability of the service all renders cannot be consumed at once.

A buffer of renders is provided every month and renders accrue every second the add on is provisioned.

The current available renders are returned in the Available-Renders header and the accrual rate is returned in the Render-Accrual-Rate header of each send request.

If your app goes over the limit a HTTP 429 status code will be returned.

Removing the add-on

Till can be removed via the CLI.

This will destroy all associated data and cannot be undone!

$ heroku addons:destroy till
-----> Removing till from sharp-mountain-4005... done, v20 (free)

Support

All Till support and runtime issues should be submitted via one of the Heroku Support channels. Any non-support related issues or product feedback is welcome at Till Support.

Keep reading

  • All Add-ons

Feedback

Log in to submit feedback.

Ziggeo Trakr visual testing

Information & Support

  • Getting Started
  • Documentation
  • Changelog
  • Compliance Center
  • Training & Education
  • Blog
  • Podcasts
  • Support Channels
  • Status

Language Reference

  • Node.js
  • Ruby
  • Java
  • PHP
  • Python
  • Go
  • Scala
  • Clojure

Other Resources

  • Careers
  • Elements
  • Products
  • Pricing

Subscribe to our monthly newsletter

Your email address:

  • RSS
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku Blog
    • Heroku News Blog
    • Heroku Engineering Blog
  • Heroku Podcasts
  • Twitter
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku
    • Heroku Status
  • Facebook
  • Instagram
  • Github
  • LinkedIn
  • YouTube
Heroku is acompany

 © Salesforce.com

  • heroku.com
  • Terms of Service
  • Privacy
  • Cookies
  • Cookie Preferences