name: onesignal-templates
description: Use this skill when the user wants to create, design, edit, duplicate, or reason about a OneSignal Template — reusable blueprints for push notifications, email, or SMS. Triggers on "create a template", "save this as a template", "edit my push/email/sms template", "what's a template_id", "use a template in a journey / API send", "import an email template", "copy a template across apps", or any reusable-message-content question that isn't a one-off send.
OneSignal Templates Skill
Purpose
Help the agent create and reason about OneSignal Templates — reusable message blueprints for push, email, and SMS that centralize content and aggregate performance across sends.
This is a reasoning guide, not a script.
When to Use
Trigger phrases: "create a [push / email / SMS] template", "save this as a template", "edit / update / duplicate a template", "what's a template_id and where do I find it", "use a template in a Journey", "use a template via API", "import / forward an email template", "copy a template across apps", "why didn't my template content show up".
Lookalike intents that should NOT trigger this skill:
- A one-off send (no template) — use
messages skill. - An in-app message — covered by the
messages skill (in-app uses a different editor; the Templates page is push/email/SMS only). - A Journey design question — use
onesignal-journeys.
Key Concepts
A Template is a saved message blueprint:
- One template = one channel. Push, email, and SMS each have their own template type. In-app messages do NOT use the Templates page — they have their own composer (still reusable inside Journeys, but copied not referenced).
- Templates support Liquid syntax, Data Tags, and (for email) Data Feeds for personalization.
- Each template has a stable `template_id` (UUID) used in API sends and Journey message steps.
- Updating a template doesn't reset its aggregate stats; new sends accumulate alongside old ones.
- Past sends keep the content they were sent with — updates only affect future sends.
- API sends can override template fields per send (e.g. include
contents alongside template_id to change just the body for one send).
For full product rules (where templates live, copy-across-apps mechanics, deletion constraints, override semantics), read REFERENCE.md.
Decisions That Shape a Template
Each dimension has a priority tag:
- Channel (Critical) — push / email / SMS. Mutually exclusive; one template per channel. In-app is NOT a Templates-page channel.
- Purpose / category (Often defaultable) — campaign blueprint, transactional/event-driven, OTP/verification, abandoned-cart-style reminder, welcome series step. Affects what defaults make sense.
- Content (Critical for any creation) — headline, body, image (if push or email), buttons / action URL, sender name / from address (email), media URL (SMS/MMS).
- Personalization (Often defaultable) — Liquid placeholders for
user.first_name, tags, custom-event properties, Data Feeds. Default to "minimal personalization" unless the user signals otherwise. - Multi-language variants (Often defaultable) — usually English-only; offer to add variants if the app has language tags or Subscriptions in multiple languages.
- Channel-specific options (Often defaultable):
- Push: action buttons + Action IDs, big image, badge, sound, click action URL, channel category (Android), critical alert (iOS).
- Email: from name, from address, reply-to, subject + preview text, drag-and-drop vs HTML editor, unsubscribe link customization.
- SMS: phone number / sender ID, MMS media, link shortening, opt-out language.
- Labels (Almost always defaultable) — internal tags for filtering on the Templates page.
- Name (Almost always defaultable) — descriptive ("Welcome — Day 1 Push") so it's findable in dropdowns.
- Call
list_templates to detect duplicates ("Welcome Push" already exists?). If close matches exist, surface them and offer inspect/duplicate/edit instead of fresh creation. - For email templates, check
get_email_setup_status — if email isn't set up (domain not authenticated), flag that creating a template is fine but sending will fail. - For SMS templates, check
get_platform_settings for SMS — if SMS isn't set up (or 10DLC/toll-free not registered for US), flag that the template is creatable but sends will fail or be blocked. - If the user's prompt mentions personalization (
{{user.first_name}}, a tag, a custom event property), check that the underlying tag exists or list_custom_events for the event — Liquid that references a missing field renders empty. - For "use this template in a Journey" requests, also call
list_journeys to see if it's already wired in elsewhere.
How to Reason About Questions
- Identify the channel from the user's prompt. If unclear, that's the FIRST question.
- Walk the other Decisions; mark each Specified / Defaultable / Open.
- Ground in tools (above) — many "Open" dimensions become "Specified" once you've checked existing data and setup state.
- Skip AskUserQuestion entirely for fully-specified prompts. Summarize with assumptions.
- Otherwise bundle 1–4 most decisive open dimensions into ONE AskUserQuestion call.
Ambiguity to Watch For
- "template" without channel — clarify push vs email vs SMS. They have very different fields and editors.
- "transactional" — usually means event-driven (paired with a Custom Event in a Journey or with a
template_id in an API call). Confirm whether the user wants to design the template now and wire it up later. - "abandoned cart template" — they probably want both (a) a template AND (b) a Journey wired to it. Offer to load the journeys skill next.
- "like the one I already have" — duplicate vs reference. Templates are referenced by
template_id; "like the one" usually means duplicate-and-modify. - "forward my Mailchimp template" — they want Email Template Forwarding. Surface that as the path; don't paste HTML manually.
- "copy this template to another app" — point to the Copy Template to Another App API; one-time copy, not a live sync.
- "why isn't my personalization rendering" — almost always: missing tag/property, wrong Liquid syntax, or sent before the tag was set. Diagnose.
Defaults & Best Practices
Apply silently and surface as assumptions:
- For push: default to no big image, no action buttons, click action URL = the user-provided link or "open app" if none given.
- For email: HTML editor only if the user pasted HTML; otherwise drag-and-drop. Default
from name to the app name. reply-to defaults to from address. - For SMS: default to plain SMS (not MMS) unless an image was provided. Always include a "Reply STOP to opt out" line for US sends — required for compliance.
- For all channels: default minimal personalization unless the user signals otherwise. Suggest a name based on purpose ("Welcome — Day 1 Push", "OTP — Verification").
Best practices:
- Give templates descriptive names so they're easy to find in Compose dropdowns and Journey step pickers.
- Use Labels to organize templates by use case (campaign / transactional / journey-step).
- For multi-channel campaigns, create one template per channel rather than trying to make one template "do" multiple channels (you can't — one channel per template).
For more depth (full Liquid syntax, Data Feeds for email, multi-language variant mechanics, copy-across-apps, deletion constraints), read REFERENCE.md. For full reasoning traces, read EXAMPLES.md.
Summary and Approval
Every summary must include:
- Template name + channel + (optional) labels.
- Content in human-readable form (subject + preview + body for email; headline + body + click action for push; body + media + opt-out for SMS).
- Personalization — list every Liquid placeholder used and the source field.
- Channel-specific options (sender, action buttons, big image, etc.).
- Assumptions — every default applied so the user can correct them.
- Must-mention warnings for this domain:
- Templates are tied to a single channel — one template per channel; create separate templates for multi-channel campaigns.
- Updating a template doesn't reset stats; past sends keep their original content.
- You cannot delete a template that's in use by a Journey — remove it from the Journey first or delete the Journey.
- Email Template Forwarding is the recommended path for migrating from another ESP.
- Copy Template to Another App is a one-time copy, not a live sync — edits don't propagate.
- For SMS, Liquid that references a missing tag renders empty (not as the placeholder text).
Require explicit user approval before creating, updating, or deleting a template. For deletion, also require an extra confirmation and remind the user it's irreversible.
Anti-Patterns
Avoid:
- Suggesting one template can serve multiple channels — false. One channel per template.
- Pasting a long HTML email template directly into Liquid; use the email forwarding path or the drag-and-drop editor.
- Using
{{user.tags.<name>}} placeholders without confirming the tag exists; render-empty bugs are silent. - Recommending the user delete a template that's still attached to a live Journey — the delete will fail.
- Designing an "in-app template" through the Templates page — in-app messages have their own composer, not the Templates page.
- Hardcoding values that should be Liquid (e.g. literal "Hi John" instead of
{{user.first_name | default: "there"}}). - Reproducing this skill's example wording verbatim — derive your own from the user's prompt.
Supporting Files
REFERENCE.md — full content field catalog by channel, Liquid + Data Tags + Data Feeds reference, multi-language variant mechanics, copy-across-apps API, deletion constraints, override semantics for API sends.EXAMPLES.md — worked traces (vague request, push template, email forwarding migration, OTP/transactional, multi-language, "why isn't my personalization rendering").