Menu Driven SMS Surveys Using Africa’s Talking SMS API

Introduction

SMS surveys are an important tool for any business wishing to gather insights and feedback to improve their customers’ experience. In this tutorial, we will build a simple SMS-based survey system using Africa’s Talking (AT)’s 2-way SMS product. 

The survey system works as follows:

  • An organization creates a survey with a set of questions. The first question in each survey requests a user if they want to take part.
  • If the user accepts, they will receive questions in the appropriate order and respond after every question until the survey’s last question.

A sample survey and survey questions are as shown below:

  • Survey Title: Products feedback from users
  • Questions (in the given order):
  1. Hi <customer name>, can you take our survey. We need to know how you feel about our AT products? Reply with Yes or No
  2. Which AT products do you use? Reply with  1 – USSD, 2 – SMS, 3 – Airtime
  3. How likely can you recommend our products to another business? Reply with 1 – Unlikely, 2 – Undecide and 3 – Very likely.

Tutorial outline

  1. Pre-requisites
  2. Setting up an AT account and SMS shortcode.
  3. Project structure and database design.
  4. Connecting to the database.
  5. Writing the logic for the user, survey and SMS entities.
  6. Inviting users to a survey and testing the app.
  7. Conclusion and troubleshooting ideas.

Pre-requisites

  • Some knowledge of PHP programming language and MySQL DBMS
  • AT SMS shortcode
  • Incoming message callback URL
  • A computer setup with a PHP HTTP server and a MySQL database (you can use XAMPP software for this purpose)
  • A computer setup with a composer for dependency management (we will use AT’s PHP SDK)
  • A computer setup with MySQL database and Apache server. You can use XAMPP software, which bundles both Apache web server and MySQL DBMS.

Setting up an AT account and SMS shortcode.

In this section, you will learn how to do the following:

  • Setting up an AT developer account
  • Creating SMS shortcode (we need 2-way communication)
  • Adding an incoming SMS callback URL
  • Generating an API key for your AT developer account
Creating developer account in AT
  1. Follow this link to create your AT developer account: Click here.
  2. Login to AT developer account
  3. Click on 'Go To Sandbox App
Adding an incoming SMS callback URL
  1. Click here to access the SMS – Inbox callback page.
  2. In the URL input text, add a URL that invokes your receiveSms.php PHP script (we will do this later). If you will not host your app on an online server, you can use ngrok to generate a URL, pointing to your local machine. If you do not know how to setup a http link using ngrok, please see this tutorial, How to access your Windows computer or local server from anywhere using ngrok. The callback URL can be generated when you are about to test your app. Learn more about the incoming SMS callback URL here.
  3. Click submit.
Creating SMS shortcode
  1. Click here to access the Create Short Code page.
  2. Enter your shortcode in the Short Code text input.
  3. Click Submit. If the system rejects your shortcode, it means it has been taken by another developer. Try different numbers until you are successful.
Generating an API Key

For you to use AT products/services, such as sending SMS, you need to generate an API key for your account. 

Use the following steps to generate an API Key:-

  1. Click here to access AT dashboard.
  2. Read the instructions on that page.
  3. Enter your account password.
  4. Click on Generate to generate your API key.

Project structure and database design

In this lesson, we will cover the following: 

  • project structure
  • database design
Project structure 

In this app, we have the files shown in the directory structure below.

project
|	db.php
|	receiveSms.php
|	sms.php
|	survey.php
|	user.php
|	util.php
|_______invite
|	|	invite.php
  • db.php – this is where database connection happens
  • receiveSms.php – this is the script, which executes when an SMS is received from a user
  • sms.php – contains the logic for sending an SMS to the user.
  • survey.php – contains the logic for the survey and the survey question, such as reading a survey question
  • user.php – contains user logic such as read all user phone numbers
  • util.php – contains some settings variables, which may be unique to each user/developer, e.g. API key etc.
  • invite.php – contains the logic for sending a survey invite from all target users. We also know that the survey invite is the first question in the survey.
Database Design 

The diagram below summarizes the database schema for the database used in this app. 

Application database schema

The database name is menusurvey, and it has 5 tables as follows:

  • user – contains user details. phone_number is a unique attribute.
  • survey – contains the surveys. The maxi_level is the number of questions in the survey
  • user_survey – contains details about which user is taking what survey. The attributes level (level 1 means the user has answered the first question, level 2 means the user has responded to the second question and so forth) tracks which survey question a user is answering at the moment and invitation status. invitation status attribute can take the following values:-
    • 1 – user has been invited to take a survey
    • 2 – user has accepted to take a survey
    • 3 – user has declined to take a survey
    • 4- user had accepted to take the survey and has completed, i.e. answered all the questions.
  • survey_question – contains question contained in a given survey
  • survey_question_answer – contains question user responses to survey questions

Use this link to access the databases SQL schema. It will save you time.

https://gist.github.com/derduskenga/4a9b73db1216493b9ece7a8aa888810f

With the SQL schema, create a named database in your MySQL DBMS and import the .sql file.

Connecting to database

In this section, we will connect to our database as well as set up the util.php file. 

Setting up the util.php file

Add the following code into the util.php file.

<?php
    class Util{
        static $DB_NAME = "db name here";
        static $DB_USER = "db user here"; 
        static $DB_USER_PASS = "db user password here"; 
        static $SERVER_NAME = "db server here";

        static  $API_KEY = "AT account api key here"; //sandbox
        static $API_USERNAME = "sandbox"; //sandbox
        static $SMS_SHORTCODE = "yout AT account short code here";        
    }
?>

From the code above, notice that you will be required to use your own values for the variables. For instance, for $SMS_SHORTCODE, use the shortcode, which you set in your AT sandbox.

Connecting to database 

Add the following code in the db.php file.

<?php
    include_once 'util.php';	
    class DBConnector {
        var $pdo;
        function __construct(){
                $dsn= "mysql:host=". Util::$SERVER_NAME . ";dbname=" . Util::$DB_NAME ."";
                $options = [ 
                        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
                        PDO::ATTR_EMULATE_PREPARES => false,
                        PDO::ATTR_DEFAULT_FETCH_MODE =>PDO::FETCH_ASSOC
                        ];
                try{
                        $this->pdo = new PDO($dsn, Util::$DB_USER, Util::$DB_USER_PASS, $options);				
                }catch (PDOException $e){
                        echo $e->getMessage();
                }			
        }
        public function connectToDB(){
                return $this->pdo;
        } 			
        public function closeDB(){
                $this->pdo = null;
        }
    }
?>

From the code, you can see that we are using PHP Data Objects (PDO) to connect to the database. You do not need to adjust anything in your php.ini file when using MySQL. Otherwise, you will need to enable drivers for other databases. If you have never heard of PDO, have a look at this tutorial, How to Connect to ANY DB using PHP Data Objects.

Writing the logic for user, survey and SMS entities.

In this section, you will build the logic for user, survey and sms entities using SmsSurvey and User classes respectively.

Building Sms class

In the Sms class, we have used AT’s PHP SDK to send an SMS.

Proceed as follows:

  1. From your project directory, run composer require africastalking/africastalking to install AT’s PHP SDK.
  2. Add the following code in the sms.php file.
<?php
    require 'vendor/autoload.php';
    use AfricasTalking\SDK\AfricasTalking;
    include_once 'util.php';
    include_once 'db.php';
    class Sms {
        protected $AT;
        function __construct(){            
            $this->AT = new AfricasTalking(Util::$API_USERNAME, Util::$API_KEY);
        }
        public function sendSMS($message, $recipients){
            //get the sms service
            $sms = $this->AT->sms();
            //use the service 
            $result = $sms->send([
                'to'      => $recipients,
                'message' => $message,
                'from'    => Util::$SMS_SHORTCODE,
            ]);
            return $result;
        }
    }
?> 

The SMS is sent in the sendSMS function. sendSMS function takes $messge and $recipients parameters. $recipients is an array of phone numbers (see allPhoneNumbers function in User class below).

Building the User class 

In the user.php file, add the following code. Be sure to read the comments in the code. 

If you understood the project description, the functions in the class should also make sense.

Building the Survey class 

The Survey class is where we add users to a survey, read survey questions and track how users are responding to survey questions. 

In the survey.php file, add the following code

It is easy to understand what the function in the Survey class do because of how we have named them. However, heavy lifting is done by the updateUserToSurvey function. When a user answers a survey question, this is the function, used to update the questions, which have been answered and to send the next question. Before the user answers the last question, the following code snippet keeps on updating the user question level.

     //Read a survey question, which $level+1 and send it to the user
             $message = $this->readSurveyQuestion($pdo,$surveyId,$level+1);
             $sms->sendSMS($message,$phoneNumber);
     //update question level for this user in this particular survey
                    
          $user->updateUserLevel($pdo,$surveyId,$level + 1,$userId);
                    //add survey question answer
$surveyQuestionId = $this->getSurveyQuestionIdByLevelAndSurveyId($pdo, $level, $surveyId);

   $this->addAnswerToSurveyQuestion($pdo,$surveyQuestionId,$userAnswer);

We know the user is answering the last question when the level is equal to the number of questions in the survey. See the code snippet below:

$maxLevel = 3; //say 3
                $userId = $user->getUserIdByPhoneNumber($pdo,$phoneNumber);
                if ($level == $maxLevel){

To better understand the algorithm, read the comments in the source code. Also, remember that sending an SMS functionality is handled by sendSMS in the Sms class

Inviting users to a survey and testing the app

In this section, you will complete the logic for the following

  • inviting users to a survey
  • receiving answers for survey questions from users
  • testing you app
Inviting users to a survey 

Inviting users to a survey consists of 2 steps:

  1. Adding users to a survey
  2. Sending an invitation message, i.e. the first question of a survey. Users will either accept or reject to take the survey.
  3. In the invite.php file, add the following code (invite.php file is in the invite folder).
?php
    include_once '../sms.php';
    include_once '../db.php';
    include_once '../user.php';
    include_once '../survey.php';

    $sms = new Sms();
    $survey = new Survey();
    $user = new User();
    $con = new DBConnector();
    $pdo = $con->connectToDB();
    $surveyId = 1; //pick a survey manually, but can be read from DB
    //___________________________________________________________________
        $questionLevel = 1;   	         //_____________________________________________________________________
    //Select question 1, which is always asking the user if they accept to take the survey. 
       
   $message = $survey->readSurveyQuestion($pdo, $surveyId, $questionLevel); //We are readin the first question
   
    $recipients = $user->allPhoneNumbers($pdo);
    $sms->sendSMS($message,$recipients);   
   
    //add these users to a survey 
    $survey->addUserToSurvey($pdo,$recipients,$surveyId, 1, 1); 
    /*level and invitation status set to 1 because first question have been 
    sent, which means user have been invited*/
?>

Notice that we read all the users’ phone numbers, add them to a survey, i.e. survey with ID 1, then send an SMS asking the users if they would like to take a survey. In a production ready app, you need a way to identify the surveys. Our example is simple – we are sure there is a survey of ID 1. If you’ve forgotten what addUserToSurvey function does, visit the Survey class to check its definition.

Receiving SMS responses from users, i.e. survey question answers 

When AT receives an SMS from a user, it uses the callback URL we set in section 4 to deliver it to your server. AT sends a POST request to your server with parameters including sender phone number and text. To learn more about this visit, AT docs

In the receiveSms.php file, add the following code.

<?php
        include_once 'util.php';
        include_once 'db.php';
        include_once 'user.php';
        include_once 'sms.php';
        include_once 'survey.php';

        $survey = new Survey();
        $con = new DBConnector();
        $pdo = $con->connectToDB();
                   
        $phoneNumber = $_POST['from'];          
        $text = $_POST['text'];
        $surveyId = 1;
        $survey->updateUserToSurvey($pdo,$phoneNumber,$text,$surveyId);       
?>

Every time we receive a response from a user, we update the user survey. The $text variable contains the SMS text sent from the user i.e. the survey question’s answer.

Testing your SMS survey app
  1. While in AT sandbox dashboard, launch the simulator (see left menu, lower side). You can also download the AT simulator from the Google Play store and test the menu from your phone.
  2. Setup a phone number of your choice. The mobile number, in this case, is equivalent to the one held in a SIM card of a real mobile phone. If the phone number you use refuses, chances are another developer somewhere is using a similar number in the emulator, so you have to try another one.
  3. Open a new tab in your browser and run your invite.php file. If you are using your local host on port 80, you paste something like this into your browser; http://127.0.0.1/appfolder/invite/invite.php This is how you add users to a survey and send them an invitation. If everything goes well, you will see a blank page, and a invitation message is delivered to your emulator as an SMS. Notice that in our example, we have hardcoded the survey ID to 1. Find a way of indenting your surveys.
  4. Reply to the received SMS appropriately. If you accept to take the survey, you will answer all the questions to the end of the survey. You can also decide to reject the survey request. Test both scenarios.

Conclusion and troubleshooting ideas

If you are here, then you made it. Congratulations! 

The solution we have discussed here is one way of thinking about an SMS-based survey (menu-driven, of course ) – it may not be the best though. Feel free to think of it in another way. All we set to achieve is to learn how to use AT SMS API to create a survey app.

Also, note that you can use AT’s SMS product by consuming the REST API instead of using the SDK.

If things never worked as we explained, please check out for the following troubleshooting ideas:

  1. Ensure that you have used the correct username for the sandbox. The Username for the sandbox environment is always sandbox. Do not confuse it with your live environment username.
  2. Ensure you have used the API key for your sandbox – of course, you have to generate it. Please copy and paste it to avoid errors. Remember that if you regenerate the key, it will change. You have to update it in your code.
  3. Ensure an SMS shortcode has been created in AT dashboard. If you try to invite users to a survey without the shortcode, you will not receive an SMS.
  4. Use your own variables where you will be asked to, e.g. API key, sender ID etc. in the Util class
  5. Ensure you follow the steps presented in section 8 (where you are testing the app) in the order presented, e.g. you have to execute invite.php script only after the phone simulator is set up.
  6. Ensure that a correct SMS callback URL is well set. Otherwise, your app will not receive messages sent by the user. If you are using ngrok, make sure that the generated link is active – it may have expired, or the ngrok client may have disconnected with the ngrok server.
  7. AT simulator uses port 1517 (see this https://simulator.africastalking.com:1517) for access. Thus, if you are using an internet connection, with restrictions such as access port, it may not work. In that case, you may try to use your mobile data.

To access the complete code for this tutorial in GitHub, click here.

Thank you for following this tutorial. I hope it was helpful. Feel free to add your comment.

0 Shares:
You May Also Like