Writing for product

Copy patterns for buttons, dialogs, empty states, onboarding, errors, and accessibility that span components.


Component-specific copy lives in each component's own design docs, in its Content section. This page covers the patterns that span components: the message types and interaction moments that show up across the product.

Accessibility and alt text

Alt text makes images accessible to people who use screen readers and provides context when images don't load. Every informative image needs alt text, and decorative images should use alt="" so screen readers skip them.

Good alt text describes meaning and context rather than visual detail, and stays within the character guidance. Don't open with "Image of" (screen readers already announce that it's an image), and don't repeat the caption. Use the same word choices as the nearby body text and captions so the image and the copy around it read as one description.

table
UseInstead of
A bar chart showing email open rates by day, peaking on Tuesday.A colorful bar chart with blue and red bars on a white background.
A campaign builder showing three connected steps: trigger, filter, and email.img_campaign_flow_v2.png
A tooltip reads "Number of people who received this message" when hovering over the Delivered metric.A mouse cursor hovers over a small circular icon next to the word Delivered and a tooltip box appears below it with text inside.

Alt text in Customer.io contexts

Empty state illustrations are usually decorative. If the heading and body copy already convey the message, use alt="". Charts and data visualizations are the opposite case: describe the key insight, not the structure, as in "Open rates peaked at 42% in March, driven by the re-engagement campaign." For complex charts, note the general pattern and link to the underlying data.

Buttons and action labels

A button label starts with a verb, stays short (see character guidance), and is specific enough to be self-explanatory without its surrounding context. Generic verbs like "Submit", "Confirm", and "OK" require people to hold that context in their heads to understand what will happen. Specific verbs like "Delete campaign" and "Send newsletter" let people act with confidence. This matters most for destructive actions, where a vague label can have significant consequences. If a label uses the word "Yes", pair it with the action that will take place: "Yes, delete snippet".

Prefer "Cancel" for a plain dismiss, but a specific dismiss verb is better when it clarifies what staying or leaving does ("Keep my account", "Go back"). Never use "No", "Never mind", or "Close". When a button opens a dialog or requires additional input before the action completes, add an ellipsis (…); see Ellipses for the full rule.

Do
  • Send campaign
  • Delete segment
  • Permanently delete campaign
  • Cancel
  • Yes, delete snippet
Don't
  • OK
  • Confirm
  • Submit
  • Yes
  • Sure

Types

table
TypePatternExamples
Cancel / dismissCancel, or a specific dismiss verbCancel, Keep my account, Go back
ConfirmationVerb restating the actionDelete campaign, Send now
DestructiveDelete + objectDelete segment
Dialog-triggeringVerb…Export…
Loading statePresent participle…Saving…, Sending…
Primary actionVerb + objectCreate campaign, Add people, Send broadcast
ProgressiveForward-motion verbNext, Continue, Set up object
SaveSave / Save changes / Save and closeMatch to interaction model

Character guidance

These are recommended maximums. Treat them as a ceiling, not a target; shorter is usually better.

table
ElementRecommended max
Alt text140 characters
Badge / tag / status2 words
Button label1–3 words
Dialog title~60 characters
Empty state body2 sentences
Placeholder text~30 characters
Toast / notification~80 characters
Tooltip1 sentence

Component-specific content

For copy examples specific to a component, see that component's own design documentation:

Confirmation dialogs

Confirmation dialogs pause a destructive or consequential action long enough for the person to confirm it deliberately.

The title is in sentence case, ends with a question mark, and names the object being acted on. Generic titles like "Are you sure?" or "Delete?" force the person to look elsewhere to work out what they're confirming. The body states the consequence: if the action is irreversible, say so explicitly, and if it's reversible within a time window, state the window. The confirm button follows the button rules and restates the action. Cancel is always present and visually de-emphasized.

table
ElementPatternExample
BodyConsequence. State if irreversible, or the recovery window if reversible.This campaign will be deleted. This cannot be undone.
CancelCancelCancel
ConfirmVerb + objectDelete campaign
TitleAction + object name?Delete Q3 Re-engagement?

Empty states

An empty state tells the person what's missing and, when there's a next step, gives them a way to take it. The heading is in sentence case with no period; the body is written in full sentences, with periods, and stays within the character guidance. Include a primary action whenever one exists, and don't apologize for the emptiness. Vague filler like "Nothing to see here." or "There is no content available at this time." tells the person nothing about what belongs here or what to do next.

Be mindful of what you put here. Critical information that disappears once the state is populated belongs somewhere permanent.

No data

No data exists yet. Tell the person what will appear here and give them a clear action to get started.

table
ElementPatternExample
ActionPrimary action buttonCreate segment
BodyWhat you can do with itSegments let you target specific groups based on behavior or attributes.
HeadingWhat this isNo segments yet.

No results

Data exists, but nothing matched. Echo the query so the person can see what was searched, and suggest a way to recover.

table
ElementPatternExample
BodyRecovery action or suggestionTry a different name or check your filters.
HeadingNo results for "[query]"No results for "welcome series"

Promotional

A promotional empty state introduces a feature the person hasn't used yet. The tone is benefit-led and outcome-first, closer to marketing copy than product copy, and it pairs with a hero image depicting a stylized future state.

table
ElementPatternExample
BodyWhat this makes possible, in 1–2 benefit-first sentences.Organize your messaging strategy around your business goals. See which messages drive results.
CTAInvitation verbCreate goal
HeadlineOutcome-focused statementTurn messaging into a growth engine.
Do
  • "Automate your customer journeys" (leads with the benefit)
Don't
  • "You have no campaigns" (frames the promotion as an absence)
  • "Unlock powerful automation" (see forbidden words)

Errors and system feedback

Error states are high-anxiety moments. Vague errors ("Something went wrong") make people feel helpless, and blame-framed errors ("You entered an invalid value") create frustration. A good error message turns a moment of friction into a moment of guidance. It is often the difference between a person recovering independently and submitting a support ticket.

To get there, answer as many of these as you can:

  1. What happened? State the problem plainly.
  2. Why? Give context when it's honest and useful.
  3. What now? Give a specific next step, and always offer a recovery path when one exists.

Never say "Oops", and never use exclamation points in an error.

Destructive warnings (before action)

State the consequence. If the action is reversible within a time window, say so. It's more informative and less alarming than stating only that something will be deleted.

Do
  • Deleting this segment will remove it from 3 active campaigns. This cannot be undone.
  • Unsubscribing these 1,400 people will opt them out of all messages.
Don't
  • Warning: This action may have consequences.

Payment and account errors

Use passive voice in payment, security, and account errors where active voice would imply blame or cause alarm. "Your payment was declined" reports a fact; "We declined your payment" picks a fight.

table
UseInstead of
Your account has been disabled.We disabled your account.
Your payment was declined.We declined your payment.

Permission errors

Name what the person can't do and who can help. A bare "Access denied" leaves them with no way forward.

table
UseInstead of
[Feature] isn't available on your plan. Contact your admin to access this feature.You can't do that.
You don't have permission to delete campaigns. Contact your admin to update permissions.Access denied.

Success messages

Confirm what happened and keep it brief, with no editorializing. A warm tone belongs to genuine milestones (a welcome, a thank-you), not routine confirmations; see Exclamation points.

table
UseInstead of
2,400 people added to [segment name].Great work! You've added people to your segment.
[campaign name] saved.Awesome! Your campaign has been saved successfully.

System errors (something failed)

Say what didn't happen and what the person can try. "An error occurred" is technically true and practically useless.

table
UseInstead of
Your changes couldn't be saved. Check your connection and try again.An error occurred. Please try again later.
Oops! Something went wrong.

Validation errors (inline, adjacent to field)

Frame validation errors as instructions, not accusations. Tell the person what a valid value looks like rather than only that theirs isn't.

table
UseInstead of
Enter a valid email address.Invalid input.
Password must be at least 8 characters.Error.
Segment name is required.Please check this field.

Onboarding

Lead each step with the task rather than background information, and give one instruction per step. Always show progress ("step X of Y" or an equivalent) so the person knows how much is left. When they finish, confirm completion explicitly: say what was set up and what they can do now. "Setup complete!" celebrates without informing.

table
UseInstead of
"You're all set. Your campaign is ready to send.""You did it!"
"Your first event was tracked. Customer.io is now receiving data.""Setup complete!"