Customizing order confirmation emails

Display custom product thumbnails and preview links in your Shopify order confirmation emails.

By default, Shopify's order confirmation email shows the stock product image. Most merchants want it to show what the customer actually designed. This page covers both.

Line item properties

When a customer adds a customized product to their cart, Pixel Wrangler attaches the following properties to the line item:

PropertyDescription
_pw_thumbnailURL to the thumbnail image of the customer's design
_pw_previewURL to the full preview image (opens in a new tab)
_pw_textThe first custom text entered by the customer
_pw_text_2, _pw_text_3, etc.Additional custom text fields
_pw_image_countNumber of images uploaded
_pw_text_countNumber of text fields with content
_pw_sticker_countNumber of stickers applied
_pw_background_countNumber of backgrounds applied

Shopify hides line item properties starting with an underscore from the customer-facing storefront, so these don't leak into the cart UI unless you explicitly render them.

Displaying the custom thumbnail

To replace the default product image with the customer's design in your order confirmation email:

Step 1 — Access email templates

  1. In your Shopify admin, go to Settings → Notifications
  2. Click Order confirmation (or any other email you want to customize)
  3. Click Edit code

Step 2 — Find the line item image

Look for the section that renders line item images. It usually looks like this:

<img src="{{ line.image | img_url: 'compact_cropped' }}" />

Step 3 — Swap in the custom thumbnail

Replace the image tag with this:

{% if line.properties._pw_thumbnail and line.properties._pw_thumbnail != '' %}
  <img src="{{ line.properties._pw_thumbnail }}"
       alt="Custom Design"
       width="100"
       style="max-width: 100px;" />
{% else %}
  <img src="{{ line.image | img_url: 'compact_cropped' }}"
       alt="{{ line.title }}" />
{% endif %}

The fallback matters. If a non-customized product is in the same order, this keeps the regular product image for that line.

Adding a "View preview" button

A button that opens the full preview image in a new tab:

{% if line.properties._pw_preview and line.properties._pw_preview != '' %}
  <a href="{{ line.properties._pw_preview }}"
     target="_blank"
     style="display: inline-block;
            margin-top: 8px;
            padding: 8px 16px;
            background-color: #000000;
            color: #ffffff;
            text-decoration: none;
            border-radius: 4px;
            font-size: 14px;">
    View preview
  </a>
{% endif %}

A full example

Thumbnail and preview button in one block:

{% for line in line_items %}
  <tr>
    <td style="padding: 10px;">
      {% if line.properties._pw_thumbnail and line.properties._pw_thumbnail != '' %}
        <img src="{{ line.properties._pw_thumbnail }}"
             alt="Custom Design"
             width="100"
             style="max-width: 100px; border-radius: 4px;" />
      {% else %}
        <img src="{{ line.image | img_url: 'compact_cropped' }}"
             alt="{{ line.title }}" />
      {% endif %}
    </td>
    <td style="padding: 10px;">
      <p style="margin: 0; font-weight: bold;">{{ line.title }}</p>
 
      {% if line.properties._pw_text and line.properties._pw_text != '' %}
        <p style="margin: 4px 0; font-size: 14px; color: #666;">
          Custom text: {{ line.properties._pw_text }}
        </p>
      {% endif %}
 
      {% if line.properties._pw_preview and line.properties._pw_preview != '' %}
        <a href="{{ line.properties._pw_preview }}"
           target="_blank"
           style="display: inline-block;
                  margin-top: 8px;
                  padding: 8px 16px;
                  background-color: #000000;
                  color: #ffffff;
                  text-decoration: none;
                  border-radius: 4px;
                  font-size: 14px;">
          View preview
        </a>
      {% endif %}
    </td>
    <td style="padding: 10px; text-align: right;">
      {{ line.final_line_price | money }}
    </td>
  </tr>
{% endfor %}

Hiding internal properties

_pw_* properties are hidden from customers by default because Shopify hides any line item property starting with an underscore. If your theme overrides that default and renders all properties, filter them out:

{% for property in line.properties %}
  {% unless property.first contains '_pw_' %}
    <p>{{ property.first }}: {{ property.last }}</p>
  {% endunless %}
{% endfor %}

Styling notes

  • The thumbnail URL points to a CDN image, so it loads fast.
  • 80–120px width displays well in most email clients.
  • The preview image is full resolution and suitable for sharing.
  • Both URLs are permanent — they won't expire.

Testing

  1. Place a test order with a customized product.
  2. Open the order confirmation email.
  3. Check the thumbnail renders instead of the default product image.
  4. Click View preview to confirm the link opens.

Troubleshooting

Thumbnail doesn't show Check that your conditional includes != '' exactly as shown. Thumbnails can also take a few seconds to generate after checkout — re-send the email if the order was very recent.

Preview link doesn't work Confirm _pw_preview exists on the line item via your Shopify admin order page. Some email editors silently truncate long URLs — copy the URL out of the order properties and paste it back into the link.

Properties showing to the customer Properties starting with _ are hidden by default. If a custom theme renders all properties anyway, use the filter snippet above to drop anything prefixed with _pw_.