Develop an SMS Feedback System with Laravel

May 17, 2024
Written by
Anumadu Udodiri Moses
Contributor
Opinions expressed by Twilio contributors are their own
Reviewed by

Develop an SMS Feedback System with Laravel

Customer feedback is crucial for the success of any business, as it provides valuable insights into customer satisfaction, preferences, and areas for improvement. In today’s digital era, businesses employ diverse methods, including SMS, email, and phone calls, to efficiently gather feedback from their customers regarding their products and services.

In this tutorial, you'll learn how to develop an SMS-based feedback collection system using Laravel and Twilio's Programmable Messaging API. The application will feature a "Request for Feedback" page, enabling business owners to send feedback requests to their customers' phone numbers via SMS. It will utilize a Twilio webhook to handle incoming feedback messages, and include a dashboard page to view the collected feedback responses.

Prerequisites

To complete this tutorial, you will need the following requirements:

Create a new Laravel project

Let’s get started by creating a new Laravel project. To do that, open your terminal and navigate to the directory where you want the Laravel project to be installed. Then, run the command below to create the project and change into the newly created project directory.

composer create-project laravel/laravel sms_based_feedback
cd sms_based_feedback

After the installation, the next step is to set up our database.

Configure the database

Our application needs a database connection to work. To connect the application to your database of choice, open the .env file in the project's root directory. Update the database connection section with your corresponding database credentials.

For the purpose of this tutorial, I used MySQL, which you can see in the below example.

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=<<DB_NAME>>
DB_USERNAME=<<DB_USER_NAME>>
DB_PASSWORD=<<DB_PASSWORD>>

On the MySQL database server, create a new database. Then, replace <> with your newly created database's name.

Now, let's proceed with building our actual application. First, we will create the database table and define its schema properties using the artisan make:migration command. To do this, start by running the command below to generate the migration file:

php artisan make:migration customerFeedback

Navigate to the database/migrations directory and open the file that ends with _customer_feedback.php. Then, replace its code with the following:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('customer_feedback', function (Blueprint $table) {
            $table->id();
            $table->string('phone');
            $table->string('response');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('customer_feedback');
    }
};

Next, run the command below to execute the database migration.

php artisan migrate

After setting up our database, we can start the application development server by running the following command.

php artisan serve

Now, you can access the application by opening http://127.0.0.1:8000 in your browser. This will display the application's default page, as shown in the screenshot below.

Install Twilio's PHP Helper Library

For the application to interact with Twilio’s Programmable Messaging API, you need to install the Twilio PHP Helper Library using the following command:

composer require twilio/sdk

Retrieve and store the Twilio account credentials

First, you need to retrieve your Twilio API access token, which can be found by logging in to your Twilio dashboard, as shown in the screenshot below:

After retrieving the Account SID, Auth Token, and Twilio phone number, we can proceed to store them in the .env file. To do so, add the following environment variables to the file.

ACCOUNT_SID="<<ACCOUNT_SID>>"
AUTH_TOKEN="<<AUTH_TOKEN>>"
TWILIO_NUMBER="<<TWILIO_NUMBER>>"

Then, replace <<ACCOUNT_SID>>, <<AUTH_TOKEN>>, and <<TWILIO_NUMBER>> with your corresponding Twilio values.

Create the feedback request form

Let’s create a form that allows you to enter your customers' phone numbers and send a feedback request message to them via SMS. To do this, we need to create a controller that will handle the application logic using the command below:

php artisan make:controller CustomerFeedbackController

To open the generated controller file, navigate to the app/Http/Controllers/ directory and open the CustomerFeedbackController.php file.  

Inside the file, replace the code with the following.

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Twilio\Rest\Client;

class CustomerFeedbackController extends Controller
{
    protected $accountSid;
    protected $authToken;
    protected $twilioNumber;
    protected $twilioClient;

    public function __construct()
    {
        $this->accountSid = env('ACCOUNT_SID');
        $this->authToken = env('AUTH_TOKEN');
        $this->twilioNumber = env('TWILIO_NUMBER');
        $this->twilioClient = new Client($this->accountSid, $this->authToken);
    }

    public function submitForm(Request $request)
    {
        $validatedData = $request->validate([
            'phones' => 'required',
            'message' => 'required',
        ]);

        $phones = explode(',', $validatedData['phones']);

        foreach ($phones as $phone) {
            try {
                $this->twilioClient->messages->create(
                    $phone,
                    [
                        'from' => $this->twilioNumber,
                        'body' => $validatedData['message']
                    ]
                );
            } catch (\Exception $e) {
                return back()->withInput()->withErrors(['error' => 'Failed to send SMS.']);
            }
        }
        return redirect()->back()->with('success', 'SMS sent successfully.');
    }
}

In the code above, we:

  • Used the __construct() method to retrieve the environment variables and instantiate the Twilio client

  • Used the submitForm() function to handle the form submission, connect to the Twilio endpoint, and send the feedback request message to the customer

Create the feedback request form template 

To create the feedback request form template, we will create the base layout and CustomerFeedback component files by running the commands below:

php artisan make:component layout
php artisan make:component CustomerFeedback

The above command will generate the layout.blade.php and customer-feedback.blade.php files inside the resources/views/components directory. Open the layout.blade.php file and replace its code with the following:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Customer Feedback</title>
    <style>
    /* Reset default margin and padding */
    *,
    *::before,
    *::after {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
    }

    body {
        font-family: Arial, sans-serif;
        background-color: #f0f0f0;
        display: flex;
        justify-content: center;
        align-items: center;
        height: 100vh;
        margin: 0;
    }

    .container {
        max-width: 800px;
        width: 90%;
        background-color: #fff;
        border-radius: 8px;
        box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
        padding: 20px;
    }

    h1 {
        color: #333;
        text-align: center;
        margin-bottom: 20px;
        font-size: 1.7rem;
    }

    ul {
        list-style-type: none;
        padding: 0;
    }

    li {
        margin-bottom: 15px;
        padding: 15px;
        background-color: #f9f9f9;
        border-radius: 8px;
        box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
    }

    li:last-child {
        margin-bottom: 0;
    }

    li span {
        font-weight: bold;
        color: #007bff;
    }

    /* Styles from the second HTML file */
    body {
        font-family: Arial, sans-serif;
        background-color: #f4f4f4;
        margin: 0;
        padding: 0;
    }

    .container {
        max-width: 600px;
        margin: 20px auto;
        background-color: #fff;
        padding: 20px;
        border-radius: 5px;
        box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
    }

    h2 {
        margin-top: 0;
        color: #333;
    }

    label {
        display: block;
        margin-bottom: 5px;
        font-weight: bold;
    }

    textarea {
        width: 90%;
        height: 100px;
        padding: 10px;
        margin-bottom: 10px;
        border: 1px solid #ccc;
        border-radius: 5px;
    }

    button {
        padding: 10px 20px;
        background-color: #007bff;
        color: #fff;
        border: none;
        border-radius: 5px;
        cursor: pointer;
        transition: background-color 0.3s;
    }

    button:hover {
        background-color: #0056b3;
    }

    label,
    textarea,
    button {
        font-size: 1.15rem;
    }
    </style>
</head>

<body>
    <div class="container">
        {{ $slot }}
    </div>
</body>

</html>

Next, open the customer-feedback.blade.php files and replace its code with the following:

<x-layout>
    <form method="POST" action="{{ url('/feedback') }}">
        @csrf
        <h1>Send SMS feedback request to customers</h1>
        <label for="phone">Phone:</label>
        <textarea name="phones" id="phone" placeholder="A comma-separated list of customer phone numbers..."></textarea>

        <label for="message">Feedback request message:</label>
        <textarea name="message" id="message" placeholder="Enter a feedback request message for your customers..."></textarea>
        <button type="submit">Submit</button>
    </form>
</x-layout>

Configure the routes

To configure the application, navigate to the routes folder, open the web.php file, and add the following routes.

Route::get('/feedback', function () { return view('components.customer-feedback'); })->name('CustomerFeedback');
Route::post('/feedback', [CustomerFeedbackController::class, 'submitForm']);
Route::get('/feedback/receive', [CustomerFeedbackController::class, 'receiveFeedback']);
Route::get('/feedback/responses', [CustomerFeedbackController::class, 'showFeedbackResponses']);

Then, at the top of the web.php file, add the following use statements:

use App\Http\Controllers\CustomerFeedbackController;

Save the code above and open http://127.0.0.1:8000/feedback in your browser. You should see the following output, as shown in the screenshot below.

Enter your customer's phone numbers and the feedback message as shown in the screenshot above. Then, click on the Send Feedback Request button to send the message.

On your mobile phone, you should receive a text message with the feedback request message, as shown in the screenshot below:

Handle incoming SMS responses

When customers provide their feedback by replying to the feedback request message, our application needs to be configured with a Twilio SMS Webhook to handle it and store the user's feedback in the database.

Let's start by creating a model called CustomerFeedback, which will be responsible for storing the received feedback in the database. To create the model, run the command below:

php artisan make:model CustomerFeedback

Next, navigate to the app/Models directory, open the new CustomerFeedback.php file, and update its contents with the following code:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class CustomerFeedback extends Model
{
    protected $table = 'customer_feedback';
    protected $fillable = [
        'phone',
        'response',
    ];
}

To handle incoming feedback SMS messages and store them in the database, add the following function to the CustomerFeedbackController.php file, located inside the app/Http/Controllers directory:

public function receiveFeedback(Request $request)
{
    $from = $request->From;
    $body = $request->Body;
    
    CustomerFeedback::create([
        'phone' => $from,
        'response' => $body
    ]);
    
    $this->twilioClient->messages->create(
        $from,
        [
            'from' => $this->twilioNumber,
            'body' => "Thank you for your feedback."
        ]
    );
    
    return response("Thank you for your feedback.");
}

Then, in the top section of the CustomerFeedbackController.php file, add the following use statement:

use App\Models\CustomerFeedback;

Now, the application can handle feedback responses using the URL http://127.0.0.1:8000/feedback/receive.

Configure the Twilio webhook 

To make http://127.0.0.1:8000/feedback/receive accessible online, we'll use Ngrok. Let's proceed by exposing http://127.0.0.1:8000/feedback/receive to the internet by running the following command in a terminal.

ngrok http http://127.0.0.1:8000

Running this command will generate a forwarding URL, as shown in the terminal screenshot below.

Now, copy the generated forwarding URL. Then, in your Twilio console dashboard, navigate to Phone Numbers > Manage > Active Numbers. Then, click your Twilio number, and click its Configure tab, as shown in the screenshot below.

Send the feedback message

Now that we've configured the Twilio SMS webhook, our application can handle incoming feedback messages and store them in the database.

To provide your feedback, simply reply to the feedback request message on your phone. Upon successful submission, you'll receive a thank-you message, as shown in the screenshot below:

View the feedback responses

Let’s create a page that fetches all the stored feedback from the database and displays it in our application. To do that, open the CustomerFeedbackController.php file and add the following function:

public function showFeedbackResponses()
{
    $feedbackResponses = CustomerFeedback::all();
    return view('components.feedback-responses', ['feedbackResponses' => $feedbackResponses]);
}

Next, run the command below to generate the accompanying template file:

php artisan make:component FeedbackResponses

Navigate to the resources/views/components directory, open the feedback-responses.blade.php file, and replace its code with the following:

<x-layout>
    <h1>Customer Feedback Responses</h1>
    <ul>
        @foreach($feedbackResponses as $feedback)
        <li><span>Customer phone:</span> {{ $feedback->phone }},<br><br> <span>Feedback Response:</span>
        {{ $feedback->response }}</li>
        @endforeach
    </ul>
</x-layout>

Save your work and open http://127.0.0.1:8000/feedback/responses in your browser. You should see all the collected feedback displayed, as shown in the screenshot below:

That's how to develop an SMS-Based feedback collection system with Laravel and Twilio

In this tutorial, we walked through the process of developing an SMS-based feedback collection system using Laravel and Twilio. Throughout this tutorial, we covered the following steps:

  • Set up a new Laravel project and installed the Twilio PHP Helper Library

  • Created a feedback request form page

  • Handled incoming feedback SMS messages using Twilio webhook functionality

  • Displayed all of the collected feedback

Feel free to change the code to fit what you want. Then, create cool things and tell us about them!

Moses Anumadu is a software developer and online educator who loves to write clean, maintainable code. He's creating something awesome for Laravel developers with Laravel.