Skip to main content
This page is the authoritative reference for every structural rule Switchbord checks before submitting a template to Meta. Each section is keyed to the error code the client-side validator emits (see BORD-335) so you can jump straight from a red editor banner to the fix. All rules are enforced by both the Switchbord client-side linter and Meta’s submit-time validator. Meta’s human reviewer adds a second layer of content checks on top (see Marketing templates).

name-regex

Template names are used as stable identifiers across Meta, webhooks, and our database. Meta enforces lowercase-only characters so names are URL-safe and diff-friendly across BSPs. Rule: ^[a-z][a-z0-9_]{0,511}$ — lowercase letters, digits, and underscores only. No spaces, hyphens, uppercase, dots, or accented characters. Must be unique per WABA per language. DO
DON’T
Meta docs: Template guidelines — naming.

leading-variable

Meta rejects body text that starts with a placeholder because it renders awkwardly on mobile and gives the model no anchor for category classification. A body that begins with a name or greeting reads like a message; one that begins with {{1}} reads like a template leak. DO
DON’T
Meta docs: Message template guidelines.

trailing-variable

The mirror of the leading-variable rule. A body that ends on {{N}} — even with a trailing full stop — is rejected. Add at least one fixed word after the last placeholder, ideally a full sentence of context. DO
DON’T
Meta docs: Message template guidelines.

adjacent-variables

Two placeholders with only whitespace or punctuation between them are rejected. Meta cannot render the boundary cleanly and cannot classify the intent when the body is effectively a parameter list. Put at least one real word between every pair. DO
DON’T
Meta docs: Message template guidelines.

missing-example

Every {{n}} in a HEADER, BODY, or dynamic URL button must have a matching realistic example. Meta uses examples to render the preview shown to reviewers and to classify the template’s category. A template with placeholders and no examples is rejected at submit time. DO
DON’T
Meta docs: Create and submit a template.

example-count-mismatch

The length of the example array must equal the number of distinct placeholders. Three {{n}} tokens require exactly three example strings — not two, not four. This check runs per component (body, header text, URL button). DO
DON’T
Meta docs: Template parameters.

numeric-only-example

Example values must be realistic — that is, they should contain alphabetic characters or a clearly meaningful alphanumeric token (currency amount with symbol, a date string, an order code). A bare number, a single symbol, or a code-like string with no context is rejected because it does not represent how a real recipient will see the message. DO
DON’T
Bake the unit into the example — write "20%", not "20" with the % sitting adjacent in the body. That removes the “bare number” heuristic and renders identically. Meta docs: Example values.

sequential-numbering

Placeholders must start at {{1}} and run sequentially with no gaps and no duplicates. {{1}}, {{2}}, {{3}} is valid; {{1}}, {{3}} is not; {{2}}, {{3}} is not (must start at 1). The validator extracts the unique indices, sorts them, and checks the resulting list equals [1..N]. DO
DON’T
Meta docs: Template parameters.

params-words-ratio

A template where placeholders dominate the fixed text reads like a raw data dump and is flagged during content review. The Switchbord linter warns when the ratio of variables to total words exceeds roughly 1 in 4 — a template with three {{n}} tokens should have at least twelve words of fixed copy around them. DO
(12 fixed words around 3 placeholders) DON’T
(3 placeholders, 2 fixed tokens) Meta docs: Template quality.

length-caps

Each component has a hard character limit. Count the raw template string including placeholders — the runtime expansion does not count against the limit. DO
DON’T
Meta docs: Template components.

button-limits

Buttons have per-type hard caps. Exceeding any one cap rejects the whole template at submit. Dynamic URL buttons must have {{1}} as the only variable, appearing at the end of the URL path or query value — never in the hostname. DO
DON’T
Meta docs: Template buttons.

component-ordering

A template’s components must appear in the order HEADER → BODY → FOOTER → BUTTONS. Each component may appear at most once, except BODY which is required exactly once. Meta normalises the order in some cases but rejects duplicates and unknown types with code 100. DO
DON’T
Meta docs: Template components. Footers are for static, legally-important copy — the sender identity, the opt-out instruction, a disclosure. They cannot contain {{n}} placeholders. Put runtime data in the body. DO
DON’T
Meta docs: Template components — footer.

Quick-reference regex set

If you are writing your own validator or scripting bulk checks, the canonical regexes are:

See also