Hypertext Rails
Documentation
Getting Started
Communication Center
- Automation Workflow Flow
- Trigger Events and Cadence Rules
- Fallback Channel Implementation
- Fallback Channel Testing (dev)
- Twilio SMS Integration Guide
- Email Tracking Setup (sent, delivered, failed, open, click)
- SMS Tracking & Twilio Free Tier
- AWS SES Delivery Tracking (console setup for delivery webhook)
- Compiled Template Guide (layout, components, variables)
- Workflow & Template Features (project-driven recipients, multi-project format)
Procore / Project Groups
- Procore Integration — Complete Guide (installation single/grouped, project groups, token storage, why no migration)
Other Features
- Heartbeats Dashboard (kiosk connectivity, queries, sample data)
SMS Tracking & Twilio Free Tier
What We Track for SMS
| Event | How it's tracked | Where |
|---|---|---|
| Sent | Recorded when Twilio API accepts the message | SmsDeliverySendJob sets status: 'sent', stores external_message_id (Twilio Message SID), creates CommsEvent with event_type: 'sent' |
| Delivered | Twilio POSTs to our webhook when status becomes delivered |
POST /webhooks/twilio/status → Twilio::WebhooksController#status finds delivery by MessageSid, updates CommsDelivery to status: 'delivered', creates CommsEvent |
| Failed/Undelivered | Same webhook with status failed or undelivered |
Same controller updates status and creates CommsEvent |
SMS does not support open or click tracking (no tracking pixel or link wrapping for SMS in MVP).
How the Status Callback Works
Twilio needs to POST to our app when message status changes (e.g. sent → delivered or failed). We support two ways to get that callback:
Per-message callback (recommended)
When sending each SMS, we passstatus_callbackandstatus_callback_method: 'POST'in the API request (TwilioService#send_sms). The URL is built from your app’s existing public host — the same one already in Rails config (action_mailer.default_url_options[:host]), orBASE_HOST_URLif you use that. No mail-related or Twilio-specific env vars are required for SMS; we just use the app’s public host.
So every SMS asks Twilio to callhttps://YOUR_APP_HOST/webhooks/twilio/status. No Twilio Console setup required for the callback URL.Phone number–level callback
You can also set the Status Callback URL on the Twilio phone number (or Messaging Service) in the Twilio Console, or viarails twilio:configure_webhooks[BASE_URL]. That sets a global callback for all messages from that number.
If both are set, Twilio will use the per-message URL when provided. Per-message callback is more reliable for trial/Messaging Service setups.
Twilio Free / Trial Tier
- Trial accounts can only send SMS to verified phone numbers (verified in Twilio Console).
- Webhook URL must be publicly reachable over HTTPS. Twilio will not call
http://localhost:3000. For local dev use a tunnel (e.g. ngrok) and set your app’s host to that URL sostatus_callbackis correct. - You don’t “confirm” a Twilio webhook like SNS. Twilio simply POSTs to the URL you give. If the URL is wrong or unreachable, you just won’t get status updates; sending can still succeed.
“Couldn’t confirm Twilio” on free tier
Often this means one of:
- Trial account – You can only send to numbers you’ve verified in Twilio Console. Verify the recipient number under Phone Numbers (or use the Messaging Sandbox and join with a code).
- Webhook URL not reachable – For status callbacks to work,
https://YOUR_HOST/webhooks/twilio/statusmust be reachable from the internet. Use ngrok (or similar) in development and setBASE_HOST_URLorMAIL_APP_HOST(andaction_mailer.default_url_options[:host]) to that host. - Wrong host in config – The per-message
status_callbackuses the same host as the rest of your app (Railsdefault_url_options[:host], orBASE_HOST_URLif set). If that points to localhost or a stale URL, Twilio will POST to the wrong place.
Checklist for SMS delivery tracking on free tier
- [ ] Twilio credentials set:
TWILIO_ACCOUNT_SID,TWILIO_AUTH_TOKEN,TWILIO_FROM_NUMBER(or Messaging Service). - [ ] For trial: recipient number verified in Twilio Console, or use Messaging Sandbox and have recipient join with code.
- [ ] App base URL is public HTTPS. Your app already has a host in config (
action_mailer.default_url_optionsinconfig/environments/*.rb). For local dev with ngrok, set that host to your ngrok URL (e.g. in config or viaBASE_HOST_URL). - [ ] No firewall blocking Twilio;
/webhooks/twilio/statusreturns 200 and does not require auth (signature is validated inside the controller).
After sending an SMS, check comms_events for that delivery: you should see sent from the job and, once Twilio confirms delivery, delivered from the webhook.
Related
- TWILIOSMSCOMPLETE_GUIDE.md – Setup, sandbox modes, and troubleshooting
- EMAILTRACKINGSETUP.md – Email sent/delivered/open/click
- COMMUNICATIONCENTERANALYTICSSPECSUMMARY.md – Tracking capabilities by channel