{{ contact.firstName }} once, and every recipient sees their own name.
Where each group works
Not every shortcode works in every email. Using one outside its context leaves it blank rather than raising an error.Customer details
Works in every email — broadcasts and automations.Hi Ada, — or Hi there, for a contact with no first name.
- Always add
| default:. Most contacts have only an email address, so without a fallback your email opensHi ,. - Always write
contact.in front.{{ firstName }}on its own silently fails in broadcast emails. {{ contact.fullName }}shows the email address when both names are blank. For greetings,{{ contact.firstName | default: 'there' }}is safer.
Store
Works in every email.- In broadcasts these work in the email body but not in the subject line. In automations they work in both.
{{ retainful_shop_url_with_coupon_code }}requires a coupon step in the workflow. In a broadcast it drops the coupon silently and links to your store.
Abandoned cart
- Keep the
.size > 0check. Without it, an email with no cart still shows the button, linking nowhere. See Hide empty values correctly. - The coupon version also requires a coupon step in the workflow.
Coupon
SAVE10XYZAB. Valid for 7 days. Expires March 05, 2026
- Each contact receives their own unique code.
- Always apply
| date:to{{ retainful_coupon_expiry_date }}. On its own it prints a raw timestamp. - The expiry clock starts when the coupon is created, so every email in a sequence shows the same date.
- Keep the
.size > 0check. With no coupon step,{{ coupon.expiration_days }}prints0and the rest print blank, so the email reads “Valid for . (0 days)”.
Summary block
Lists the items your customer ordered or left in their cart. Drag the block in and the editor writes the loop for you — you only edit what is inside it.
Stripped of its layout tables and Outlook-only comments, a default Summary block is:
Classic White T-Shirt × 2, then $59.98.
- Show or hide the name and price, and set their colour and size, in the block’s settings panel. You do not need to touch the shortcodes.
- The Review block is the same thing with a button, but its loop variable is
line, notitem— write{{ line.name }}there. - If you edit the source: keep the
htmlmin:ignoreHTML comments shown above (they stop the loop tags being mangled), do not renameitem, and do not changeevent.line_items.limit:9999means no limit — lower it to cap how many items show. - In preview it shows placeholder text —
Product Title,Quantity,$xx.xx, and a grey image. Real values appear on send.
Unsubscribe
Works in every email.Four rules worth knowing
Always add a fallback
default covers every “no value” case — blank, never set, or missing.
Hide empty values correctly
To hide a block when a shortcode has no value, test.size > 0:
Correct:
href — a real button that goes nowhere.
.size > 0 is safe on every shortcode in this document.
Typos are invisible
{{ contact.frstName }} renders as empty space. No error, no warning. Proofread, and always send a test email.
A test proves your spelling is right, not that the data will be there. A test send fills in sample values even for shortcodes that come back blank on a real send.
Do not invent tags
Only use what is in this document. A made-up{% tag %} — such as {% current_year %} — breaks the whole email: every shortcode disappears and the raw tag is shown to your customer.
For the current year, use {{ "now" | date: "%Y" }}.