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 BirthdayIf 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.