{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":["admonition"]},"type":"markdown"},"seo":{"title":"Headless Shopify","description":"Add Onward Checkout+ to a headless Shopify storefront with the Shopify Storefront SDK."},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"headless-shopify","__idx":0},"children":["Headless Shopify"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["On a headless Shopify storefront (Hydrogen, Next.js, or any custom frontend), Onward can't add Checkout+ through your theme. Instead, you load the Onward headless script, give it access to your cart, and tell it where your cart's checkout button is."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The integration has five steps:"]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Load the Onward headless script"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Implement a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["StorefrontClient"]}," for your cart"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Initialize Onward and attach it to your cart"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Tell Onward when the cart changes"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Hide the Onward product in your cart"]}]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info","name":"Before you start"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Install the Onward Shopify app on your store. It creates the Onward product that is added to the cart at checkout."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"step-1-load-the-headless-script","__idx":1},"children":["Step 1: Load the headless script"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Add this script to every page that shows a cart, replacing ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["example.myshopify.com"]}," with your store's ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["myshopify.com"]}," domain:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"html","header":{"controls":{"copy":{}}},"source":"<script src=\"https://proxy.useonward.com/public/assets/onward_headless.js?shop=example.myshopify.com\" async></script>\n","lang":"html"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The script carries your store's Onward settings and defines ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["window.initializeOnward"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["window.OnwardSetup"]},". It dispatches an ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onward:loaded"]}," event on ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["window"]}," once both are available."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"step-2-implement-a-storefrontclient","__idx":2},"children":["Step 2: Implement a StorefrontClient"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Onward reads and updates your cart through an object you write that implements the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/shopify_storefront_sdk/storefront_client/interfaces/storefrontclient"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["StorefrontClient"]}]}," interface, usually on top of the Shopify Storefront API. Implement every method: which ones Onward calls depends on your store's Checkout+ settings, and those can change without a code change on your side."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The methods return a ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/shopify_storefront_sdk/storefront_client/interfaces/cart"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Cart"]}]},", so you'll map your cart into that shape. A few details matter:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["fetchInsuranceProduct"]}]},": look the Onward product up by its handle, ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onward-package-protection"]},", not by ID, and include a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["price"]}," on every variant."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["requiresShipping"]}]},": set it to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["true"]}," on each ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/shopify_storefront_sdk/storefront_client/interfaces/productvariant"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ProductVariant"]}]}," that ships. Onward only protects lines where it is ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["true"]},", so leaving it unset means nothing in the cart is protected."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Subscriptions and line item properties"]},": if your store uses them, pass ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["sellingPlanIdentifier"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["properties"]}," through on cart lines. ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["clearCart"]}," empties the cart and Onward re-adds every line, so anything you drop is lost."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"step-3-initialize-onward-and-attach-it-to-your-cart","__idx":3},"children":["Step 3: Initialize Onward and attach it to your cart"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Once the script has loaded, initialize Onward with your ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["StorefrontClient"]},", then use ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/shopify_storefront_sdk/onward_setup/classes/onwardsetup"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["OnwardSetup"]}]}," to place the widget and connect your checkout button:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"javascript","header":{"controls":{"copy":{}}},"source":"window.addEventListener('onward:loaded', () => {\n  window.initializeOnward({ storefrontClient: new MyStorefrontClient() });\n\n  const onward = new window.OnwardSetup();\n  onward.addContainer('.cart-footer', { position: 'afterbegin' });\n  onward.attachCheckoutButton('.cart-footer .checkout-button', {\n    optOutSelector: '.cart-footer',\n  });\n});\n","lang":"javascript"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Replace the selectors with your own:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/shopify_storefront_sdk/onward_setup/classes/onwardsetup#addcontainer"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["addContainer"]}]}," renders the Onward widget. We recommend placing it directly above the checkout button."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/shopify_storefront_sdk/onward_setup/classes/onwardsetup#attachcheckoutbutton"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["attachCheckoutButton"]}]}," makes sure the cart is protected when the customer checks out, and adds a link inside ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["optOutSelector"]}," for customers who want to check out without protection."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Call ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["initializeOnward"]}," before creating ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["OnwardSetup"]},", and do both once per page load. ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["OnwardSetup"]}," watches the page for elements that match your selectors, so a cart drawer that opens later or re-renders is picked up automatically."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["By default, Onward continues to checkout by clicking your original checkout button. If your checkout is started some other way, pass a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["continueToCheckout"]}," function to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["attachCheckoutButton"]},". ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/shopify_storefront_sdk/onward_setup/interfaces/attachcheckoutoptions"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["AttachCheckoutOptions"]}]}," lists that and the other options."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If your storefront sells in more than one currency or language, also pass a ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/shopify_storefront_sdk/initialization/interfaces/ilocale"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["locale"]}]}," to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["initializeOnward"]},". Without it, Onward assumes USD and English."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"step-4-tell-onward-when-the-cart-changes","__idx":4},"children":["Step 4: Tell Onward when the cart changes"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Onward reads your cart once when it initializes. After that, pass it the updated cart every time it changes (items added or removed, quantities updated), so the protection price stays current and the right protection is added at checkout:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"javascript","header":{"controls":{"copy":{}}},"source":"await window.onwardApp?.cartChanged(cart);\n","lang":"javascript"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["cart"]}," is the same ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/shopify_storefront_sdk/storefront_client/interfaces/cart"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Cart"]}]}," shape your ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["StorefrontClient"]}," returns."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"step-5-hide-the-onward-product-in-your-cart","__idx":5},"children":["Step 5: Hide the Onward product in your cart"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Onward can add its product to the cart as the customer heads to checkout, so it may still be there if they come back to your store. Onward doesn't control how your cart renders, so leave out lines for the product with the handle ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onward-package-protection"]}," when you display the cart. Keep them in the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Cart"]}," you return from your ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["StorefrontClient"]}," and pass to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["cartChanged"]},"; Onward needs to see them."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"testing","__idx":6},"children":["Testing"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["With products in the cart, check that:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The Onward widget appears where you placed it and shows a protection price."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The price updates when you change quantities or add and remove items."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Checking out with the checkout button includes Onward protection on the order."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The opt-out link reaches checkout without Onward protection."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If you get stuck, contact your Onward representative and we'll help you through it."]}]},"headings":[{"value":"Headless Shopify","id":"headless-shopify","depth":1},{"value":"Step 1: Load the headless script","id":"step-1-load-the-headless-script","depth":2},{"value":"Step 2: Implement a StorefrontClient","id":"step-2-implement-a-storefrontclient","depth":2},{"value":"Step 3: Initialize Onward and attach it to your cart","id":"step-3-initialize-onward-and-attach-it-to-your-cart","depth":2},{"value":"Step 4: Tell Onward when the cart changes","id":"step-4-tell-onward-when-the-cart-changes","depth":2},{"value":"Step 5: Hide the Onward product in your cart","id":"step-5-hide-the-onward-product-in-your-cart","depth":2},{"value":"Testing","id":"testing","depth":2}],"frontmatter":{"seo":{"title":"Headless Shopify","description":"Add Onward Checkout+ to a headless Shopify storefront with the Shopify Storefront SDK."}},"lastModified":"2026-10-26T13:40:22.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/guides/headless_shopify","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}