show item prices on packing slip - line_item.properties?

Topic summary

Goal: display per-item prices on Shopify packing slips using Liquid templating within the packing slip template.

Early approach: edit the template and, inside the for loop over line_items_in_shipment, match each displayed line item to order.line_items (often by SKU) and output item.final_price | money. Several users confirmed it worked, with formatting tweaks (e.g., placing price under SKU).

Order totals: add order.subtotal_price, order.tax_price, order.shipping_price, and order.total_price after the loop to show invoice-like totals.

Breakages/changes: many later reports show incorrect pricing (all items same, last item’s price, variant issues). Community notes suggest Shopify changed available line_item fields in packing slips; unique identifiers (sku, id, variant_id) may be unavailable when iterating line_items_in_shipment. The official variable list for packing slips is limited.

Workarounds: match by title + variant_title to fetch item.final_price from order.line_items (works unless duplicate names/variants). Another shared method maps original_price from order.line_items, and several customized templates were posted.

Open issues: line-item subtotals (qty × price), per-line discounts, sale/discounted pricing accuracy, alignment/styling, and adding fulfillment location/contact number. Some recommend invoice apps (e.g., drag‑and‑drop editors). Status: ongoing; code snippets and attachments are central; no official Shopify resolution noted.

Summarized with AI on December 12. AI used: gpt-5.

That’s all I want to do, put the price of the item on the packing slip. Shopify says it can’t be done, which means it can’t be done easily.

I can imagine a line_item.properties value set equal to the price, but I don’t know how to set the value. I don’t want a HTML input, it is something that should be set by the code. In product-template.liquid, I suppose. But I can’t find a way to create a property to carry the value of the price out to the packing slip.

Is there a way to do that, with a modicum of coding?

TIA

Ed K

Hey @edk ,

There is a way to put the price of the item on the packing slip.

I was able to place the price right below the product description (placing the price anywhere else requires re-styling the template):

To implement this in your store, you will need to edit your packing slip template.

Replace the entire contents of your packing slip template with this code:

<div class="wrapper">
  <div class="header">
    <div class="shop-title">
      <p class="to-uppercase">
        {{ shop.name }}
      </p>
    </div>
    <div class="order-title">
      <p class="text-align-right">
        Order {{ order.name }}
      </p>
      <p class="text-align-right">
        {{ order.created_at | date: "%B %e, %Y" }}
      </p>
    </div>
  </div>
  <div class="customer-addresses">
    <div class="shipping-address">
      <p class="subtitle-bold to-uppercase">
        Ship to
      </p>
      <p class="address-detail">
        {% if shipping_address != blank %}
          {{ shipping_address.name }}
          {% if shipping_address.company != blank %}
            <br>
            {{ shipping_address.company }}
          {% endif %}
          <br>
          {{ shipping_address.address1 }}
          {% if shipping_address.address2 != blank %}
            <br>
            {{ shipping_address.address2 }}
          {% endif %}
          {% if shipping_address.city_province_zip != blank %}
            <br>
            {{ shipping_address.city_province_zip }}
          {% endif %}
          <br>
          {{ shipping_address.country }}
        {% else %}
          No shipping address
        {% endif %}
      </p>
    </div>
    <div class="billing-address">
      <p class="subtitle-bold to-uppercase">
        Bill to
      </p>
      <p class="address-detail">
        {% if billing_address != blank %}
          {{ billing_address.name }}
          {% if billing_address.company != blank %}
            <br>
            {{ billing_address.company }}
          {% endif %}
          <br>
          {{ billing_address.address1 }}
          {%  if billing_address.address2 != blank %}
            <br>
            {{ billing_address.address2 }}
          {% endif %}
          {% if billing_address.city_province_zip != blank %}
            <br>
            {{ billing_address.city_province_zip }}
          {% endif %}
          <br>
          {{ billing_address.country }}
        {% else %}
          No billing address
        {% endif %}
      </p>
    </div>
  </div>
  <hr>
  <div class="order-container">
    <div class="order-container-header">
      <div class="order-container-header-left-content">
        <p class="subtitle-bold to-uppercase">
          Items
        </p>
      </div>
      <div class="order-container-header-right-content">
        <p class="subtitle-bold to-uppercase">
          Quantity
        </p>
      </div>
    </div>

    {% comment %}
    To adjust the size of line item images, change desired_image_size.
    The other variables make sure your images print at high quality.
    {% endcomment %}
    {% assign desired_image_size = 58 %}
    {% assign resolution_adjusted_size = desired_image_size | times: 300 | divided_by: 72 | ceil %}
    {% capture effective_image_dimensions %}
      {{ resolution_adjusted_size }}x{{ resolution_adjusted_size }}
    {% endcapture %}

    {% assign index = 0 %}

    {% for line_item in line_items_in_shipment %}
      <div class="flex-line-item">
        <div class="flex-line-item-img">
          {% if line_item.image != blank %}
            <div class="aspect-ratio aspect-ratio-square" style="width: {{ desired_image_size }}px; height: {{ desired_image_size }}px;">
              {{ line_item.image | img_url: effective_image_dimensions | img_tag: '', 'aspect-ratio__content' }}
            </div>
          {% endif %}
        </div>
        <div class="flex-line-item-description">
          <p>
            <span class="line-item-description-line">
              {{ line_item.title }}
            </span>
            {% if line_item.variant_title != blank %}
              <span class="line-item-description-line">
                {{ line_item.variant_title }}
              </span>
            {% endif %}
            {% if line_item.sku != blank %}
              <span class="line-item-description-line">
                {{ line_item.sku }}
              </span>
            {% endif %}
            <span class="line-item-description-line">
              {% assign final_price = nil %}
              {% for item in order.line_items %}
                {% if item.sku == line_item.sku %}
                  {% assign final_price = item.final_price %}
                {% endif %}
              {% endfor %}
              {% if final_price %}
                {{ final_price | money }}
              {% endif %}
            </span>
          </p>
        </div>
        <div class="flex-line-item-quantity">
          <p class="text-align-right">
            {{ line_item.shipping_quantity }} of {{ line_item.quantity }}
          </p>
        </div>
      </div>
      {% assign index = index | plus: 1 %}
    {% endfor %}
  </div>
  {% unless includes_all_line_items_in_order %}
    <hr class="subdued-separator">
    <p class="missing-line-items-text ">
      There are other items from your order not included in this shipment.
    </p>
  {% endunless %}
  <hr>
  {% if order.note != blank %}
    <div class="notes">
      <p class="subtitle-bold to-uppercase">
        Notes
      </p>
      <p class="notes-details">
        {{ order.line_items }}
      </p>
    </div>
  {% endif %}
  <div class="footer">
    <p>
      Thank you for shopping with us!
    </p>
    <p>
      <strong>
        {{ shop.name }}
      </strong>
      <br>
      {{ shop_address.address1 }}, {{ shop_address.city }}, {{ shop_address.province_code }}, {{ shop_address.zip }}, {{ shop_address.country }}
      <br>
      {{ shop.email }}
      <br>
      {{ shop.domain }}
    </p>
  </div>
</div>
<style type="text/css">
  body {
    font-size: 15px;
  }

  * {
    box-sizing: border-box;
  }

  .wrapper {
    width: 831px;
    margin: auto;
    padding: 4em;
    font-family: "Noto Sans", sans-serif;
    font-weight: 250;
  }

  .header {
    width: 100%;
    display: -webkit-box;
    display: -webkit-flex;
    display: flex;
    flex-direction: row;
    align-items: top;
  }

  .header p {
    margin: 0;
  }

  .shop-title {
    -webkit-box-flex: 6;
    -webkit-flex: 6;
    flex: 6;
    font-size: 1.9em;
  }

  .order-title {
    -webkit-box-flex: 4;
    -webkit-flex: 4;
    flex: 4;
  }

  .customer-addresses {
    width: 100%;
    display: inline-block;
    margin: 2em 0;
  }

  .address-detail {
    margin: 0.7em 0 0;
    line-height: 1.5;
  }

  .subtitle-bold {
    font-weight: bold;
    margin: 0;
    font-size: 0.85em;
  }

  .to-uppercase {
    text-transform: uppercase;
  }

  .text-align-right {
    text-align: right;
  }

  .shipping-address {
    float: left;
    min-width: 18em;
    max-width: 50%;
  }

  .billing-address {
    padding-left: 20em;
    min-width: 18em;
  }

  .order-container {
    padding: 0 0.7em;
  }

  .order-container-header {
    display: inline-block;
    width: 100%;
    margin-top: 1.4em;
  }

  .order-container-header-left-content {
    float: left;
  }

  .order-container-header-right-content {
    float: right;
  }

  .flex-line-item {
    display: -webkit-box;
    display: -webkit-flex;
    display: flex;
    flex-direction: row;
    align-items: center;
    margin: 1.4em 0;
    page-break-inside: avoid;
  }

  .flex-line-item-img {
    margin-right: 1.4em;
    min-width: {{ desired_image_size }}px;
  }

  .flex-line-item-description {
    -webkit-box-flex: 7;
    -webkit-flex: 7;
    flex: 7;
  }

  .line-item-description-line {
    display: block;
  }

  .flex-line-item-description p {
    margin: 0;
    line-height: 1.5;
  }

  .flex-line-item-quantity {
    -webkit-box-flex: 3;
    -webkit-flex: 3;
    flex: 3;
  }

  .subdued-separator {
    height: 0.07em;
    border: none;
    color: lightgray;
    background-color: lightgray;
    margin: 0;
  }

  .missing-line-items-text {
    margin: 1.4em 0;
    padding: 0 0.7em;
  }

  .notes {
    margin-top: 2em;
  }

  .notes p {
    margin-bottom: 0;
  }

  .notes .notes-details {
    margin-top: 0.7em;
  }

  .footer {
    margin-top: 2em;
    text-align: center;
    line-height: 1.5;
  }

  .footer p {
    margin: 0;
    margin-bottom: 1.4em;
  }

  hr {
    height: 0.14em;
    border: none;
    color: black;
    background-color: black;
    margin: 0;
  }

  .aspect-ratio {
    position: relative;
    display: block;
    background: #fafbfc;
    padding: 0;
  }

  .aspect-ratio::before {
    z-index: 1;
    content: "";
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    border: 1px solid rgba(195,207,216,0.3);
  }

  .aspect-ratio--square {
    width: 100%;
    padding-bottom: 100%;
  }

  .aspect-ratio__content {
    position: absolute;
    max-width: 100%;
    max-height: 100%;
    display: block;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    margin: auto;
  }
</style>

Let me know how it goes or if you need further help!

8 Likes

Astonishingly easy, but formatting needs work. I did not copy exactly but found the part of the loop where the price is extracted:

              {% assign final_price = nil %}
              {% for item in order.line_items %}
                {% if item.sku == line_item.sku %}
                  {% assign final_price = item.final_price %}
                {% endif %}
              {% endfor %}
              {% if final_price %}
                {{ final_price | money }}
              {% endif %}

and pasted it, after backing up the original. A little formatting and this will be done.

I am betting that this method of pasting the code will work?

I take it back, I said that Shopify meant it could not be done easily. Wrong!

Thanks Brian!!!

Yes, you may paste that code to get the price, so long as it is inside the main “for” loop of the template:

{% for line_item in line_items_in_shipment %}

...Keep price code snippet inside here...

{% endfor %}

I take it back, I said that Shopify meant it could not be done easily. Wrong!

I’m so glad the code worked for you! Send me a DM if you need help with formatting.

Will you please click Accept as Solution on my answer? Thank you.

@edk Personal print has got a drag and drop editor that lets you build whatever invoice you want, or any other thing to be printed with your invoice.

It also lets you add some “smart” text to personalize your invoices for each customer. Plus they can then be downloaded directly from the Shopify orders’ list page. We’re using it to send some automated personalized thank you notes to our customers for about a year, and zero complaint so far.

Hello EDk,

How did you format the price to appear on the far right i have used

but the price appears mid right.

I don’t remember how I did that. I went with a simpler format with the price below the SKU.

Now that I think about it, I remember trying to align it and couldn’t get it to work, so I gave up. The simpler format looked better, anyway.

I tried a few things just now. Trying to put the price on the same line as the SKU:

{{ line_item.sku }} <div align="right">  {{ final_price | money }}  </div> 

It right-justified, but adds a linefeed between the SKU and price. Why I don’t know.

Sorry I can’t be more help.

Ed

Thank you for this - very helpful! Worked great.

This is great, worked perfectly! however my notes are now printing on packing slip as ######. Any ideas?

Brian – how would I do the same thing but instead of price, put the product SKU in that position? I’ve tried to play around with it, but can’t figure it out.

I’ve copied the code and paste it exactly the way it was, but the prices are not right, all items have same price, and it does change according with the quantity. It pics the price of the last product. I am using debut theme, do you have any idea what could it be? It does not show the total either.

2 Likes

I’m having the same problem. The Packing Slip prices WERE working before, but they just recently started showing all the same prices on my packing slips. Any ideas on what might have changed and if there is any way to fix it?

Hey edk! Thanks for asking this question.

I noticed in the image you uploaded that you have the order subtotal listed at the bottom of the item list. How did you do that? I’ve been looking everywhere for a way to add the subtotal to my packing slips and haven’t found it anywhere!

Thanks for your help!

Hey Ed, do you know the Shopify liquid of First Item SKU and First Item Quantity?

Hi @BrianAtWork ,

thanks for your post. I used your code and I’m close to the goal but I still got a problem:

If there are multiple products in the same order, all the items have the same price of the first item.

Can you help me to fix it please?

Thank you,

Carlo

@CarlosNZ I’ve got the same problem!

Did you solve it?

@Digby-Iona me too!

Did you solve it?

Hi i have copied and pasted this into my page but i can only get it to show up at the very bottom of the item and the total cost doesn’t show only the item cost? how did you get yours to show the total and have prices more in the middle not under?

The final price no longer works. Shopify changed something and I have not figured it out yet.

Here is the final code in my packing slip. Parts that don’t work now are in red. Starting at line 123 of the unmodified packing slip template:

{%- comment -%} ********adding prices to packing slip *********{%- endcomment -%}

{% assign final_price = nil %}
{% for item in order.line_items %}
{% if item.sku == line_item.sku %}
{% assign final_price = item.final_price %}
{% endif %}
{% endfor %}
{% if final_price %}
{{ final_price | money }}
{% endif %}

{%- comment -%} ********done adding prices to packing slip *********{%- endcomment -%}

The final line number should be 135.

If things don’t format right, I’m afraid I can be no more help. The original solution came from BrianAtWork, as you see from the second entry in the thread - ask him nicely and he will probably help you.

OK, my bad - I figured this out, finally. Wrong section of snippet to highlight. That part works. Here is the real answer:

Use this Liquid doc page to reference order variables: https://shopify.dev/docs/themes/liquid/reference/objects/order

If you add this code to the packing slip the final prices will show up:



order.subtotal_price {{ order.subtotal_price | money }}


order.tax_price {{ order.tax_price | money }}


order.shipping_price {{ order.shipping_price | money }}


order.total_price {{ order.total_price | money }}

In my code, with the original snippet inserted, that is at line 147, just after the {% endfor %}

I have no idea why my example packing slip had the total price. Mystery.

Formatting and labeling is left to the reader.

1 Like