LoopSolutions
All blueprints
BigCommerceCheckout+Frontend / cart-completion engineer

Checkout+ on BigCommerce

Loop Checkout+ is opt-in order protection offered at checkout. When a customer accepts it, that acceptance has to reach Loop's Orders API so the resulting return is recognized as a protected order. On BigCommerce the frontend builds the offer with Loop's Analyze Cart API and captures four resulting fields. From there, either Loop's pre-built BigCommerce connector syncs them up for you, or you push the order to Loop's Orders API yourself with the same payload shape.

Checkout+ on docs.loopreturns.com

Before you start

  • BigCommerce stencil or headless storefront where you control checkout completion.
  • A Loop instance with an active Checkout+ plan, and API keys generated from the Loop admin.
  • Checkout+ configured in the Loop admin (coverage rules, pricing tiers, eligible products).
  • A server-side endpoint that holds your Loop API keys — /v1/analyze is called server-side, never directly from the browser.

The pieces you need

What you're wiring together, regardless of which path you take below.

Analyze Cart caller

Server
Calls Loop's /v1/analyze on cart changes. Holds your Loop credentials. Returns coverage eligibility, price, session, and accepted offer mode.

Coverage offer UI

Browser
Renders the offer in the checkout/cart with the price returned by Analyze. Captures whether the customer accepted.

Acceptance state

Browser
Holds sessionId, mode[], chargeInstructions.amount, and chargeInstructions.currency between offer acceptance and order completion.

Metafield writer

Server
Connector path. After BigCommerce creates the order, writes four loop_checkout_plus metafields onto it via the BigCommerce Order Metafields API.

Orders API pusher

Server
DIY path. When not using the connector, pushes the order to Loop's Commerce Data Orders API with fees[] and metadata[] already populated from the four fields.

The flow

What happens, in order, from cart change to Loop seeing the protected order.

  1. Cart changes → call Analyze

    Server-side, hit Loop's /v1/analyze with the cart contents whenever items, quantities, or shipping address change.
  2. Loop responds with the offer

    Eligibility, price (chargeInstructions.amount + currency), sessionId, and mode[]. Render the offer in the checkout UI when eligible.
  3. Customer accepts (or skips)

    If they accept, capture all four values — sessionId, mode[], amount, currency — and carry them through to order completion.
  4. Checkout completes

    BigCommerce creates the order; you now have the order_id. Time to persist the four values somewhere Loop can read them.
  5. Persist the values

    Either write them onto the order as metafields (the connector reads + forwards) or push the enriched order to Loop's Orders API yourself.
  6. Loop sees the protected order

    Whether via the connector or your own sync, Loop's Orders API receives fees[] + metadata[] and the order is recognized as Checkout+.

Where to start

Build the Analyze Cart caller first. Get /v1/analyze returning a clean response server-side against a test cart before you touch any checkout UI. That endpoint is the foundation — everything below assumes you have those four fields (sessionId, mode[], chargeInstructions.amount, chargeInstructions.currency) in hand by the time the order completes.

Once it's working, the rest goes in this order:

  1. Render the offer in your checkout / cart UI using the price from Analyze.
  2. Capture acceptance into the four-field state — carry it through to order completion.
  3. Persist on one of two paths, depending on your setup:
    • Connector path — you're using Loop's pre-built BigCommerce connector. Write the four values as order metafields after the order is created. See below.
    • DIY path — you're rolling your own commerce data sync. Push the enriched order to Loop's Orders API yourself. Same payload shape; you're just the one calling the API.

The connector path — four metafields

If you're on Loop's pre-built BigCommerce connector, the work ends with four metafields. The connector watches BigCommerce orders, reads these, and forwards Checkout+ data to Loop's Orders API on every sync.

Write each value onto the order as a metafield under namespace loop_checkout_plus, with permission_set: read_and_sf_access. One POST per metafield (four POSTs total per order, or five if you set the optional fee_name).

All values map directly from the /v1/analyze response.
KeyTypeSourceExample
session_idstringsessionIdlop_a1b2c3d4e5f6g7h8i9j0
accepted_offer_modeJSON-encoded array of stringsmode[] — verbatim, do not sort, dedupe, or transform["returnCoverage","shippingProtection"]
fee_amountinteger cents (minor units)chargeInstructions.amount798 (= $7.98)
fee_currencyISO 4217 currency codechargeInstructions.currencyUSD
fee_nameoptionalstring— (defaults to Order protection if omitted)Order protection

Example metafield write

Repeat the call below for each of the four required keys (and optionally fee_name).

BigCommerce Order Metafields APIhttp
POST /v3/orders/{order_id}/metafields
Content-Type: application/json
X-Auth-Token: <bc store token>

{
  "namespace": "loop_checkout_plus",
  "key": "session_id",
  "value": "lop_a1b2c3d4e5f6g7h8i9j0",
  "permission_set": "read_and_sf_access"
}

All or nothing

If any of session_id, accepted_offer_mode, fee_amount, or fee_currency is missing or malformed, the connector drops the entire Checkout+ block for that order and logs a warning. The order itself still syncs to Loop — just without coverage.

Why: Loop's Orders API returns 422 fees.0 field is unsupported when accepted_offer_mode is sent without a matching fee. Skipping is safer than breaking the sync.

Write all four, or write none.

The DIY path — push to Loop's Orders API yourself

If you're not using the connector — or you're rolling your own commerce data sync — the same four values still need to reach Loop. The shape the connector would have built is what you build. POST the enriched order to Loop's Orders API with fees[] and metadata[] populated:

Loop Orders API — enriched payloadjson
{
  "...": "standard order fields",
  "fees": [
    {
      "name": "Order protection",
      "amount": { "amount": 798, "currency_code": "USD" },
      "accepted_offer_mode": ["returnCoverage", "shippingProtection"]
    }
  ],
  "metadata": [
    { "key": "session_id", "value": "lop_a1b2c3d4e5f6g7h8i9j0" }
  ]
}

Idempotency

Loop's Orders API replaces fees[] and metadata[] on every upsert — it does not append. Re-send the same Checkout+ payload on every order update (fulfillment, refund, etc.). No need to guard against duplicate writes.

The connector does this automatically; on the DIY path, build your update payloads to always include the Checkout+ block when it applied at checkout.

Pitfalls

  • Never call /v1/analyze from the browser — your Loop credentials must stay server-side.
  • mode[] is verbatim — don't sort, dedupe, or transform it. Loop's portal matches against the exact value the customer accepted.
  • fee_amount is cents, not dollars. 798, not 7.98.
  • All-or-nothing on the four required fields — the connector drops the whole block if any is missing or malformed.
  • Loop's Orders API replaces fees[] and metadata[] on every upsert. Always include the Checkout+ block on subsequent order updates.
  • HTTPS everywhere — applies to every Loop integration.