sms_widget
The message box in Odoo's Send SMS dialog does live math while you type: sms_widget detects the character encoding, counts the characters, and tells you how many SMS segments, and therefore credits, the message will cost.
| Technical name | sms_widget |
|---|---|
| Field types | text, char, html (inherited from the text field) |
| Views | form |
| Module | sms, extended by mass_mailing_sms |
| Used in core | 6 occurrences across 2 modules: the SMS composer wizard (sms) and SMS Marketing mailings (mass_mailing_sms) |
| Versions | Odoo 20.0, Odoo 19.0, Odoo 18.0, Odoo 17.0, Odoo 16.0 |
| No-code setup | No: it is wired into the SMS composer and mailing forms in XML |
| Alternatives | text, text_emojis, html_mail |
What the SMS widget does
What this means for your team
Supported options in Odoo 19
| Option | Type | What it does |
|---|---|---|
line_breaks | boolean | Inherited from the text widget. Set to false to keep the message on a single line; remember each line break also costs two characters in the SMS count.(default: true) |
placeholder_field | field name (char) | Inherited from the text widget, where it is declared for Studio's Dynamic Placeholder property. The dynamic placeholder machinery itself is driven by the dynamic_placeholder option pair read in extractProps. |
The counters themselves are not configurable. There is no option to change the 160/153 and 70/67 limits, force an encoding, or hide the counter line; all of it is hardcoded in the component. Changing any of that means extending the widget in JavaScript.
Working examples
Counting rules the counter lives by
Version compatibility
| Version | Status | Notes |
|---|---|---|
| Odoo 20.0 | In development | Not released. The source file on the development branch is byte-identical to 19.0. |
| Odoo 19.0 | Verified | Verified against the shipped source. |
| Odoo 18.0 | Verified | Identical to 19.0 apart from the module pragma line. |
| Odoo 17.0 | Verified | Same counting rules on the modern component API. |
| Odoo 16.0 | Verified | Same counting rules on the legacy widget API (props.value); JS customizations differ. |
Upgrade note. The widget has existed since before Odoo 16 and its counting rules are unchanged. Odoo 17 rewrote it from the legacy widget API onto the modern component stack (record.data instead of props.value); JavaScript customizations from 16 need porting, but XML usage is identical across versions.
What is changing in Odoo 20
Common problems and fixes
| Symptom | Cause and fix |
|---|---|
| The segment count tripled after a small edit | One character outside the GSM-7 charset (smart quote, em dash, emoji) switched the whole message to Unicode: 70/67 limits instead of 160/153. Retype quotes and dashes as plain ASCII, or accept the Unicode cost if the emoji is worth it. The counter updates live, so check it before sending. |
| Character count is higher than the visible text length | Line breaks count as two characters each, and in SMS Marketing the opt-out link and link tracker placeholders are added to the count. Reduce line breaks and keep URLs short; the annotation under the counter tells you when tracker or opt-out padding is included. |
| A warning says the message must include a non-whitespace character | The blur handler rejects messages made only of spaces and newlines and trims the value to empty. Type actual content; the guard exists because gateways reject blank messages after billing the attempt. |
| The widget shows a missing-widget warning on your custom model | The sms module is not installed, so sms_widget is not in the fields registry. Add sms to your module's dependencies in __manifest__.py. |
| Emoji button inserts the emoji but the counter does not move | A JavaScript customization overrode _emojiAdded without updating the record, which is what triggers the recount. Call record.update with the textarea value in your override, as the stock _emojiAdded does. |
SMS widget vs the alternatives
| Widget | Best for | Key difference |
|---|---|---|
sms_widget | Message bodies that are actually sent as SMS | Live encoding detection and per-segment cost math under the textarea |
| text | Plain multiline text with no sending semantics | No counter, no emoji picker, no whitespace guard |
text_emojis | Notes and comments where emojis help | The emoji picker without any SMS counting; the base sms_widget extends |
| html_mail | Email bodies with formatting | Full HTML editor with CSS inlining for mail clients; nothing SMS-related |
Frequently asked questions
How many characters fit in one SMS in Odoo?+
Why does my message say 2 SMS when it is under 160 characters?+
Does the opt-out link count against my SMS length?+
Are URLs counted at their real length?+
Can I use sms_widget on my own model?+
Can I change the segment limits or disable the counter?+
SMS campaigns burning more credits than they should?
Encoding cliffs, tracker padding and opt-out links quietly multiply your per-message cost across thousands of recipients. We set up SMS Marketing in Odoo end to end: gateway integration, compliant opt-outs, templates that stay inside one GSM-7 segment, and automations that trigger them.
Set up SMS marketing properly