Why Meta rejects templates without explaining
Meta's template review system is automated, fast, and infuriatingly opaque. A rejected template returns either "TAG_CONTENT_MISMATCH", "INVALID_FORMAT", or worst of all, "POLICY_VIOLATION" with no further information. The actual rules they apply are public, just spread across half a dozen Meta documentation pages.
This linter consolidates the rules we have learnt from operating NuvenarHub at scale across 100+ WhatsApp accounts and hundreds of submitted templates. It catches roughly 85% of the rejections we have seen.
The five rejection reasons that account for 80% of failures
- Category mismatch: Marketing language in a Utility template, or vice versa. Most common rejection by a wide margin.
- Variable adjacency: Two placeholders touching with no separator. Surprisingly common in copy-pasted templates.
- URL shorteners: Bit.ly and friends are hard-blocked. Use full URLs on your own domain.
- Body at edge: Variable at the very start or very end of the body. Meta's sample-data validator struggles with these.
- Aggressive caps: More than 60% capital letters reads as spam to the classifier.
What the linter does not check
- Business verification status. Unverified businesses get rejected more aggressively. The linter cannot see your verification status.
- Sender quality rating. A Red-rated number gets templates blocked regardless of content.
- Sample data realism. Meta wants believable sample values when you submit. {{1}} = "Smith" passes; {{1}} = "XXX" fails.
- Brand similarity. Templates impersonating major brands get rejected manually.