Skip to main content
iVentureTeam

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.

Siddharth JambukiyaSiddharth JambukiyaOdoo Techno-Functional Consultant
August 19, 2026Updated August 19, 20266 min read
Odoo 19 Send SMS dialog with the sms_widget textarea showing the live character count and number of SMS segments below the message.
Technical namesms_widget
Field typestext, char, html (inherited from the text field)
Viewsform
Modulesms, extended by mass_mailing_sms
Used in core6 occurrences across 2 modules: the SMS composer wizard (sms) and SMS Marketing mailings (mass_mailing_sms)
VersionsOdoo 20.0, Odoo 19.0, Odoo 18.0, Odoo 17.0, Odoo 16.0
No-code setupNo: it is wired into the SMS composer and mailing forms in XML
Alternativestext, text_emojis, html_mail

What the SMS widget does

Anywhere Odoo lets you write a text message, the Send SMS action on a contact, the body of an SMS Marketing campaign, the composer behind automated SMS, the text box is sms_widget. It looks like a normal multiline text field with an emoji picker, but below it sits a line of arithmetic that updates on every keystroke: character count and number of SMS segments.

That arithmetic is the widget's whole reason to exist. SMS is billed per segment, and segment size depends on encoding. The widget classifies your message with one regex: if every character belongs to the GSM-7 charset (the 7-bit alphabet from the GSM 03.38 standard, which covers basic Latin, digits and a set of accented letters), the message packs 160 characters into one SMS and 153 into each segment of a longer one. A single character outside that set, a curly apostrophe pasted from Word, an emoji, a script like Devanagari, silently switches the entire message to Unicode: 70 characters per single SMS, 67 per segment.

It is built on top of the emoji text field, which itself extends the standard text widget, so everything you know about multiline text fields applies here too.

What this means for your team

For anyone running SMS campaigns, this widget is the difference between predictable and surprising invoices.

The one-character cliff is real money. A 150-character message in GSM-7 is one segment. Paste in a single smart quote and the same message becomes Unicode: now it is three segments, three times the credits, multiplied by every recipient in the campaign. The counter makes that visible before you hit send, but only if your team knows to watch it. We train marketing teams to draft SMS copy directly in Odoo rather than pasting from word processors, precisely because of this.

The counter also protects deliverability. The blur check that rejects whitespace-only messages, and the SMS Marketing additions that count the opt-out link and tracker URLs, exist so the number you see matches what the gateway actually bills.

Supported options in Odoo 19

Verified against fields_sms_widget.js in the Odoo 19.0 sms module. The widget declares no options of its own; the descriptor spreads the emoji text field's, which spreads the standard text field's, so the options below are inherited from text and behave identically here.

OptionTypeWhat it does
line_breaksbooleanInherited 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_fieldfield 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

How the SMS composer uses it

<field name="body" widget="sms_widget" default_focus="1"/>

On your own model's message field

<field name="reminder_message" widget="sms_widget" placeholder="Text sent to the customer..."/>

The field should be a Text field; the counter and emoji picker come for free. The sms module must be installed.

Segment math cheat sheet

GSM-7:    1-160 chars = 1 SMS, then ceil(n / 153) segments
Unicode:  1-70 chars  = 1 SMS, then ceil(n / 67) segments
Line breaks count as 2 characters. One non GSM-7 char = whole message Unicode.

Counting rules the counter lives by

Three behaviors from the source are worth pinning down precisely.

Line breaks are counted twice. The character count is content.length plus one extra for every newline. That mirrors the GSM standard, where a line feed in the extended table costs an escape character, and it is why a heavily formatted message runs out of room faster than its visible length suggests.

The whitespace guard runs on blur, not on save. Leaving the field with a message that contains only spaces or newlines pops a danger notification, "must include at least one non-whitespace character", and trims the value to empty. The record updates on every keystroke before that, so the guard is the last word.

SMS Marketing rewrites the message before counting it. The mass_mailing_sms module patches the widget for mailing.mailing records: every URL in the body is replaced by a placeholder the length of a link tracker URL, and if the mailing has the opt-out option enabled, the unsubscribe link's length is added on top. The counter then annotates itself, "(including link trackers and opt-out link)", so the segment estimate matches what actually leaves the gateway. Both placeholder lengths are fetched from the server per mailing.

Version compatibility

VersionStatusNotes
Odoo 20.0In developmentNot released. The source file on the development branch is byte-identical to 19.0.
Odoo 19.0VerifiedVerified against the shipped source.
Odoo 18.0VerifiedIdentical to 19.0 apart from the module pragma line.
Odoo 17.0VerifiedSame counting rules on the modern component API.
Odoo 16.0VerifiedSame 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

Odoo 20 is expected at Odoo Experience in Brussels, 24 to 26 September 2026. The notes below are read from the public development branch and are not final until release.

Nothing changes: the widget's source file on master is byte-identical to Odoo 19, including the encoding regex, the segment limits and the SMS Marketing patch points. Views and customizations should carry over untouched. We re-verify against the shipped release.

Common problems and fixes

SymptomCause and fix
The segment count tripled after a small editOne 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 lengthLine 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 characterThe 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 modelThe 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 moveA 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

WidgetBest forKey difference
sms_widgetMessage bodies that are actually sent as SMSLive encoding detection and per-segment cost math under the textarea
textPlain multiline text with no sending semanticsNo counter, no emoji picker, no whitespace guard
text_emojisNotes and comments where emojis helpThe emoji picker without any SMS counting; the base sms_widget extends
html_mailEmail bodies with formattingFull HTML editor with CSS inlining for mail clients; nothing SMS-related

If the field is not literally going out as a text message, skip this widget: the counter would only confuse users. Plain text or text_emojis covers notes, and html_mail covers email bodies.

Frequently asked questions

How many characters fit in one SMS in Odoo?+
160 if every character is in the GSM-7 charset, 70 if any character forces Unicode. Longer messages split into segments of 153 (GSM-7) or 67 (Unicode) characters, and sms_widget shows the resulting segment count live.
Why does my message say 2 SMS when it is under 160 characters?+
Something in it is not GSM-7, typically curly quotes or an emoji, which drops the single-SMS limit to 70 characters. Line breaks also count double. The counter reflects the encoding the gateway will actually use.
Does the opt-out link count against my SMS length?+
Yes. In SMS Marketing, when the unsubscribe option is enabled the widget adds the opt-out link's length to the count and says so under the counter, so the estimate matches what is billed.
Are URLs counted at their real length?+
In SMS Marketing campaigns, no: every URL is replaced by a link tracker placeholder of standard length before counting, because that is what recipients receive. In the plain SMS composer, URLs count at face value.
Can I use sms_widget on my own model?+
Yes: put widget="sms_widget" on a Text field in the form view, with the sms module installed. You get the counter, the emoji picker and the whitespace guard with no extra code.
Can I change the segment limits or disable the counter?+
Not through options; the limits and the counter are hardcoded. Extending the widget in JavaScript is the only route, and it is rarely worth it since the limits mirror the SMS standard itself.

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

How this page was produced

The counting rules on this page, the GSM-7 regex, the 160/153 and 70/67 limits, the double-counted newlines and the blur-time whitespace guard, were read from fields_sms_widget.js on the Odoo 19.0 branch, and the link tracker and opt-out padding from the mass_mailing_sms patch of the same widget. Version history was confirmed by diffing the file across the 16.0 through master branches. Spotted an error or a version difference? Tell us and we will correct the page.