Overview
Shop Now: On-Store redirects a shopper from the Loop returns portal to your storefront to pick replacement products with their return credit. When they’re done, your storefront hands the selected items back to Loop as a cart token, and Loop completes the exchange server-side. Most merchants implement this with Loop’s On-Store SDK, which assumes it runs inside a Shopify Online Store theme. This guide is for headless / custom storefronts that need to implement the same flow themselves, without the SDK. It documents the contract the Loop portal and Loop API expect, and the theme dependencies a headless storefront must replace.Shopify Checkout is never used in this flow. Loop creates the exchange order itself, and computes all exchange pricing, credit, bonus, and tax — not Shopify. Store discount codes and Shopify Functions do not apply to the exchange.
- Inbound — read the
loop_*query params on your landing page and enter “on-store mode”. - Handoff — when the shopper checks out, collect the selected variant IDs,
POSTthem to the Loop Cart API, and store the returned token. - Outbound — redirect back to the Loop portal with that token, and clear your own cart.
How It Works
Base URL
The Cart API is served from:Authentication
The Cart API uses the same authentication as the rest of Loop’s APIs. Send your merchant API key in theX-Authorization header — see Authentication for how to create and manage keys, the full header contract, and the 401 response shape.
The key must have the Carts scope. Generate one from Returns Management → Tools & integrations → Developer tools in the Loop Admin and select the Carts scope.
Step 1 — Inbound: portal → storefront
Loop redirects the shopper to your storefront (your apex domain, or a market-localized URL) withloop_* query params. On-store mode is keyed on the presence of loop_total.
Query parameters
Amounts are minor units in the shop base currency (e.g.
12099 = 120.99). For multi-currency display, convert using your own storefront FX rate. The portal omits any param with a falsy value, so treat loop_total as the reliable credit total and don’t assume loop_base / loop_credit are always present.What to do on landing
1
Detect on-store mode
Check for
loop_total in the query string. Its presence means the shopper arrived from the Loop portal in Shop Now: On-Store mode.2
Persist the loop_* values
Store the
loop_* values (for example in sessionStorage or localStorage) so they survive navigation across your store.3
Discard stale carts
If
loop_return_id differs from a previously saved session, discard any saved cart or token — it belonged to a different return.4
Render a credit UI (optional)
Show available credit and bonus % from
loop_total and loop_discount_percentage.5
Suppress non-applicable UI (recommended)
Hide storefront elements that don’t apply during an exchange: discount-code popups, alternative payment buttons (PayPal, Afterpay, Google Pay), home try-on, sticky mobile add-to-cart, and chat widgets. Store discounts and Functions will not apply to the exchange.
Step 2 — Handoff: storefront → Loop Cart API
When the shopper is done and clicks your “checkout” equivalent, collect the selected Shopify variant IDs from your cart andPOST them to the Cart API.
Each variant ID must resolve to a real Shopify variant for the shop — Loop validates against Shopify and returns Variant ID X not found. otherwise. The cart array is required and must be non-empty.
Create a cart
token — persist it:
To amend the selection later,
POST /api/v1/cart/{token} with a new full cart array — it replaces the cart contents. See the Cart API reference for the full request and response schema, including update and delete.Step 3 — Outbound: storefront → portal
Once you have atoken:
1
Clear your storefront cart
Empty your own cart so the shopper doesn’t accidentally buy the items through normal checkout. Skip only if you intentionally preserve it.
2
Redirect back to the Loop portal
Send the browser back to the portal with the token. Only the token travels in the URL — the variant selections were persisted server-side in Step 2.
Redirect URL rules
URL-encode
token, to, and return_key. {loop_domain} and {loop_redirect_url} come from the inbound params.Carrying storefront discounts into the exchange
To keep a discount the shopper had on your storefront in the exchange, send it to the Cart API in the optionalshopify field — a Base64-encoded copy of the Shopify Ajax cart object (GET /cart.js). Loop reads the discount fields already present in that object; it does not evaluate discount codes or Shopify Functions itself.
Loop only consumes this snapshot when your shop is configured to use Shopify Scripts. Without it, the snapshot is ignored and exchange items price at catalog price. Most headless stores don’t need it — omit
shopify entirely unless you carry cart discounts.Where the discount data comes from
The snapshot is Shopify’s own cart object, so you don’t build the schema yourself — you take what Shopify already gives you:1
Apply the discount on the Shopify cart
Add or manage discount codes with
POST /cart/update.js ({ "discount": "CODE" }; comma-separate for multiple, empty string to clear).2
Read the resulting cart
Fetch the cart with
GET /cart.js. The response now carries the discount fields (total_discount, cart_level_discount_applications, per-item discount_allocations).3
Base64-encode it as `shopify`
Send that cart object as the
shopify field on POST /api/v1/cart (see below).What Loop reads
Loop consumes a subset of the/cart.js object. All money values are minor units (cents), exactly as Shopify returns them:
- Cart level —
currency,total_price,total_discount, and eachcart_level_discount_applications[]entry (title,value,value_type,total_allocated_amount). - Per line item (
items[]) —variant_id,quantity,original_price,discounted_price,final_line_price, and eachdiscount_allocations[]/line_level_discount_allocations[]entry (amount,discount_application).
/cart.js object with a 10% cart-level discount and a line-level discount — see the Shopify reference for the full shape:
Sending the snapshot
Base64-encode the cart object and include it asshopify alongside cart. Do this on your backend so the API key stays server-side:
Node (server-side)
In the browser the equivalent encoding is
btoa(unescape(encodeURIComponent(json))), but prefer encoding and sending from your backend. Regardless of the snapshot, exchange pricing, credit, bonus, and tax are always computed by Loop, not by Shopify checkout.Replacing the theme dependencies
The stock On-Store SDK assumes it runs inside a Shopify Online Store theme. A headless storefront must provide substitutes for each dependency:Eligibility and access
Access to the Cart API is granted through the Carts scope on your API key, which Loop provisions when Shop Now: On-Store is enabled for your account. Contact support@loopreturns.com to get set up. If the API key isn’t authorized — On-Store isn’t enabled for the shop, or the key lacks the Carts scope — the Cart API responds with 401 Unauthorized:Minimal reference implementation
The browser never sees the API key. It calls your own backend, which holds the Carts-scoped key and forwards the request to Loop.Storefront (browser)
Your backend proxy (Node)
Technical considerations
Related Resources
On-Store Exchanges
Conceptual overview of Shop Now and Shop Now: On-Store.
Create Cart — API Reference
Full request and response schema for the Cart API (create, get, update, delete).