As of December 2024, Webnus’ Modern Events Calendar doesn’t support sending text (SMS) reminders out of the box. However, you can fork its code to be able to do so; here’s one approach below, using Twilio (which costs about $7 per 1k messages):
Sending an SMS at time of registration
- Create the following new PHP file in your theme, let’s call it mec-sms.php. Be sure to specify your account_sid, auth_token, and twilio phone number.
<?php
class DsaMecSms
{
const ACCOUNT_SID = 'XXX';
const AUTH_TOKEN = 'XXX';
const TWILIO_PHONE_NUMBER = '+19704271234'; // Your Twilio phone number
const TWILIO_API_URL = 'https://api.twilio.com/2010-04-01/Accounts';
const DSA_SMS_DEBUG = true;
private $postData;
public function __construct($postData)
{
$this->postData = $postData;
}
public function processBooking()
{
try {
$bookingData = $this->postData;
if (self::DSA_SMS_DEBUG) {
$this->logToFile("Received Booking Data: " . print_r($bookingData, true));
}
$bookingId = $bookingData['id'] ?? null;
$eventTitle = $bookingData['event']['title'] ?? 'Unknown Event';
$startDate = $bookingData['start'] ?? 'Unknown Start Date';
$endDate = $bookingData['end'] ?? 'Unknown End Date';
if (self::DSA_SMS_DEBUG) {
$this->logToFile("Processing event: $eventTitle, Booking ID: $bookingId");
}
$attendees = $bookingData['attendees'] ?? [];
foreach ($attendees as $attendee) {
$attendeeName = $attendee['name'] ?? 'Unknown Name';
$phoneNumber = $attendee['fields'][0]['value'] ?? null;
if (!$phoneNumber) {
$this->logToFile("Skipping attendee due to missing phone number.");
continue;
}
$this->sendConfirmationMessage($attendeeName, $eventTitle, $startDate, $phoneNumber);
}
} catch (Exception $e) {
$this->logToFile("Error in processBooking: " . $e->getMessage());
throw $e;
}
}
private function sendConfirmationMessage($name, $event, $start, $phone)
{
$message = $this->generateConfirmationMessage($name, $event, $start);
if (self::DSA_SMS_DEBUG) {
$this->logToFile("Sending Message: $message to $phone");
}
$this->sendSMS($phone, $message);
}
private function generateConfirmationMessage($name, $event, $start)
{
$eventDate = date('l, F j, Y', strtotime($start));
$eventTime = date('g:i A', strtotime($start));
$eventLocation = "Student Resolution Center";
return sprintf(
"Workshop reminder: %s on %s at %s with the Student Resolution Center. Call 970-491-7165 to cancel.",
$event,
$eventDate,
$eventTime
);
}
private function sendSMS($toPhone, $message)
{
$url = sprintf(
"%s/%s/Messages.json",
self::TWILIO_API_URL,
self::ACCOUNT_SID
);
$postFields = http_build_query([
'To' => $toPhone,
'From' => self::TWILIO_PHONE_NUMBER,
'Body' => $message,
]);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_USERPWD, self::ACCOUNT_SID . ':' . self::AUTH_TOKEN);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/x-www-form-urlencoded']);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode != 201) { // Twilio returns 201 for successful message creation
$this->logToFile("Failed to send SMS to $toPhone. Response: $response");
throw new Exception("Error sending SMS: $response");
}
$this->logToFile("SMS sent successfully to $toPhone.");
}
private function logToFile($message)
{
$logFile = __DIR__ . '/mec-booking-data.log';
file_put_contents($logFile, date('[Y-m-d H:i:s] ') . $message . PHP_EOL, FILE_APPEND);
}
}
// Prevent the entry-point code from running if included directly
if (!defined('DSA_SMS_SCRIPT')) {
header('Content-Type: application/json');
try {
$input = $_POST;
if (empty($input)) {
$input = json_decode(file_get_contents('php://input'), true);
}
if (!$input) {
throw new Exception("Invalid or missing input data");
}
$dsaMecSms = new DsaMecSms($input);
$dsaMecSms->processBooking();
echo json_encode(['status' => 'success', 'message' => 'Booking processed successfully.']);
} catch (Exception $e) {
http_response_code(400);
echo json_encode(['status' => 'error', 'message' => $e->getMessage()]);
}
exit; // Prevent further execution
}
- Next enable the booking module at https://YOURSITE/wp-admin/admin.php?page=MEC-settings&tab=MEC-booking.
- Under the Advanced tab, tick the box for “Enable webhooks module”
- In this example, I checked, “Auto verification for free bookings” to avoid needing to verify bookings
- Next visit Booking –> Booking Form, as you will need to add a new attendee field for Telephone number and hit Save.
- Next you should see a Webhooks link under the M.E. Calendar sidebar. E.g., https://YOURSITE/wp-admin/edit.php?post_type=mec-webhooks
- Click Add Webhook.
- Leave the hook as Booking Confirmed, Request as POST, and enter the url path to the file you just created. E.g., https://YOURSITE/wp-content/themes/hello-child/mec-sms.php and click Publish
- Be sure to create a fake event that has at least one ticket option so that visitors can book themselves
Sending an SMS Reminder
If you additionally want to send a reminder text message in advance, here’s how:
- Go to Notifications –> Booking Reminder and click, “Enable booking reminder notification”
- In this example, I’m going to send reminders one day in advance, so set Hours to be 24 and enter a subject and body. Click Save
- Next we are going to have to fork one of MEC’s files to include SMS functionality. Open/wp-content/plugins/modern-events-calendar/app/crons/booking-reminder.php in your editor of choice
- We are going to replace the foreach loop on lines 106-115. First remove those lines and paste in the following code:
foreach ($bookings as $booking) {
// Skip if the booking's post status is 'trash'
if ('trash' === get_post_status($booking->ID)) {
continue; // Skip this iteration and move to the next booking
}
$event_id = get_post_meta($booking->ID, 'mec_event_id', true);
$end = $db->select("SELECT `tend` FROM `#__mec_dates` WHERE `post_id`='" . $event_id . "' AND `tstart`='" . $booking->mec_timestamp . "' LIMIT 1", 'loadResult');
$timestamps = $booking->mec_timestamp . ':' . $end;
$result = $notif->booking_reminder($booking->ID, $timestamps);
if ($result) {
$sent_reminders++;
}
try {
// Define constant to skip direct entry-point code
define('MEC_SMS_SCRIPT', true);
// to include the SMS functionality
require_once get_stylesheet_directory() . '/mec-sms.php';
// Fetch phone number from serialized attendees data
$attendees_data = get_post_meta($booking->ID, 'mec_attendees', true);
$attendees_data = maybe_unserialize($attendees_data); // Unserialize if needed
// The following code will help you determine the position of phone # in the array
//echo '<pre>';
//print_r($attendees_data);
//echo '</pre>';
if (is_array($attendees_data) && isset($attendees_data[0])) {
// Extract phone number from the 'reg' array (index 3)
$phone = $attendees_data[0]['reg'][2] ?? null;
if ($phone) {
$message = sprintf(
"Reminder: Your event '%s' is starting soon. Please be on time.",
get_the_title($event_id) // Fetch the event title
);
// Prepare the booking data in the format expected by the DsaMecSms class
$postData = [
'id' => $booking->ID,
'event' => [
'title' => get_the_title($event_id),
],
'start' => date('Y-m-d H:i:s', $booking->mec_timestamp),
'attendees' => [
[
'name' => $booking->post_title,
'email' => '', // Extract email if available, or set as blank
'fields' => [
['value' => $phone], // Phone number field
],
],
],
];
// Instantiate the DsaMecSms class
$smsHandler = new DsaMecSms($postData);
// Process the booking to send SMS
$smsHandler->processBooking();
} else {
//echo 'Phone number not found.';
}
} else {
//echo 'No attendee data found.';
}
} catch (Exception $e) {
echo 'Message: ' . $e->getMessage();
}
}
- Next let’s create an event that is 24 hours into the future. Once that is done, register for the event using a valid phone number that can receive text messages. You should receive both an e-mail and text reminder.
- Finally, per the directions at https://YOURSITE/wp-admin/admin.php?page=MEC-settings&tab=MEC-notifications#booking_reminder you will need to set a cron job that hits your site once an hour. I use UpTime robot for this task, specifically set to hit https://YOURSITE/wp-content/plugins/modern-events-calendar/app/crons/booking-reminder.php once per hour.
That’s it! Given that we have just forked the MEc plugin, you will need to remember to overwrite lines 106-115 in the booking-reminder.php file each time you upgrade, but other than that, you should be all set to send e-mail and text reminders to your visitors!