Integration modes
The Shipping Protection (SP) integration mode controls two things: when the fee line is written to the cart, and which SDK method your checkout button calls. Your account manager (AM) configures the integration mode in the back office. Your code can read it, but cannot modify it:
window.xcotton.sp.getMode() // 'cart' | 'checkout' | 'checkoutPlus'All three modes share the exact same init, syncCart, and adapter setup. Changing the mode changes when the fee line is written, how the first sync cleans the cart, and which call your checkout buttons make. Everything from the Quick start stays unchanged.
The three modes at a glance
Section titled “The three modes at a glance”| Aspect | cart | checkout | checkout+ |
|---|---|---|---|
getMode() return value | 'cart' | 'checkout' | 'checkoutPlus' |
| Panel UI (back-office setting) | Includes a toggle switch | Includes a toggle switch | Price display only (no switch) |
| When the switch is toggled | Immediately adds or removes the fee line | Records the customer’s choice and updates the price. Cart is untouched | — |
| When the fee line is written | On switch toggle. The first sync and any sync whose SP inputs changed also align it | At checkout, resolveSP() follows the switch intent | addSpFee() on “Checkout with protection”.declineSpFee() on “Checkout without protection” |
| Checkout button behavior | await resolveSP(), then navigate | Same as cart | Buttons call await addSpFee() / await declineSpFee() |
| Additional code required | Call resolveSP() from checkout, block on failure, retry while busy | One checkout click handler | Two checkout buttons and their click handlers |
In cart mode, toggle-triggered fee writes are asynchronous. The SDK does not intercept native checkout links or make browser navigation wait for a write. Your storefront must call resolveSP() at the checkout boundary. When the intent is on, it re-quotes and aligns the fee line. When the intent is off, it removes the fee line or confirms that none exists (added / removed / skipped). It rejects if adding or removing the fee line fails. resolveSP() does not queue behind a switch write. While a toggle-triggered write is still running, it rejects with OPERATION_IN_PROGRESS. Wait for the write to settle and retry. Navigate only after it resolves. For any other rejection, stay on the page and show the error.
Waiting only for storefront cart requests, observing onCartChange, or seeing a successful recovery read does not prove that the toggle write you just triggered succeeded: a recovery read after a failed write can also trigger onCartChange. The pre-checkout resolveSP() (or addSpFee() / declineSpFee() in checkout+) is the public entry point that observes the write result.
When a cart is first synchronized
Section titled “When a cart is first synchronized”On the initial syncCart(cartId) call (or init({ cartId })), and whenever you switch to a different cart ID, the SDK applies the mode’s entry handling. checkout and checkout+ remove leftover fee lines before refreshing the quote.cart refreshes the quote first, then aligns the fee line with the switch intent:
cart mode. The switch intent is resolved as follows:
- Fee line and a main product in cart: keep the fee line and set the switch to on. Exception: if this browser saved an off intent and the cache has not expired, remove the fee line as saved.
- No fee line in cart: add the fee line or leave it out according to the switch intent saved in this browser. If nothing was saved, apply the default state configured by your account manager (AM). Apply that default as well on the first visit to the
/cartpage when the cart has a main product and this browser saved an intent.
The intent cache expires 2 hours after each write. Expiry does not reset every intent to the back-office default. It affects only rule 1: when the cache has expired and the cart has a fee line and a main product, the switch is forced on.
In cart mode, the SDK aligns the fee line with both intent and current eligibility. When the switch intent is on and the cart is eligible, the SDK keeps exactly one fee line with quantity 1. Otherwise, it removes every fee line.
checkout and checkout+ modes. The SDK removes any leftover fee line from the cart regardless of switch state. In both modes, the fee line is written strictly at checkout time. In checkout+ the switch intent is only a generic-model placeholder (initially fixed to on): the SDK never reads, writes, or renews the switch cache.
After the initial sync, syncCart(cart.id) compares the cart facts before and after the sync and re-quotes only when an SP input changes, such as a main product line, a discount code, or a cart-level attribute. Adding or removing a PP protection line does not trigger an SP quote. Switching to another cart runs the mode’s initial handling again. In cart mode, the SDK also removes the fee line whenever the cart becomes empty or the order subtotal falls outside the eligible range. In checkout and checkout+ modes, it updates the quote only and defers fee line changes until checkout.
What your storefront renders
Section titled “What your storefront renders”The SP selector discovers storefront containers and excludes SDK panel and modal subtrees. A container keeps its panel after its first match until the node leaves the document or the configured selector changes. Changing attributes such as its class after mounting does not release the panel. This prevents selectors such as :empty from repeatedly mounting and removing their own content. Remove the container node to dispose of its panel.
The SDK renders only the panel inside your container. It never replaces your checkout button or injects a secondary “without protection” button. Your account manager (AM) configures the panel style to match the integration mode, while your storefront renders the container and checkout buttons:
| Element | cart | checkout | checkout+ |
|---|---|---|---|
| Panel style | With a switch | With a switch | Use the price-only panel without a switch |
| Checkout button | Add resolveSP() to the existing button’s click handler. Block on failure | Existing button whose click handler calls resolveSP() | Two buttons calling addSpFee() and declineSpFee() |
checkout+ has no switch intent. If the back office still pairs this mode with a switch panel, the switch only changes the placeholder intent. It writes no cart line and checkout never reads it. The customer’s choice is therefore expressed only by the two checkout buttons, so the page must provide the “without protection” button as well. Do not call resolveSP() (it rejects and points you to the two write entries), and the modal does not show the intent button. You provide both the panel container and the button handlers.
Next steps
Section titled “Next steps”cart: the Quick start covers the basic setup. Also implement the checkout call, failure blocking, and busy retry described above.checkout: continue to Checkout mode.checkout+: continue to Checkout+ mode.