Skip to Content
Orders & emailsNotification emails

Notification emails

OptionWise option values are standard Shopify line-item properties. They’re always saved on the order — you’ll see them on the order’s detail page in your Shopify admin. However, Shopify’s notification emails don’t print line-item properties by default, so the customer’s choices won’t appear in the order confirmation email (or your new-order email) until you add a small snippet to the template.

It’s a one-time, copy-paste edit per template. This page gives you the exact snippet for each place you’re likely to want it: the order confirmation email, the new order email you receive, and the packing slip.

The fastest route for the order confirmation: on your OptionWise dashboard, open Recommended for you → Add option details to your order emails. OptionWise prepares an updated copy of your template with the options code already in place — you replace the template with it in a single copy-paste, and OptionWise verifies the result. A copy of your original template is saved first, so you can restore it at any time. This page is the manual guide for merchants who prefer to place the code by hand, and the reference for the other templates.

The template editor’s Send test notification button can’t tell you whether the snippet works — it emails Shopify’s sample order, which has no options on it. To see the real thing, use Create a test order in the dashboard flow (it creates a test order with sample options and Shopify sends your actual notification emails), or place a test order yourself.

Order confirmation (customer email)

Open the notification template

Open your store’s Order confirmation template  (in your Shopify admin under Settings → Notifications → Customer notifications) and click Edit code.

Find the item block your emails use

Look for the block that loops over the purchased items — it starts with a line like {% for line in subtotal_line_items %} (some templates use line_items). Each product’s title and price are rendered inside it.

Shopify’s default template contains several copies of this block, one per order scenario — scroll to the last one, near the bottom of the template: that’s the copy an ordinary order renders. The dashboard flow gives you its exact line number.

Paste the properties snippet

Inside that block, find the line that prints the product title and the variant-title lines just under it (a short {% if %}…{% endif %} group). Right after that group — so options appear under the variant, the same order Shopify uses at checkout — paste:

{% for property in line.properties %} {% assign first_char = property.first | slice: 0 %} {% if property.last != blank and first_char != '_' %} <div><span class="order-list__item-variant">{{ property.first }}: {{ property.last }}</span></div> {% endif %} {% endfor %}

Paste the bundle-section copy

Orders that include priced add-ons or linked products render their items through a separate bundle section of the same template, so that section needs its own copy of the snippet. Scroll further down to the block that starts with {% for line_item_group in line_item_groups %}. Inside it, the line {% if component.variant.title != 'Default Title' %} appears more than once — once per rendering branch — and the copy must go after the {% endif %} of the occurrence inside the {% if line_item_group.deliverable? == false %} branch (the first one in the block). If in doubt, paste the copy after each occurrence — extra copies in branches your orders don’t use are harmless — or use the dashboard flow, which points at the exact line. Note the snippet loops component rather than line:

{% for property in component.properties %} {% assign first_char = property.first | slice: 0 %} {% if property.last != blank and first_char != '_' %} <div><span class="order-list__item-variant">{{ property.first }}: {{ property.last }}</span></div> {% endif %} {% endfor %}

If your template doesn’t have a line_item_groups block (older customized templates), skip this step — the dashboard flow only asks for the pastes your template needs.

Save and verify

Click Save, then go back to the dashboard flow and check the template — it confirms the code is in the right place. From there, Create a test order places a test order with sample options: Shopify sends you your store’s real confirmation email (and your merchant-facing New order email). The order is marked as a test, so it stays out of your reports, and you can delete it at any time.

Keep the snippet as written: it hides OptionWise’s internal items (anything starting with _optionwise_, which customers never see) and skips any options the customer left empty.

How it renders

For a line item with a couple of options, the snippet produces:

Wooden Photo Frame Size: Large Engraving: Happy Birthday

If you’d rather match your existing formatting, change only the markup inside the {% if %} — the two guards and the {{ property.first }} / {{ property.last }} outputs are the parts that matter. As written, the snippet reuses the template’s own order-list__item-variant styling, so options render in the same font as the variant line above them.

Optional: hide the Add-ons line

On orders with priced add-ons, the bundle section lists an Add-ons item alongside the product. Its price is already included in the bundle total, so you can hide the line if you prefer a shorter email. In the same {% for component in line_item_group.components %} loop where you pasted the bundle-section copy, add this on a new line directly after the {% for %} line:

{% if component.properties["_optionwise_trace"] %}{% continue %}{% endif %}

This skips only OptionWise’s Add-ons item; the product and its options still render, and all prices stay the same.

New order (the email you receive)

The merchant-facing New order notification is a separate template, so it needs the same edit. Go to Settings → Notifications → Staff notifications, open New order, click Edit code, and find the block that loops over the purchased items (it starts with a line like {% for line in subtotal_line_items %}; some templates use line_items). If the block appears more than once, use the last copy. Inside it, just under the lines that print the product title and variant, paste:

{% for property in line.properties %} {% assign first_char = property.first | slice: 0 %} {% if property.last != blank and first_char != '_' %} <div><span class="order-list__item-variant">{{ property.first }}: {{ property.last }}</span></div> {% endif %} {% endfor %}

As with the order confirmation, if the template has a {% for line_item_group in line_item_groups %} block further down, add the component.properties copy of the snippet there too (see the bundle-section step above) so orders with priced add-ons show their options as well.

The same approach works for any other notification that lists line items — shipping confirmations, for example — each template is edited separately.

Packing slip

Packing slips live in a different place: Settings → Shipping and delivery, then Edit template in the Packing slips section. Find the loop that renders each item (it starts with a line like {% for line_item in ... %}) and paste this version — note it uses line_item rather than line:

{% for property in line_item.properties %} {% assign first_char = property.first | slice: 0 %} {% if property.last != blank and first_char != '_' %} <p class="text-small">{{ property.first }}: {{ property.last }}</p> {% endif %} {% endfor %}

Now your fulfillment team sees each item’s selected options on the printed slip.

Uploaded files

A file-upload value is a link to the file. In a plain-text email context the link prints as a URL; in your admin it’s a clickable download. The snippets above print it as-is, so the customer gets the link in their confirmation.

Shopify notification templates are global to your store, not part of your theme — editing them doesn’t touch your storefront or your OptionWise setup. If you later reset a template to Shopify’s default, you’ll need to re-add the snippet.