Shopify Merchants on Standard Plans Are Losing Chargebacks Over Terms-of-Sale Proof — Here's the Evidence Trail You Can Build Without Plus
Banks are increasingly rejecting chargeback disputes unless merchants can show a timestamped record that the customer saw and agreed to their terms of sale before paying — evidence Shopify's hosted checkout doesn't generate by default, and that customizing the checkout page to fix directly requires Plus. Here's how to build a real consent trail on any plan, and where the gap still exists on accelerated checkout.
A thread on the Shopify Community forum lays out a problem that's easy to miss until it costs you real money: banks are now routinely rejecting chargeback disputes unless a merchant can produce specific proof that the customer saw and affirmatively agreed to the terms of sale before the card was charged — not just that a terms page exists somewhere on the site. The merchant who started the thread put it bluntly: standard-plan stores don't have the ability to customize Shopify's hosted checkout the way Plus stores can, so there's no built-in way to insert a mandatory, logged "I agree" step at the exact moment of payment. You lose the dispute not because you did anything wrong, but because you can't produce the specific artifact the bank's dispute team is asking for.
This isn't a hypothetical edge case. It's the same structural gap covered from a different angle in our checkout customization guide: modifying the checkout page itself — adding a custom validation, a mandatory checkbox, a blocking condition — has historically required Shopify Plus, because Shopify Functions and full checkout UI extension capacity are gated by plan. Terms-of-sale consent evidence just happens to be the specific place where that gap turns into lost revenue.
What the bank's dispute team is actually asking for
Replies in the thread narrow down what "proof" means in practice, and it's more specific than most merchants assume:
- Affirmative action, not passive availability. A link to
/policies/terms-of-servicein your footer proves the terms exist. It does not prove the customer read or agreed to them before paying. - A timestamp tied to the order. The record needs to show the agreement happened before or at the moment of purchase, not that a policy page was published at some point in the past.
- The evidence needs to match the dispute reason code. One reply in the thread (from a merchant handling disputes day to day) cautions that a dispute coded as outright fraud needs different evidence than one disputing "item not as described" or a subscription renewal the customer says they didn't agree to — a generic terms checkbox mainly helps with the second category, not the first.
None of this is unreasonable from the bank's side. It is, however, a real gap on Shopify's standard plans, because the one native setting built for exactly this — a confirmation step with terms text before the charge — isn't visible or configurable on every account by default.
Step 1: turn on the native confirmation step first
Before reaching for an app or custom code, check Settings → Checkout → Order processing for Require a confirmation step. When enabled, it adds a review screen after payment details are entered and before the order is placed, and lets you fill in Terms of sale and Refund policy text in the Policies section, referenced with placeholders like:
By completing your order, you agree to our %{terms_of_sale} and %{refund_policy}.
Two things worth knowing before you go looking for it:
- Some merchants report not seeing this checkbox in their admin at all. It appears to be gated by jurisdiction in certain accounts (it's mandatory in some regions and hidden elsewhere) rather than being a universal toggle. If it's missing from your Checkout settings, contact Shopify Support directly and ask for it to be enabled — don't assume it isn't available to your plan.
- This confirmation step is order-level, not itemized consent — it shows the same terms text to every customer regardless of cart contents. That's enough for general terms-of-sale disputes, but it won't help if you need proof of consent to something cart-specific (a final-sale/no-returns policy on a particular item, for instance).
Step 2: for cart-specific consent, capture it before checkout with a timestamped cart attribute
Because the checkout page itself is off-limits for custom logic without Plus, the practical workaround merchants in the thread converge on is moving the checkbox one step earlier, onto the cart page, and writing the agreement into a cart attribute so it rides through checkout and lands on the order as a permanent, timestamped record.
Add a checkbox to your cart template (via the theme editor's Cart & Checkout section, or directly in cart.liquid/main-cart-items.liquid depending on your theme):
<label for="terms-consent">
<input type="checkbox" id="terms-consent" required>
I agree to the <a href="/policies/terms-of-service" target="_blank">Terms of Sale</a>
</label>
On check, write the agreement — plus a timestamp — into the cart's attributes via the Ajax Cart API, so it's stored server-side against the cart rather than only in the browser:
document.getElementById("terms-consent").addEventListener("change", async (event) => {
if (!event.target.checked) return;
await fetch("/cart/update.js", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
attributes: {
terms_consent: "agreed",
terms_consent_timestamp: new Date().toISOString(),
terms_consent_version: "2026-07-01",
},
}),
});
});
Cart attributes carry through to the order and show up in the admin order page under Additional details, and in Liquid via order.attributes:
{% for attribute in order.attributes %}
{{ attribute.first }}: {{ attribute.last }}
{% endfor %}
Versioning the consent (terms_consent_version) matters more than it looks — if you update your terms of sale six months from now, you want every historical order to show which version of the terms the customer actually saw, not your current one.
Step 3: know exactly where this workaround stops covering you
Cart attributes only get written if the customer actually passes through your cart page. Dynamic checkout buttons — Buy it now, Shop Pay, Google Pay/Apple Pay buttons rendered directly on the product page — skip the cart entirely and take the customer straight into checkout. Any order placed through one of those buttons has no cart-attribute consent record, because the checkbox never rendered.
You have two honest options here, not a clean fix:
- Disable dynamic checkout buttons on product pages (Online Store → Themes → Customize → Product page → dynamic checkout button toggle) so every purchase is forced through the cart page where the checkbox lives. This costs you some one-click conversion speed to close the evidence gap.
- Accept the gap and document it. Rely on the native confirmation step from Step 1 for accelerated-checkout orders (it applies regardless of entry point, since it's rendered by Shopify's checkout itself), and use the cart-attribute record as a stronger, cart-specific supplement for standard-flow orders.
Don't present the cart-attribute checkbox to a client or your own team as "we now have full consent coverage" — it's real evidence, but only for the traffic that goes through the cart.
Step 4: on Shopify Plus, close the gap with a checkout validation Function
If you're on Plus, you can go further than a cart-page checkbox: block checkout completion entirely unless consent was captured, using a cart and checkout validation Function, the same replacement platform covered in our Shopify Scripts to Functions migration guide. The Function reads the cart attribute set by your checkbox and rejects checkout if it's missing, which is a materially stronger dispute artifact than a cart-page checkbox alone — the order literally could not have been placed without the flag being set:
export function cartValidationsGenerateRun(input) {
const hasConsent = (input.cart?.attribute?.value === "agreed");
if (hasConsent) return { operations: [] };
return {
operations: [
{
validationAdd: {
errors: [
{
message: "Please confirm you agree to the Terms of Sale to continue.",
target: "$.cart",
},
],
},
},
],
};
}
This still depends on the checkbox rendering somewhere before the validation runs (cart page or a checkout UI extension block), so pair it with a Checkout UI Extension that renders the checkbox directly inside checkout for Plus stores, rather than relying solely on the cart-page version.
What to actually submit when you dispute a chargeback
Having the record is only half the job — submit it in a form the bank's dispute portal can actually use:
- A screenshot or export of the order's Additional details section showing the
terms_consent, timestamp, and version attributes. - The exact terms-of-sale text that was live on that version date, not your current policy page — keep dated copies when you update your terms.
- Match the evidence to the dispute reason code before submitting. If the dispute is coded as fraud (card not authorized by the cardholder), a terms-agreement timestamp doesn't address that at all — you need fraud-specific evidence like AVS/CVV match results and device/IP data instead. Save the terms-consent evidence for disputes about policy, subscription terms, or "not as described."
Setting expectations honestly
None of this is a guaranteed dispute win — banks still weigh evidence case by case, and the community thread is clear that merchants remain uncertain how consistently these records actually convert to wins. What this does do is close the gap between "we have a terms page" and "we have a timestamped record tied to this specific order," which is the actual difference between evidence a dispute team accepts and evidence it doesn't.
Code Kaarigari builds cart-attribute consent capture, checkout validation Functions, and Checkout UI Extensions for stores on every plan tier, and can wire up an evidence trail that matches what your payment processor and bank actually ask for. Start with our Shopify development services, or contact Code Kaarigari to get a consent and evidence audit running against your own checkout flow.
Sources reviewed
- Shopify Community: Shopify Merchants Are Being Penalised for Chargeback Evidence We Literally Cannot Provide on Any Other Plan Other Than Plus
- Shopify Community: Checkout Review Order / Confirmation / Agree Terms and Conditions Setting
- Shopify.dev: Cart and Checkout Validation Function API
- Shopify.dev: Liquid cart object reference