Checkout Price Change (tag pair)
Use {exp:cartthrob:checkout_price_change} only as the target of a
checkout_form configured with price_change_handling="template" and
a price_change_template in group/template form.
The tag reads the opaque state identifier CartThrob places in the target URL. Do not create, alter, or expose that value yourself. It outputs no results when the state is missing, expired, consumed, from another session or cart, or used on a template other than the configured target.
Parameters
state
Optional. When omitted, the tag reads the state from the request URL. If supplied, it must be the same opaque token generated by CartThrob. It is not a price, quote ID, payment reference, or card value.
{exp:cartthrob:checkout_price_change}
...
{/exp:cartthrob:checkout_price_change}
Variables
The following single variables are available:
{checkout_price_changed}(1){checkout_price_change_handling}(template){checkout_price_change_currency}{checkout_price_change_precision}{checkout_price_change_expires_at}{checkout_changed_components_list}(pipe-delimited names){checkout_price_change_title}{checkout_price_change_description}{checkout_price_change_continue_label}{checkout_price_change_cancel_label}{checkout_price_change_continue_url}{checkout_price_change_cancel_url}{checkout_previous_subtotal},{checkout_previous_discount},{checkout_previous_shipping},{checkout_previous_tax},{checkout_previous_total_adjustment}, and{checkout_previous_total}{checkout_previous_subtotal_numeric},{checkout_previous_discount_numeric},{checkout_previous_shipping_numeric},{checkout_previous_tax_numeric},{checkout_previous_total_adjustment_numeric}, and{checkout_previous_total_numeric}{checkout_current_subtotal},{checkout_current_discount},{checkout_current_shipping},{checkout_current_tax},{checkout_current_total_adjustment}, and{checkout_current_total}{checkout_current_subtotal_numeric},{checkout_current_discount_numeric},{checkout_current_shipping_numeric},{checkout_current_tax_numeric},{checkout_current_total_adjustment_numeric}, and{checkout_current_total_numeric}{checkout_previous_item_tax},{checkout_previous_shipping_tax},{checkout_previous_discount_tax},{checkout_previous_discount_total}and their_numericvariants{checkout_current_item_tax},{checkout_current_shipping_tax},{checkout_current_discount_tax},{checkout_current_discount_total}and their_numericvariants{checkout_previous_has_tax_breakdown}and{checkout_previous_tax_allocation}{checkout_current_has_tax_breakdown}and{checkout_current_tax_allocation}{checkout_previous_subtotal_source},{checkout_previous_shipping_source},{checkout_previous_tax_source}, and{checkout_previous_total_source}{checkout_current_subtotal_source},{checkout_current_shipping_source},{checkout_current_tax_source}, and{checkout_current_total_source}{checkout_subtotal_changed},{checkout_discount_changed},{checkout_shipping_changed},{checkout_tax_changed}, and{checkout_total_changed}(1or0)
Test the matching has_tax_breakdown variable before displaying item,
shipping, or discount-tax details. Those values are blank and allocation is
unallocated when the finalized aggregate tax cannot be split exactly; the
aggregate previous/current tax remains available. Sources are calculated,
fixed, submitted, or extension.
The adjustment is derived from the other primary amounts. It is display-only, not an additional charge or an independently changed component.
{checkout_changed_components} is a tag pair. It provides one row for
each changed component with {component}, {label}, {previous},
{previous_numeric}, {current}, and {current_numeric}.
Example
<section
data-ct-checkout-price-change-modal
aria-labelledby="price-change-title"
>
{exp:cartthrob:checkout_price_change}
<h1 id="price-change-title">
{checkout_price_change_title}
</h1>
<p>{checkout_price_change_description}</p>
<p>Adjustment: {checkout_previous_total_adjustment} → {checkout_current_total_adjustment}</p>
<p>Previous total: {checkout_previous_total}</p>
<p>Current total: {checkout_current_total}</p>
{checkout_changed_components}
<p>{label}: {previous} → {current}</p>
{/checkout_changed_components}
<p>
<button
type="button"
data-ct-checkout-price-change-confirm
>
{checkout_price_change_continue_label}
</button>
<button
type="button"
data-ct-checkout-price-change-cancel
>
{checkout_price_change_cancel_label}
</button>
</p>
{/exp:cartthrob:checkout_price_change}
</section>
CartThrob fetches the target template, extracts
[data-ct-checkout-price-change-modal], and presents it over the
existing checkout. The target controls the content and styling.
CartThrob intercepts the two marked buttons to continue or cancel the
original checkout submission. Because the page does not change, hosted
payment fields such as Stripe Elements and PayPal Hosted Fields remain
mounted.
Put any CSS needed by the modal inside the marked section or in a stylesheet already loaded by the checkout page. Scripts returned in the fetched template are not executed; use the documented data attributes for the two actions.
For backward compatibility, a target without
data-ct-checkout-price-change-modal uses the older full-page
transition. The Continue URL returns to the original checkout form with
one-time acceptance state, while Cancel returns without accepting the
updated total. Hosted payment fields cannot be serialized or restored
after that navigation, so payment details must be entered again.
AJAX can also update coupons, addresses, shipping selections, and the displayed total before the final checkout submission.
The tag intentionally returns no_results for invalid state. The
surrounding ExpressionEngine template owns any empty-state or HTTP
status behavior.