How to Add Custom Fields to Shopify Checkout (with Liquid)

Want to stay in the loop?

Subscribe to receive updates, insights, and special offers straight to your inbox.

Share your email so we can get in touch

What is checkout.liquid and why Shopify Plus matters

checkout.liquid is the Liquid template that renders the checkout experience for Shopify Plus stores. Shopify restricted editing of this template to Plus merchants to protect the checkout’s security, performance and PCI compliance.

Why it matters

  • Editing checkout.liquid gives you direct control over where fields appear and how they behave.
  • Shopify saves values added in inputs named attributes[...] as order attributes attached to the order object.
  • If you’re on a plan below Plus, the supported and stable solutions are cart attributes, line item properties, apps, or the newer Checkout Extensibility (Checkout UI Extensions / Functions).

In my experience, I’ve seen store owners try clever hacks on non-Plus stores, they sometimes work briefly but break with theme updates or Shopify platform changes. I always recommend the stable routes unless you have Plus.

Example: Add a simple “Delivery Instructions” field (step-by-step)

Overview: we’ll add a text input called delivery_instructions and show how Shopify saves it.

Where to place the HTML in checkout.liquid

Open your Plus store’s theme editor:

  1. Go to Online Store > Themes, duplicate the theme.
  2. Edit code of the duplicated theme.
  3. Open templates/checkout.liquid (or the checkout layout file indicated in your theme).
  4. Locate the position where you want the field — typically order-summary or inside the main form before the payment section.

Important: insert within the checkout form so values are submitted with the order.

Liquid + HTML snippet (text input)

{%- comment -%}
Delivery instructions example.
Place this inside the checkout form where you want the field to appear.
{%- endcomment -%}

<div class="custom-field delivery-instructions" aria-live="polite">
  <label for="checkout_attributes_delivery_instructions" class="custom-label">
    Delivery instructions (optional)
  </label>
  <input
    id="checkout_attributes_delivery_instructions"
    name="attributes[delivery_instructions]"
    type="text"
    maxlength="500"
    class="input--text"
    placeholder="Leave any delivery notes for the courier"
    value="{{ checkout.attributes.delivery_instructions | escape }}"
  />
</div>

Explanation

  • name="attributes[delivery_instructions]" — Shopify saves this under order.attributes.delivery_instructions.
  • value="{{ checkout.attributes.delivery_instructions }}" — prepopulates field during checkout (useful for edit flows).
  • escape to avoid XSS if the attribute previously contained special characters.

In my experience, the value="{{ checkout.attributes.xxx }}" pattern is essential: when customers edit their order or the page reloads, their input stays. I added this in a client project and it dramatically reduced abandoned checkouts because users didn’t lose typed notes.

How Shopify stores the value (attributes[...]) and how to access it

  • When the order is created, attributes are visible in the Order admin under additional details.
  • Via Liquid on order confirmation/notifications: use {{ order.attributes.delivery_instructions }}.
  • Through API: order attributes are included in the order JSON (useful for fulfillment flows or webhook processing).

Example: show the attribute on the order status page (thank you page)

{%- if order.attributes.delivery_instructions -%}
  <section class="order-attribute">
    <h3>Delivery instructions</h3>
    <p>{{ order.attributes.delivery_instructions }}</p>
  </section>
{%- endif -%}

Tip: sanitize or escape the attribute when rendering to avoid injecting unsafe HTML.

Example: Add a checkbox / gift message field

If you want a boolean choice or small message (e.g., gift wrap), use checkbox + conditional:

<div class="custom-field gift-wrap">
  <label>
    <input
      type="checkbox"
      name="attributes[gift_wrap]"
      value="yes"
      {% if checkout.attributes.gift_wrap == 'yes' %}checked{% endif %}
    />
    Add gift wrap
  </label>
</div>

{%- if checkout.attributes.gift_wrap == 'yes' -%}
  <div class="custom-field gift-message">
    <label for="checkout_attributes_gift_message">Gift message (optional)</label>
    <textarea
      id="checkout_attributes_gift_message"
      name="attributes[gift_message]"
      maxlength="250"
    >{{ checkout.attributes.gift_message | escape }}</textarea>
  </div>
{%- endif -%}

Notes

  • Store gift_wrap as "yes" (or blank) to represent state.
  • Use checkout.attributes... to prepopulate.

In my experience, pairing a checkbox with a conditional message field improves UX: customers only see the message box when relevant. I implemented this for seasonal campaigns and conversion rates increased slightly because the checkout looked cleaner.

Validation & UX: making the field required, maxlength, styling

Shopify checkout handles form submission; however, you can add client-side validation via JS (be careful and test). Example minimal JS for required field:

<script>
  (function() {
    var form = document.querySelector('form[action*="/checkouts/"]');
    if (!form) return;

    form.addEventListener('submit', function(e) {
      var input = document.querySelector('input[name="attributes[delivery_instructions]"]');
      if (input && input.dataset.required === "true" && input.value.trim().length === 0) {
        e.preventDefault();
        alert('Please add delivery instructions before continuing.');
        input.focus();
      }
    });
  })();
</script>

Caveats

  • Client-side validation is UX polishing only — avoid preventing server submission without thorough testing.
  • Accessibility: use labels, ARIA attributes and adequate color contrast.
  • Styling: follow theme classes to keep visual consistency (input--text is example class; adapt to your theme).

Alternatives if you’re not on Shopify Plus

If your store is not on Plus, do not try to “hack” the checkout. Safer options:

Add fields on the cart page (Cart attributes)

Add inputs named attributes[...] on the cart form so values are carried to the order:

<form action="/cart" method="post" id="cart-form">
  <!-- ...cart rendering... -->
  <label for="cart_attributes_delivery_instructions">Delivery instructions</label>
  <input id="cart_attributes_delivery_instructions" name="attributes[delivery_instructions]" type="text" />
  <!-- Cart update button -->
</form>

Behaviour: values entered on the cart page will be saved and appear in the order as attributes once the customer completes checkout.

Use apps (recommended for non-Plus)

Apps like HulkApps, Accentuate, or dedicated checkout field apps provide UIs and backend handling without editing checkout.liquid. They’re especially useful for conditional logic or field syncing.

In my experience, when I didn’t have Plus I used the cart attribute approach or a reputable app. It’s much faster and safer — and you avoid maintenance headaches.

Checkout Extensibility (Shopify recommended)

Shopify now pushes Checkout UI Extensions and backend checkout APIs for extensible UX. For new stores and forward-looking implementations, evaluate Checkout Extensibility (it uses different tech and deployment workflow than Liquid).

Testing, backup and deployment checklist

  1. Duplicate theme and work on the copy.
  2. Test on desktop and mobile browsers.
  3. Place test orders (use payment gateway test mode).
  4. Verify attributes appear in order admin and in webhooks/API responses.
  5. Check email/notifications if you render the value in order confirmations.
  6. Revert if anything blocks checkout.

In my experience, thorough testing with multiple browsers and real orders avoided issues where input focus or CSS overlapped the “Place order” button — a small CSS error once hid the button under a fixed footer.

Troubleshooting & common pitfalls

  • Field not saved: check name="attributes[...]" spelling. If placed outside the checkout form, it won’t be submitted.
  • Value lost on reload: make sure to use value="{{ checkout.attributes.field | escape }}".
  • Layout breaking: inspect CSS; avoid global selectors that change core checkout elements.
  • Checkout blocked: if JS errors occur, they may block submission — check console logs.
  • Non-Plus workarounds failing: don’t rely on theme hacks; use cart attributes or apps.

Conclusion + Recommended next steps

  • If you are on Shopify Plus, editing checkout.liquid with properly named inputs (attributes[...]) is a straightforward way to collect extra data. Use the code snippets above as a starting point.
  • If you’re not on Plus, prefer cart attributes or a dependable app.
  • Consider upgrading to Checkout Extensibility for long-term, supported customization.

When I implemented this for clients I always prioritized safety: duplicate theme, test orders, and prefer minimal JS. That workflow saved time and avoided regressions.


FAQs

Q: Can I edit checkout.liquid if I’m not on Shopify Plus?

A: No — Shopify restricts checkout.liquid edits to Plus stores. Don’t attempt unsupported hacks.

Q: Are attributes secure / visible to customers?

A: Attributes are saved with the order and visible in order admin and to the customer if you render them (like in confirmation). Avoid storing sensitive personal data in plain attributes.

Q: Will theme updates overwrite my changes?

A: If you edit a published theme, updates from the theme vendor may override changes. Use theme versions and backups.

Q: Can I map attributes to fulfillment or shipping apps?

A: Yes — use webhooks or API calls to read order.attributes and sync to fulfillment systems.

Ready to transform your store and see meaningful results in your metrics? Contact us today and let’s start building your success.

Latest Articles

Thumbnail for Shopify vs Wix: Which One Is Right for Your Business?
November 17, 2025 | 3 min read

Shopify vs Wix: Which One Is Right for Your Business?

Thumbnail for Shopify Blog SEO: How to Drive Traffic with Content
November 03, 2025 | 6 min read

Shopify Blog SEO: How to Drive Traffic with Content

Thumbnail for How to Prepare Your Shopify Store for Black Friday
October 30, 2025 | 5 min read

How to Prepare Your Shopify Store for Black Friday