How to Add a Gift Wrap Option to Shopify Cart Without an App
Gift wrapping is one of the easiest ways to lift average order value on Shopify, and you don't need a subscription app to do it. Shopify's cart attributes and line item properties are built into the platform. With a few edits to your theme's cart template and a small Liquid snippet in your order total calculation, you can offer gift wrap, collect the customer's choice, charge for it, and see it clearly on the order. This guide walks through the full setup for a modern Shopify theme (Dawn and other Online Store 2.0 themes).
Why Use Cart Attributes for Gift Wrapping Instead of an App
Gift wrap apps typically charge a monthly fee and add a script to your storefront. Check current pricing before committing, but most fall in the range of a few dollars to $20+ per month, and many cap the number of orders or charge per order over a threshold. For a small store, that cost rarely justifies the feature.
Cart attributes solve the same problem natively:
- No monthly cost. Cart attributes are a core Shopify feature available on every plan.
- No extra scripts. Nothing loads on your storefront, so your page speed and Core Web Vitals stay clean.
- Full control over markup and styling. The checkbox matches your theme instead of an app's iframe.
- Data lands on the order. Attributes appear in the admin order page, in the order confirmation email, and in the Shopify API — no syncing or third-party dashboard required.
- Works with Shopify Functions and manual review. You can build a fee into the total via a cart transform, or handle it as a manual line item.
The tradeoff is that you're editing theme code, so you should be comfortable with Liquid or have a developer on call. If you change themes later, you'll redo the work.
Step 1: Add a Gift Wrap Checkbox to Your Cart Form
Open your theme in Online Store → Themes → Edit code and find your cart template. In Dawn it's sections/main-cart-items.liquid; in other themes look for cart.liquid, cart-template.liquid, or a section named main-cart.
Inside the <form action="{{ routes.cart_url }}" method="post"> element, add a checkbox. Keep it simple:
<div class="gift-wrap-option">
<label for="gift-wrap">
<input
type="checkbox"
id="gift-wrap"
name="attributes[Gift wrap]"
value="Yes"
{% if cart.attributes['Gift wrap'] == 'Yes' %}checked{% endif %}
>
Add gift wrap (+$5.00)
</label>
</div>
Two details matter here:
- The
nameattribute uses theattributes[...]prefix. That's what tells Shopify to store the value as a cart attribute rather than a line item property. - The
{% if %}check re-checks the box after a page reload, so the customer's choice survives a quantity update or a refresh.
Place the checkbox above the checkout button and below the line items. Add a small note like "Gift wrap is applied to the entire order" so customers understand the scope. If you want per-item wrapping instead, use line item properties instead of cart attributes — that's a different implementation and the fee math changes.
Step 2: Capture the Gift Wrap Selection with Cart Attributes
Cart attributes are submitted with the cart form. When the customer checks the box and clicks update or checkout, Shopify stores Gift wrap: Yes on the cart. You can read it anywhere in the theme with cart.attributes['Gift wrap'].
A few practical notes:
- Attribute names are case-sensitive. If you write
Gift wrapin the form, read it asGift wrapeverywhere. A mismatch silently returns blank. - Empty values are ignored. If the box is unchecked, Shopify may store an empty string or drop the attribute. Test both states.
- Attributes persist until cleared. They stay on the cart until the customer removes them or the cart is emptied. If you offer a "remove gift wrap" link, post
attributes[Gift wrap]with an empty value.
If you want to collect a gift message too, add a textarea with name="attributes[Gift message]". Keep the field optional and cap the length in the markup with maxlength="200" so it fits on your packing slip.
Step 3: Display the Gift Wrap Fee in the Cart and Checkout
The cart attribute itself doesn't add money to the order. You have two ways to show and charge the fee.
| Approach | How it works | Best for |
|---|---|---|
| Manual line item via cart note | Add a note like "Gift wrap: $5" and adjust the order manually in admin after checkout | Stores with low gift wrap volume, or where you invoice separately |
| Shopify Function / cart transform | A Function reads the cart attribute and adds a fee line item to the cart total automatically | Stores that want the fee charged at checkout without manual work |
For the manual approach, display the fee in the cart with Liquid so the customer sees it before paying:
{% if cart.attributes['Gift wrap'] == 'Yes' %}
<p class="gift-wrap-fee">Gift wrap: $5.00 (added to your order at fulfillment)</p>
{% endif %}
Be honest in the copy. If the fee isn't charged at checkout, say so, or you'll get chargebacks and support emails.
For the automated approach, build a cart transform Function that checks cart.attributes['Gift wrap'] and adds a fee variant. If you don't want to write a Function, apps like Shopify Functions-based fee tools or Cart Transform helpers exist, but check current pricing and whether they support attribute-based triggers before installing.
Step 4: Apply the Gift Wrap Charge to the Order Total
If you're using a cart transform Function, the fee is a real line item and Shopify charges it at checkout. That's the cleanest path.
If you're not using a Function, the reliable manual method is:
- Create a hidden product called "Gift Wrap" with a single variant priced at your fee.
- In the cart template, use JavaScript to add that variant to the cart when the checkbox is checked, and remove it when unchecked.
- Tag the cart attribute so you can reconcile the two in admin.
document.getElementById('gift-wrap').addEventListener('change', async (e) => {
const variantId = 41234567890123; // your Gift Wrap variant ID
if (e.target.checked) {
await fetch('/cart/add.js', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ items: [{ id: variantId, quantity: 1 }] })
});
} else {
await fetch('/cart/change.js', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ id: variantId, quantity: 0 })
});
}
location.reload();
});
Replace the variant ID with your own. This keeps the fee as a real charge and avoids manual invoicing. The downside is that the hidden product shows in your product list unless you keep it unpublished and only reference it by ID.
Step 5: Show Gift Wrap Details in Order Notifications and Admin
Cart attributes flow into the order, but they don't appear in notification emails by default. Edit your notification templates under Settings → Notifications.
In the Order confirmation and New order emails, add a block that prints the attribute:
{% if attributes['Gift wrap'] == 'Yes' %}
<p><strong>Gift wrap:</strong> Yes</p>
{% endif %}
{% if attributes['Gift message'] %}
<p><strong>Gift message:</strong> {{ attributes['Gift message'] }}</p>
{% endif %}
In the admin, open any order and scroll to the Additional details section. Cart attributes appear there as a list. Your fulfillment team can see the gift wrap flag without opening a separate app.
If you use a 3PL or a fulfillment service, confirm it reads order attributes from the Shopify API. Most do, but check before you promise gift wrap as a service.
Testing and Troubleshooting Your No-App Gift Wrap Setup
Test with a real order before you announce the feature. Use a discount code or a test payment gateway so you don't pay full price.
- Check the box, update the cart, and confirm the attribute appears in admin.
- Uncheck it and confirm the attribute clears.
- Reload the cart page and confirm the checkbox state persists.
- Place a test order and verify the attribute appears in the confirmation email.
- Test on mobile — the checkbox should be tappable and not hidden behind the checkout button.
Common problems:
- Attribute missing from the order. The checkbox is outside the cart form, or the
nameis missing theattributes[...]prefix. - Fee charged twice. The cart transform Function and the JavaScript add-to-cart are both running. Pick one.
- Checkbox resets on reload. The
{% if cart.attributes[...] %}check is missing or the attribute name doesn't match exactly. - Fee not showing at checkout. You're using the manual approach without a Function, so Shopify has nothing to charge. Add the hidden product method or a cart transform.
Conclusion
You can add a gift wrap option to your Shopify cart without paying for an app. Cart attributes handle the customer's choice, a small Liquid edit displays it, and either a cart transform Function or a hidden fee product handles the charge. Test the full flow on a real order before launch so your fulfillment team sees the gift wrap flag in the admin and the confirmation email.
FAQ
Does this work on all Shopify themes?
It works on any theme that uses a standard cart form, including Dawn and most Online Store 2.0 themes. Older themes with heavily customized carts may need extra edits, but the attributes[...] prefix works the same way.
Can I charge per item instead of per order? Yes, but you'll need line item properties instead of cart attributes. Add the property to each line item in the cart form, then calculate the fee based on the number of items flagged. That's a different implementation and more code.
Will the gift wrap fee show in Shopify's reports? If you use a hidden fee product or a cart transform line item, the revenue appears in your sales reports as a product. If you use the manual note approach, it won't appear as revenue — only as an order note.