How to Build a Real-Time SMS Status Tracking and Logging Using Go and Twilio
Time to read: 9 minutes
How to Build a Real-Time SMS Status Tracking and Logging Using Go and Twilio
Tracking an SMS' status in real-time is essential for applications that rely on timely notifications, as it ensures messages reach their intended recipients or trigger follow-ups when delivery fails.
This tutorial will walk you through creating a simplistic SMS status tracking and logging system using Go and Twilio. Because Twilio provides reliable SMS and status callback functionality, while Go’s concurrency and efficiency make it ideal for handling real-time data.
So, specifically, in this tutorial, you’ll learn to set up a Go server, integrate Twilio’s Programmable Messaging API, handle status callbacks for real-time tracking, and implement a logging system to record each SMS event.
We’ll cover everything from initial setup and sending messages to building an endpoint for receiving status updates. By the end, you’ll have a solution that can be deployed in production, giving you a solid foundation in SMS tracking and logging for your applications.
Prerequisites
Before you begin, ensure you have the following:
- Go version 1.22 or above
- A Twilio account (either free or paid). If you are new to Twilio, click here to create a free account
- Basic knowledge of Go
- A mobile phone that can send SMS
- ngrok and an active ngrok account
Overview of Twilio's SMS status callbacks
Twilio's SMS status callbacks allow developers to track the lifecycle of an SMS message in real time. When a message is sent, Twilio can notify your server about status changes such as queued, sent, delivered, or undelivered. These updates help you understand whether messages are successfully reaching recipients or encountering delivery issues.
Notifications are sent via HTTP POST request webhooks to a URL which you define in your application. If you're not familiar with the term, a webhook is a way for one application to send real-time data to another application over HTTP when a specific event occurs.
This feature is essential for applications that rely on delivery assurance, auditing, message tracking, or user notifications. For example, an e-commerce platform might use it to confirm that order updates were delivered to customers, or a healthcare app might use it to ensure appointment reminders reached patients.
To use status callbacks, you simply provide a status callback URL when sending an SMS through Twilio. As the message moves through different stages, Twilio automatically POSTs structured data including the message SID, message status, and recipient number to that URL.
For more details on how status callbacks work, including all available status values and webhook payload examples, refer to Twilio’s official documentation.
Create a new Go application
Creating the project involves initializing a new Go module using the go mod init command. This sets up the foundational structure for your application by creating a go.mod file, which defines the module’s name and tracks its dependencies. It’s how Go knows where your project starts and what external packages it will rely on.
Installing dependencies means that any third-party packages your application imports are downloaded and properly tracked. This happens when you run go get or go build, or run your program, prompting Go to fetch the necessary packages and record them in the go.mod and go.sum files.
Run the following commands to create a project directory, navigate into it, and install the required dependencies:
The dependencies are:
- Twilio's official Go Helper Library: This simplifies using Twilio's APIs in Go
- GoDotEnv: This loads environment variables from a .env file
- GoCSV: This simplifies reading and writing CSV files in Go
Then, initialize a new Go module by running the following in your terminal:
Create the environment variables
To simplify storing the application's configuration information, you should use environment variables. These will be stored in an .env file and loaded into the environment using GoDotEnv.
Start by creating a .env file in the root of your project and add the following to it:
CSV_FILE
is the path to the CSV file where webhook status information will be logged. For a simple example, it's easier than interacting with a database.
The TWILIO_
prefixed variables are your Twilio credentials and phone number. RECEIVER_PHONE_NUMBER
will store your phone number, so replace <your_cell_mobile_number>
with your mobile/cell phone number in E.164 format.
Finally, the STATUS_CALLBACK_URL
variable is the public URL where Twilio will send SMS status updates (e.g., queued, delivered, and undelivered).
Create the CSV template
Next up, create a new file named data.csv in the project's top-level directory. Then, in the file, paste the code below.
Retrieve your Twilio access token
Next, log in to your Twilio Console to retrieve your Account SID, Auth Token, and Twilio phone number from the Account Info panel, as you can see in the screenshot below.


Then, use them to replace <your_twilio_account_sid>
, <your_twilio_auth_token>
, and <your_twilio_phone_number>
, respectively, in the .env file.
These credentials are necessary because they authenticate your application with Twilio's API, allowing it to send and receive SMS messages securely. The Twilio phone number acts as your application's sender ID, enabling it to interact with real mobile numbers and receive message status updates through webhooks. Without these, your Go application won’t be able to connect to Twilio’s services or handle SMS events properly.
Build the real-time SMS tracking system with Go
Now, let's set up a basic Go application that listens for incoming status updates from Twilio and initiates SMS messages with the callbacks registered.
Set up a basic Go server to handle HTTP requests
To begin, you'll need a simple HTTP server that can handle POST requests. This server will act as the endpoint for receiving Twilio's status updates.
Create a file named main.go inside the root of your project directory. Once you've created main.go, add the provided server and webhook-handling code, below, to the file.
The code creates a new request multiplexer (Mux) listening on port 8080 with three routes:
/sms
: This route receives the webhook request from Twilio and writes the information to a CSV file./send-sms
: This route receives a POST request containing the message to send, and sends an SMS with that information./view-sms-status
: This route retrieves all of the webhook request data from the CSV file and renders it in a table for easy viewing.
The three routes will be handled by statusHandler()
, sendSMSHandler()
, and viewSMSStatusHandler()
, respectively, which we'll define shortly.
Configure the Go application to receive status updates from Twilio
Twilio sends status callbacks as x-www-form-urlencoded POST requests to the URL you specify. These callbacks provide important real-time data about the status of SMS messages your application sends.
To process these callbacks, your Go application must be able to parse the incoming data and respond accordingly. This is typically done by setting up a route that listens for POST requests on a specific endpoint and extracts the relevant information from them.
The data sent by Twilio usually includes fields such as the message's SID, a unique identifier for the message, the recipient’s phone number, your Twilio phone number, the current delivery status (sent
or delivered
), and, optionally, an error message if something went wrong. These fields help you track each message's delivery lifecycle, confirm successful deliveries, and identify any issues that may have occurred.
To handle this in Go, define a function that reads and logs this information for further processing, by adding the following code to the end of main.go.
statusHandler()
retrieves several fields from the webhook POST request and writes them to the CSV file by calling writeStatusData()
. If the data is successfully written, then an HTTP 200 OK status code is returned. Otherwise, an HTTP 400 Bad Request status code is returned. writeStatusData()
just opens the application's CSV file and appends the information to the end of it, and closes the file.
Add a function to send SMS with Twilio
Next, let's add a function that sends an SMS to the user's phone number using the Twilio Programmable Messaging API. To do this, add the following function to the main.go file.
sendSMSHandler()
retrieves the SMS data from the request and passes it to sendSMS()
, which initialises a Twilio Rest Client object to send the SMS using Twilio's Programmable Messaging API. If the SMS fails to send, the reason why is logged. If the message was sent, the newly created message's SID is printed out.
Feel free to refactor the code to return other details returned from the API call.
View SMS Status
Next, it's time to implement the ability to view the logged webhook status updates. To do that, first, add the following code to the end of main.go.
Working from top to bottom, the code defines two structs. The first models the webhook status information stored in the CSV file. Note the JSON tags for each field. These match the respective columns in the header row of the CSV file which you created earlier. The second struct stores a list of the first, and is passed, later, to render the status update template.
Then, comes viewSMSStatusHandler()
. This reads the status updates from the application's CSV file by calling readCSVFile()
, then renders the view-status.tmpl Go template with the retrieved status information, rendering it in a table for easy viewing. Finally, readCSVFile()
is defined which retrieves and returns any records from the CSV file, minus the header record.
Now, create a new directory named templates, and in that directory create two files. The first is named base.tmpl. The second is named view-status.tmpl. Then, in templates/base.tmpl, add the following code.
As the name implies, this is the base template, containing the core page elements, e.g., the head
, body
, and footer
tags. It also defines two blocks:
title
, which stores the page's titlemain
, which stores the route-specific code
While not strictly necessary, this approach has the benefit of letting you store route-specific code in a route-specific template, which we'll do now.
In templates/view-status.tmpl, add the following code:
This template sets the page's title to "SMS' Status", and body (main
) to a table containing a row for each status record retrieved from the CSV file.
Implement logging for SMS status updates
To effectively track and debug SMS delivery, it's important to log all status changes. So, this section focuses on setting up a robust logging system in Go, specifically one that logs details of sent Twilio SMS messages to both a file and the console.
To do that, add the code below to the end of main.go.
Expose your local application to the public internet
Since Twilio needs to reach your "/sms" endpoint. So, we'll use ngrok to expose the application to the web. Open a terminal and run the following command:
Ngrok will generate a forwarding URL (e.g., https://1234-abc.ngrok.io), which you can see in the screenshot below, that forwards requests to your local server. You will use this URL to configure the webhook in your Twilio dashboard so that Twilio can send SMS status updates directly to your "/sms" endpoint.


Now, copy the generated Forwarding URL. Then, paste it in place of <ngrok_forwarding_url>
in .env. Then, In your Twilio Console dashboard, navigate to Phone Numbers > Manage > Active Numbers.


There, click on your Twilio number, go to the Configure tab, and under the Messaging Configuration section, configure the Twilio webhook by setting:
- A message comes in to "Webhook"
- A message comes in's URL field to the ngrok Forwarding URL with "/sms" append at the end
- A message comes in's HTTP field to GET
After that, click on the Save configuration button to save the settings, as shown in the screenshot above.
Then, replace <ngrok_forwarding_url>
in .env with the ngrok Forwarding URL as well and save the file.
Test the application
To test the application, you need to start the application development server. To do that, open another terminal tab or window and run the command below:
Proper testing ensures your SMS tracking system works as expected before going live. To do that, use curl to send an SMS, by running the command below in a new terminal tab or window, after replacing <Your phone number>
with your E.164-formatted mobile/cell phone number.
Alternatively, if you prefer Postman, create a new POST request to http://localhost:8080/send-sms. Click the Body tab, then click x-www-form-urlencoded, as in the screenshot above. Then, add two keys: "To" and "Body", and set them to your E.164-formatted mobile/cell number and the message body of your choice, respectively. After you're prepared the request, click Send to send it.
Regardless of your choice of network testing tool, you'll shortly receive an SMS on your phone with the message body that you provided.
Finally, open http://localhost:8080/view-sms-status in your browser of choice, where you'll see it print out a list of status records, similar to the screenshot below.


That's how to build a real-time SMS status tracking and logging using Go and Twilio
With just a single route, a Twilio webhook, and some HTML, you now have a functional system that captures incoming messages and status updates, logs them cleanly, and displays them in real-time through a web interface.
This setup is not only lightweight and efficient but also flexible enough to expand with features like database storage, notifications, or analytics. Whether you're building for monitoring, debugging, or insight into SMS flows, this project gives you a solid foundation to build upon.
David Fagbuyiro is a software engineer and technical writer who is passionate about extending his knowledge to developers through technical writing. You can find him on LinkedIn .
The log icon was created by juicy_fish and the tracking icon was created by iconixar on Flaticon.
Related Posts
Related Resources
Twilio Docs
From APIs to SDKs to sample apps
API reference documentation, SDKs, helper libraries, quickstarts, and tutorials for your language and platform.
Resource Center
The latest ebooks, industry reports, and webinars
Learn from customer engagement experts to improve your own communication.
Ahoy
Twilio's developer community hub
Best practices, code samples, and inspiration to build communications and digital engagement experiences.