Cart and checkout debugging - August 2026

Shopify Terms and Conditions Checkbox Not Working: Cart, Checkout, and Theme Fixes (2026)

A Shopify terms and conditions checkbox not working issue usually comes from cart JavaScript, AJAX drawer replacement, duplicate checkout buttons, or checkout customization limits.

~11 min read - cart forms, checkout buttons, app conflicts, Liquid snippets

Thunder Page Speed Optimizer cannot replace legal advice or decide whether your store needs a terms checkbox. It can optimize the cart and storefront code around that checkbox: app embeds, JavaScript, third-party scripts, images, and slow checkout-button interactions. Install Thunder for the performance layer, then use the manual checklist below to fix the checkbox behavior without breaking checkout.

Quick Fix with Thunder

A broken terms checkbox is a conversion and compliance problem. Customers either get blocked when they should not, or they can reach checkout without accepting your terms. Both outcomes damage trust.

Thunder's features reduce the app-script pressure around cart drawers and checkout buttons, which makes validation bugs easier to reproduce. Use it alongside the complete Shopify speed optimization guide if the cart drawer feels slow or unstable.

Install Thunder

First, Know Where Shopify Lets You Validate Terms

The first mistake is debugging checkout Liquid when the checkbox is actually on the cart. Shopify's hosted checkout is intentionally controlled. Standard stores cannot freely inject arbitrary checkout Liquid the way older themes once did. Shopify Plus stores and newer checkout extensibility setups have more options, but most merchants implement a terms checkbox on the cart page or cart drawer before the shopper reaches checkout.

That means the correct fix depends on the surface. A cart page checkbox needs a cart form submit listener. A cart drawer checkbox needs a listener that survives AJAX re-rendering. A product-page Buy Now path may skip the cart entirely, so your checkbox never runs. Dynamic checkout buttons can also bypass cart-page validation.

Shopify's own checkout and customer-account documentation is the right boundary source here. Use theme code for cart behavior, and use supported checkout settings or checkout extensions for checkout behavior. Do not rely on hidden scripts that try to manipulate hosted checkout fields from the storefront.

Terms checkbox surface map:
Cart page: validate the main cart form submit event.
Cart drawer: validate every checkout button after AJAX cart refreshes.
Product page Buy Now: either disable dynamic checkout or add a separate acceptance flow.
Hosted checkout: use supported Shopify settings, apps, or checkout extensibility.

Use Shopify's checkout settings documentation and Shopify checkout extensibility docs to confirm what belongs in checkout versus the cart. If the checkout button itself is unreliable, start with checkout button debugging and cart drawer fixes.

Fix a Terms Checkbox on the Cart Page

For a normal cart page, keep the logic simple: render the checkbox inside the cart form, require it before submit, and show an inline error message. Avoid code that only disables a button visually. A disabled-looking button can still be bypassed if another checkout link exists in the drawer, sticky bar, cart footer, or app embed.

In a Shopify theme, the exact file may be `main-cart-items.liquid`, `main-cart-footer.liquid`, `cart.liquid`, or a cart section. Put the checkbox near the checkout button so customers understand why checkout is blocked.

<label class="cart-terms">
  <input id="CartTerms" name="attributes[Accepted terms]" type="checkbox" required>
  I agree to the terms and conditions
</label>
<p id="CartTermsError" hidden>Please accept the terms before checkout.</p>
document.addEventListener('submit', function (event) {
  const form = event.target.closest('form[action="/cart"]');
  if (!form) return;

  const terms = form.querySelector('#CartTerms');
  const error = form.querySelector('#CartTermsError');
  if (!terms || terms.checked) return;

  event.preventDefault();
  if (error) error.hidden = false;
  terms.focus();
});

The order attribute stores the acceptance state on the order, which is useful for support review. Test with a real draft order path, a normal checkout path, and accelerated checkout buttons. If the cart form submits through JavaScript instead of a native form submit, you may need to attach validation to the checkout button click as well.

Fix a Terms Checkbox in an AJAX Cart Drawer

Cart drawers are where most checkbox bugs hide. The checkbox works on first page load, then stops working after a quantity change, cart refresh, upsell insertion, or free-shipping-bar update. That happens because the drawer's HTML gets replaced and the original event listener is attached to an old element that no longer exists.

Use event delegation from `document`, not a one-time listener on a button that may be replaced. Also validate every checkout trigger, not just the first button you find.

document.addEventListener('click', function (event) {
  const checkoutButton = event.target.closest('[name="checkout"], a[href="/checkout"]');
  if (!checkoutButton) return;

  const drawer = checkoutButton.closest('cart-drawer, .cart-drawer, #CartDrawer') || document;
  const terms = drawer.querySelector('[data-cart-terms]');
  const error = drawer.querySelector('[data-cart-terms-error]');

  if (!terms || terms.checked) return;

  event.preventDefault();
  event.stopPropagation();
  if (error) error.hidden = false;
  terms.focus();
}, true);

The capture phase matters because some cart apps attach their own checkout listener early. If an app redirects before your validation fires, capture-phase validation gives your code the first chance to stop the action. If that still fails, remove duplicate checkout buttons from app blocks or configure the app's own terms acceptance setting.

Related cart-state issues include cart not updating until refresh, add to cart button failures, and dynamic checkout button visibility.

Audit Apps, Duplicate Buttons, and Bypass Paths

A terms checkbox is only reliable if every checkout path respects it. Look for sticky cart bars, quick-buy drawers, bundle builders, subscription widgets, upsell modals, drawer checkout buttons, express payment buttons, and direct `/checkout` links. If any path skips the cart form, the checkbox can be bypassed.

Duplicate checkout buttons are common after years of theme edits. Search your theme for `name=\"checkout\"`, `/checkout`, `cart__checkout`, and app blocks that render checkout controls. Disable one app at a time in a duplicate theme and test again. If the checkbox suddenly works, the app is replacing or bypassing the cart form.

For performance, heavy app scripts also make debugging worse. A delayed cart drawer can cause customers to double-click checkout, trigger stale event handlers, or hit a button before the checkbox script has initialized. Clean this up with app script fixes, third-party JavaScript cleanup, and app leftovers cleanup.

Manual Fix vs Thunder Fix

ProblemManual fixThunder fix
Cart form skips validationAttach required checkbox validation to the cart form submit event.Not a legal checkbox generator.
AJAX drawer replaces markupUse delegated listeners that survive drawer refreshes.Reduces script delay around drawer interactions.
Apps add duplicate checkout buttonsDisable or configure app checkout triggers one by one.Optimizes app scripts and storefront JavaScript.
Storefront feels slowAudit scripts, images, and cart code manually.Automates common speed optimizations across the storefront.

For stores with complex checkout compliance, compare Thunder pricing with professional Shopify speed optimization.

Test Before You Publish the Fix

Test the checkbox in a duplicate theme before publishing. Use desktop, mobile, incognito, the cart page, the cart drawer, product-page dynamic buttons, subscription products, bundle products, and any accelerated wallets. Confirm that the error message is visible, focus moves to the checkbox, and checkout works immediately after acceptance.

Then run a before-and-after speed check. A working checkbox still hurts conversion if the cart drawer takes too long to open or the checkout button responds late. Use the free Shopify speed test, then compare slow-cart symptoms with checkout stuck loading and traffic but no sales.

Reference Shopify's current checkout documentation when deciding what belongs in checkout versus cart, and keep legal acceptance wording reviewed by your legal adviser if the checkbox is required for compliance.

FAQ

Why is my Shopify terms and conditions checkbox not working?

Most broken terms checkboxes come from cart drawer JavaScript, duplicate checkout buttons, AJAX form replacement, app conflicts, or code that listens to the wrong form submit event.

Can I add a required terms checkbox directly inside Shopify checkout?

Standard Shopify stores cannot freely edit hosted checkout Liquid. Shopify Plus and checkout extension setups have more checkout customization options, while most stores add the checkbox on the cart page.

Why does the checkbox work on the cart page but not the cart drawer?

Cart drawers often replace their HTML after quantity changes, so the original checkbox listener disappears unless the script re-binds after cart updates.

Can a Shopify app break a terms checkbox?

Yes. Upsell drawers, cart rewards bars, checkout-button apps, subscription apps, and popup apps can replace cart markup or submit checkout before your validation runs.

Can Thunder fix a broken terms checkbox?

Thunder does not create legal checkbox logic, but it can reduce cart script bloat and app conflicts so checkout-button behavior is easier to debug and faster for customers.

Fix the checkbox, then make the cart faster.

Repair Shopify terms checkbox validation, then use Thunder to reduce the cart scripts that make checkout bugs harder to debug.