How to Add a Gift Message Field to Shopify Order Status Page

2026-10-25 · shipping fulfillment

Shopify's order status page is the page customers land on after checkout and return to from shipping confirmation emails. By default it shows order details, tracking, and shipping address. It does not offer a gift message field. If you sell anything people buy as presents — candles, jewelry, coffee, baby goods — buyers currently have no clean place to type "Happy birthday, Sam" and have it travel with the order.

You can add that field without paying for an app. The order status page is a Liquid template you can edit, and Shopify's order attributes system lets you store customer input against the order. This guide walks through the whole build, from backing up the template to verifying the note in admin.

Why Add a Gift Message Field to the Order Status Page (Without an App)

The obvious alternative is a cart attribute or a line item property collected at checkout. Both work, but they have gaps for gift messaging:

The order status page solves a different problem: timing. Many gift buyers only think about the message after they've paid — when they're checking tracking or forwarding the confirmation to the recipient. A field on the status page catches them at that moment.

Building it yourself keeps costs at zero, avoids another app in your stack, and gives you full control over placement and styling. The trade-off is that you're editing theme code, so the steps below emphasize backups and testing.

How It Works: Order Attributes and the Status Page Template

Two Shopify mechanisms make this possible.

Order attributes are key-value pairs stored on an order. Shopify's cart.attributes object accepts custom keys, and values written to it persist through checkout onto the order. In admin, attributes appear under the order's "Additional details" section, and they're accessible in Liquid as order.attributes.

The order status page template is a Liquid file in your theme: templates/customers/order.liquid in older themes, or templates/customers/order.json plus a section file in Online Store 2.0 themes. It renders inside Shopify's checkout domain context, which means it has access to the order object but not your full theme's assets in the same way a normal page does.

The flow you're building:

  1. Customer lands on the status page and sees a textarea.
  2. They type a message and submit.
  3. A small script sends the value to Shopify's order attribute endpoint.
  4. The attribute saves to the order and shows in admin.

Shopify exposes a client-side API for this on the status page. The Shopify global object available there includes methods for updating order attributes, which is what the script in Step 3 uses.

Step 1: Locate and Back Up Your Order Status Template

Before touching anything, confirm which template system your theme uses.

In Shopify admin, go to Online Store → Themes → Actions → Edit code. Look under Templates:

Theme type File to look for Notes
Legacy (Debut, Brooklyn, Supply) customers/order.liquid Single Liquid file
Online Store 2.0 (Dawn, Sense, most new themes) customers/order.json JSON points to a section, usually main-order.liquid under Sections
Checkout extensibility themes customers/order.json Same as above; some logic lives in checkout extensions

Open the file and read it before editing. Find where the order details render — you want your field near the top, above the line items, so customers see it immediately.

Back up now. Click the file name, select all, and paste the contents into a text file on your computer, or duplicate the theme (Themes → Actions → Duplicate) and edit the copy first. Theme edits are not versioned in a way you can easily roll back, and a broken status page template can produce a blank page for every customer post-purchase.

If your theme uses order.json, the actual markup lives in the section it references. Open that section file and note the schema block at the bottom — you'll add a setting there in Step 2.

Step 2: Add the Gift Message Field to the Template

Add the markup inside the main order container, after the order number/date heading and before the line items table.

{% if order.attributes['Gift message'] == blank %}
  <div id="gift-message-wrap" class="order-gift-message">
    <label for="gift-message-input">Add a gift message (optional)</label>
    <textarea id="gift-message-input" maxlength="250" rows="3"
      placeholder="e.g. Happy birthday, Sam — enjoy!"></textarea>
    <button type="button" id="gift-message-save">Save gift message</button>
    <p id="gift-message-status" role="status"></p>
  </div>
{% else %}
  <div class="order-gift-message">
    <p><strong>Gift message:</strong> {{ order.attributes['Gift message'] }}</p>
  </div>
{% endif %}

Key decisions in that snippet:

For Online Store 2.0 themes, wrap the block in a section setting so merchants can toggle it. In the section's {% schema %} block, add:

{
  "type": "checkbox",
  "id": "show_gift_message",
  "label": "Show gift message field",
  "default": true
}

Then wrap your markup in {% if section.settings.show_gift_message %}.

Style the block with a few lines of CSS in your theme's stylesheet, or inline in a <style> tag scoped to the wrapper. Match your existing form styles — the status page often inherits minimal styling, so a bare textarea looks out of place.

Step 3: Save the Note as an Order Attribute

The status page exposes a Shopify JavaScript object with an updateAttribute-style method for writing order attributes. Add a script below your markup:

<script>
document.addEventListener('DOMContentLoaded', function () {
  var btn = document.getElementById('gift-message-save');
  if (!btn) return;

  btn.addEventListener('click', function () {
    var input = document.getElementById('gift-message-input');
    var status = document.getElementById('gift-message-status');
    var value = input.value.trim();

    if (!value) {
      status.textContent = 'Please type a message first.';
      return;
    }

    btn.disabled = true;
    status.textContent = 'Saving…';

    Shopify.updateAttribute({ 'Gift message': value })
      .then(function () {
        status.textContent = 'Gift message saved.';
        input.value = '';
        document.getElementById('gift-message-wrap').style.display = 'none';
      })
      .catch(function () {
        status.textContent = 'Something went wrong. Please refresh and try again.';
        btn.disabled = false;
      });
  });
});
</script>

Two things to verify in your theme: that the Shopify object is available on the status page (it is on standard Shopify checkout, but check after any theme migration), and that your method name matches the current API. Shopify has changed the status page JS API over time; if updateAttribute throws, check the Shopify developer docs for the current method signature before assuming the script is broken.

The attribute key 'Gift message' must match exactly between the script, the Liquid check in Step 2, and any admin filter you set up later. Case and spacing matter.

Step 4: Test the Field and Verify the Note Appears in Admin

Place a real test order. Don't use a draft order — the status page flow differs. Use a discount code or a low-priced item to keep the cost minimal, and complete checkout normally.

On the confirmation/status page:

  1. Confirm the textarea appears in the expected position.
  2. Type a test message and click Save.
  3. Confirm the success status text appears and the form hides.
  4. Refresh the page. Your saved message should now render from the {% else %} branch.

Then check admin: Orders → [your test order] → Additional details. The gift message should appear as an attribute with the key Gift message.

If it's missing, the likely causes are a mismatched key, the script not loading (check the browser console), or the attribute call failing silently. Test in an incognito window to rule out caching, and check the console for errors on every step.

Step 5: Show the Gift Message to Fulfillment and Customers

Saving the attribute is only useful if people see it. Three places matter:

For fulfillment apps like ShipStation or a 3PL integration, check whether order attributes sync. Many do; some require mapping the attribute to a custom field first. Test with one order before relying on it.

Troubleshooting Common Issues and When an App Might Still Help

Common problems and fixes:

An app makes sense when you need features that are painful to build: per-item gift messages on multi-item orders, scheduled delivery tied to the message, gift wrap selection with pricing, or automatic insertion into fulfillment documents across multiple 3PLs. Apps like Order Logic or similar order-attribute tools handle these; check current pricing and feature lists on the Shopify App Store before committing, since these change. For a single free-text field, the code above is enough.

Conclusion

A gift message field on the order status page is a small addition that closes a real gap for gift-heavy stores, and it costs nothing beyond a careful theme edit. Back up the template, match your attribute key exactly across Liquid and JavaScript, and test with a real order before going live. Once it's working, wire the attribute into your packing slip so the message actually reaches the box.

FAQ

Will this survive a theme update? Not automatically. Theme updates overwrite files in the theme they update, so keep a copy of your snippet and reapply it after major theme upgrades. Duplicating the theme before editing gives you a fallback.

Can customers edit their message after saving? Not with the code above — the form hides once a message exists. To allow edits, remove the if check and pre-fill the textarea with the existing value, but expect some customers to change messages after fulfillment has started.

Does the gift message appear on the packing slip by default? No. You need to add {{ order.attributes['Gift message'] }} to your packing slip template or your order printer app's template. Check that your fulfillment integration passes order attributes through before relying on it.