Cart Fundamentals: Objects, Line Items, Totals
Understand Shopify's cart object, line items, pricing totals, and the data structures that power cart functionality.
The cart is where browsing becomes buying. Understanding the cart object and its data structures is essential for building cart pages, cart drawers, and checkout flows.
The Cart Object
The cart object is globally available and contains all cart data:
{{ cart.item_count }} {# Total number of items #}{{ cart.total_price }} {# Total in cents: 5999 #}{{ cart.total_weight }} {# Total weight in grams #}{{ cart.items }} {# Array of line items #}{{ cart.items_subtotal_price }} {# Subtotal before discounts #}{{ cart.total_discount }} {# Total discount amount #}{{ cart.note }} {# Customer note #}{{ cart.attributes }} {# Custom cart attributes #}{{ cart.currency.iso_code }} {# "USD", "EUR", etc. #}Line Items
Each item in the cart is a line item:
{%- for item in cart.items -%} {{ item.id }} {# Line item ID (not variant ID) #} {{ item.key }} {# Unique key for this line #} {{ item.product.title }} {# "Classic T-Shirt" #} {{ item.variant.title }} {# "Small / Blue" #} {{ item.quantity }} {# 2 #} {{ item.price }} {# Unit price in cents #} {{ item.line_price }} {# quantity × price #} {{ item.original_line_price }} {# Before line discounts #} {{ item.final_line_price }} {# After all discounts #} {{ item.sku }} {# SKU #} {{ item.image }} {# Line item image #} {{ item.url }} {# Link to product #} {{ item.properties }} {# Custom properties #}{%- endfor -%}Basic Cart Page
{# templates/cart.liquid or sections/cart-main.liquid #}
<div class="cart-page"> {%- if cart.item_count > 0 -%} <h1>Your Cart ({{ cart.item_count }})</h1>
<form action="{{ routes.cart_url }}" method="post"> <table class="cart-table"> <thead> <tr> <th>Product</th> <th>Price</th> <th>Quantity</th> <th>Total</th> </tr> </thead> <tbody> {%- for item in cart.items -%} <tr class="cart-item" data-key="{{ item.key }}"> <td class="cart-item__product"> <a href="{{ item.url }}"> <img src="{{ item.image | image_url: width: 150 }}" alt="{{ item.image.alt | default: item.product.title }}" width="75" height="75" > </a> <div class="cart-item__details"> <a href="{{ item.url }}" class="cart-item__title"> {{ item.product.title }} </a> {%- if item.variant.title != 'Default Title' -%} <p class="cart-item__variant">{{ item.variant.title }}</p> {%- endif -%} </div> </td>
<td class="cart-item__price"> {{ item.price | money }} </td>
<td class="cart-item__quantity"> <input type="number" name="updates[]" value="{{ item.quantity }}" min="0" aria-label="Quantity" > </td>
<td class="cart-item__total"> {{ item.final_line_price | money }} </td> </tr> {%- endfor -%} </tbody> </table>
<div class="cart-footer"> <div class="cart-totals"> <p class="cart-subtotal"> <span>Subtotal:</span> <span>{{ cart.total_price | money }}</span> </p> <p class="cart-shipping-note"> Shipping calculated at checkout </p> </div>
<button type="submit" name="update" class="button button--secondary"> Update Cart </button>
<button type="submit" name="checkout" class="button button--primary"> Checkout </button> </div> </form> {%- else -%} {% render 'cart-empty' %} {%- endif -%}</div>Understanding Prices
Cart prices can be confusing. Here’s what each one means:
{%- for item in cart.items -%} {# Unit price (single item) #} {{ item.price }} {# Current unit price #} {{ item.original_price }} {# Original unit price (before discounts) #} {{ item.final_price }} {# Final unit price (after discounts) #}
{# Line price (quantity × unit price) #} {{ item.line_price }} {# Basic line total #} {{ item.original_line_price }} {# Before any discounts #} {{ item.final_line_price }} {# After all discounts (use this!) #}{%- endfor -%}
{# Cart totals #}{{ cart.items_subtotal_price }} {# Sum of all line prices #}{{ cart.total_discount }} {# Total discounts applied #}{{ cart.total_price }} {# Final total #}Best practice: Use final_line_price for line items and total_price for cart total.
Line Item Properties
Display custom properties added at product pages:
{%- if item.properties.size > 0 -%} <ul class="cart-item__properties"> {%- for property in item.properties -%} {%- unless property.first contains '_' -%} <li> <span class="property-name">{{ property.first }}:</span> <span class="property-value">{{ property.last }}</span> </li> {%- endunless -%} {%- endfor -%} </ul>{%- endif -%}Showing Discounts
Display applied discounts on line items:
{%- if item.original_line_price != item.final_line_price -%} <div class="cart-item__discounts"> <span class="cart-item__original-price"> {{ item.original_line_price | money }} </span> <span class="cart-item__discount-amount"> Save {{ item.original_line_price | minus: item.final_line_price | money }} </span> </div>{%- endif -%}
{# Show specific discounts #}{%- if item.line_level_discount_allocations.size > 0 -%} <ul class="cart-item__discount-list"> {%- for discount in item.line_level_discount_allocations -%} <li> {{ discount.discount_application.title }}: -{{ discount.amount | money }} </li> {%- endfor -%} </ul>{%- endif -%}Cart-Level Discounts
Some discounts apply to the entire cart:
{%- if cart.cart_level_discount_applications.size > 0 -%} <div class="cart-discounts"> <h3>Discounts Applied</h3> <ul> {%- for discount in cart.cart_level_discount_applications -%} <li> <span>{{ discount.title }}</span> <span>-{{ discount.total_allocated_amount | money }}</span> </li> {%- endfor -%} </ul> </div>{%- endif -%}Cart Totals Summary
{# snippets/cart-totals.liquid #}
<div class="cart-totals"> {# Subtotal #} <div class="cart-totals__row"> <span>Subtotal</span> <span>{{ cart.items_subtotal_price | money }}</span> </div>
{# Cart-level discounts #} {%- for discount in cart.cart_level_discount_applications -%} <div class="cart-totals__row cart-totals__row--discount"> <span>{{ discount.title }}</span> <span>-{{ discount.total_allocated_amount | money }}</span> </div> {%- endfor -%}
{# Shipping estimate (if available) #} {%- if cart.requires_shipping -%} <div class="cart-totals__row"> <span>Shipping</span> <span>Calculated at checkout</span> </div> {%- endif -%}
{# Total #} <div class="cart-totals__row cart-totals__row--total"> <span>Total</span> <span>{{ cart.total_price | money }}</span> </div>
{# Currency note #} <p class="cart-totals__currency"> All prices in {{ cart.currency.iso_code }} </p></div>Cart Attributes
Store custom data on the cart:
{# Display cart attributes #}{%- if cart.attributes.gift_wrap -%} <p>Gift wrapping: Yes</p>{%- endif -%}
{# Form to set cart attribute #}<label> <input type="checkbox" name="attributes[gift_wrap]" value="Yes"> Gift wrap this order</label>Cart Note
Allow customers to add notes:
<div class="cart-note"> <label for="cart-note">Order Notes</label> <textarea id="cart-note" name="note" rows="3" placeholder="Special instructions for your order..." >{{ cart.note }}</textarea></div>Cart Styles
.cart-table { width: 100%; border-collapse: collapse;}
.cart-table th { text-align: left; padding: var(--spacing-sm) var(--spacing-md); border-bottom: 1px solid var(--color-border); font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--color-text-light);}
.cart-item td { padding: var(--spacing-md); border-bottom: 1px solid var(--color-border); vertical-align: top;}
.cart-item__product { display: flex; gap: var(--spacing-md);}
.cart-item__product img { width: 75px; height: 75px; object-fit: cover; border-radius: var(--border-radius);}
.cart-item__title { font-weight: 500; color: inherit; text-decoration: none;}
.cart-item__title:hover { text-decoration: underline;}
.cart-item__variant { font-size: 0.875rem; color: var(--color-text-light); margin: var(--spacing-xs) 0 0;}
.cart-item__properties { font-size: 0.8125rem; color: var(--color-text-light); margin-top: var(--spacing-sm); list-style: none; padding: 0;}
.cart-item__quantity input { width: 60px; padding: var(--spacing-xs) var(--spacing-sm); text-align: center; border: 1px solid var(--color-border); border-radius: var(--border-radius);}
.cart-totals { max-width: 400px; margin-left: auto;}
.cart-totals__row { display: flex; justify-content: space-between; padding: var(--spacing-sm) 0;}
.cart-totals__row--discount { color: var(--color-sale);}
.cart-totals__row--total { font-size: 1.125rem; font-weight: 600; border-top: 1px solid var(--color-border); margin-top: var(--spacing-sm); padding-top: var(--spacing-md);}
.cart-footer { display: flex; flex-wrap: wrap; gap: var(--spacing-md); justify-content: flex-end; align-items: flex-start; margin-top: var(--spacing-xl);}Practice Exercise
Build a cart page that:
- Displays all line items with images
- Shows variant titles and properties
- Displays discounts when applied
- Has quantity inputs for each item
- Shows subtotal and total
- Has update and checkout buttons
Test with:
- Multiple items
- Items with properties
- Discounted items
- Empty cart
Key Takeaways
cartobject is globally availablecart.itemscontains all line items- Use
final_line_pricefor accurate line totals - Check for discounts on lines and cart level
- Show properties (excluding underscore-prefixed)
- Cart attributes store custom data
- Cart note for customer instructions
- Always handle empty cart state
What’s Next?
The next lesson covers Building a Cart Drawer (Mini Cart) for a slide-out cart experience.
Finished this lesson?
Mark it complete to track your progress.
Discussion
Loading comments...