Integrate Orderboost checkout in a React application
Install the Orderboost React packages, open hosted checkout, and connect cart, sign-in, tip, and paid-resource elements to your application.
Use the Orderboost React packages to render checkout launchers and local commerce surfaces. Orderboost hosts buyer checkout, while your application supplies product URLs, placement, cart state, and lifecycle callbacks.
You consume Orderboost’s API and browser capabilities. You do not run Orderboost’s database or payment services as part of an application integration.
Get your integration values
Orderboost supplies these values when your application is registered:
| Value | Where to use it |
|---|---|
| API base URL | SDK configuration and checkout API calls |
| App ID | Every OrderboostWidget configuration |
| Allowed browser origins | The production and preview origins that may load your app manifest |
| Merchant backend credentials | Server-side checkout-session and OAuth calls, when your flow needs them |
Never expose merchant backend credentials in browser code. If an origin or app ID is rejected, update the registered integration instead of bypassing the browser check.
Install the React packages
Add the SDK, React provider, and widget renderer to your application:
npm install @orderboost/react @orderboost/sdk @orderboost/widgetpnpm add @orderboost/react @orderboost/sdk @orderboost/widgetyarn add @orderboost/react @orderboost/sdk @orderboost/widgetbun add @orderboost/react @orderboost/sdk @orderboost/widgetOrderboostWidget includes its compiled styles. Your application does not need a separate widget stylesheet.
Choose the checkout element
Choose one intent for each element:
| Buyer action | initialScreen |
Your application owns |
|---|---|---|
| Buy one product | buy-now |
The canonical product URL and launch placement |
| Review a cart | cart |
Cart lines, quantities, and checkout continuation |
| Sign in | sign-in |
The backend OAuth exchange and application session |
| Send a contribution | send-tip |
The reason for the tip and server-created amount |
| Unlock a paid resource | payment-gate |
The paid endpoint and payment-aware HTTP client |
Orderboost derives the launcher label from initialScreen. Use the button and theme configuration for supported presentation changes.
Open hosted checkout from a product URL
The public buyer-checkout endpoint is the shortest custom Buy Now integration. Open the popup during the click before waiting for the network response:
import { preopenOrderboostPopup } from "@orderboost/widget";
export async function openOrderboostCheckout(productUrl: string) {
const popup = preopenOrderboostPopup("buy-now", "Your order · Orderboost checkout");
if (!popup) throw new Error("Pop-ups are blocked.");
const response = await fetch("https://api.orderboost.example/api/v1/buyer-checkouts", {
body: JSON.stringify({ productUrl, quantity: 1 }),
credentials: "omit",
headers: { "content-type": "application/json" },
method: "POST",
referrerPolicy: "no-referrer",
});
if (!response.ok) {
popup.close();
throw new Error("Checkout preparation failed.");
}
const result = (await response.json()) as { checkoutUrl: string };
popup.location.replace(result.checkoutUrl);
}
Send the canonical product URL, selected option labels, and quantity. Do not send a browser-calculated price as authority. Orderboost resolves the merchant and current variant before creating checkout.
For a multi-item cart, send items instead of productUrl:
const body = {
items: cart.lines.map((line) => ({
productUrl: line.productUrl,
quantity: line.quantity,
selected: line.selected,
})),
};
Render a server-created checkout session
Use OrderboostWidget when your backend already created a checkout and returned a short-lived browser session. Pass the checkout presentation and session to the browser:
import type { OrderboostCheckoutConfig, OrderboostCommerceSessionConfig } from "@orderboost/sdk";
import { OrderboostWidget } from "@orderboost/widget";
type Props = {
checkout: OrderboostCheckoutConfig;
session: OrderboostCommerceSessionConfig;
};
export function HostedBuyNow({ checkout, session }: Props) {
return (
<OrderboostWidget
config={{
apiBaseUrl: session.apiBaseUrl,
appId: "your_app_id",
checkout,
commerceSession: session,
displayMode: "popup",
initialScreen: "buy-now",
}}
onCheckoutComplete={(result) => result.orderId && showOrder(result.orderId)}
/>
);
}
The session contains apiBaseUrl, checkoutId, clientToken, and optionally checkoutUrl. Treat clientToken as a short-lived browser capability. Create it on your backend and send it only to the browser that owns checkout.
Use displayMode: "page" with session.checkoutUrl to navigate the current tab. While a named popup remains open, another press focuses that popup instead of creating a duplicate.
Publish a reusable Buy Now link
Use createBuyNowLink for an email, message, anchor, social post, or QR code:
import { createBuyNowLink } from "@orderboost/sdk";
const href = createBuyNowLink("https://merchant.example/products/arc-field-pack?Color=Graphite", {
apiBaseUrl: "https://api.orderboost.example",
quantity: 1,
});
export function SharedBuyNow() {
return <a href={href}>Buy Now</a>;
}
This capability-free link contains product intent, not checkout access. Orderboost resolves the current product and creates a fresh checkout when the buyer follows it.
The checkoutUrl returned by a buyer-checkout request is reusable too, but it is an unlisted bearer
link. Share it only when everyone who receives it should be allowed to instantiate the configured
checkout. Each redemption gets isolated buyer and payment state; the resulting checkout session
expires independently while the reusable link remains active until revoked.
Connect a host-owned cart
Keep cart state in your application. Render the current lines in Orderboost, then create hosted checkout when the buyer continues:
import { OrderboostWidget } from "@orderboost/widget";
export function OrderboostCart({ cart }: { cart: StoreCart }) {
return (
<OrderboostWidget
config={{
apiBaseUrl: "https://api.orderboost.example",
appId: "your_app_id",
checkout: mapCartToCheckout(cart),
displayMode: "bottom-right",
initialScreen: "cart",
}}
onCartQuantityChange={(item, quantity) => cart.setQuantity(item.id, quantity)}
onCheckoutContinue={() => openHostedCheckout(cart.lines)}
/>
);
}
mapCartToCheckout maps your cart into presentation data. openHostedCheckout sends canonical product URLs and quantities to /api/v1/buyer-checkouts. The newly returned Orderboost quote is authoritative.
Exchange Orderboost sign-in on your backend
Sign In opens the Orderboost account popup. Send its authorization result to your backend immediately:
import type { OrderboostAuthConfig } from "@orderboost/sdk";
import { OrderboostWidget } from "@orderboost/widget";
import { useState } from "react";
export function OrderboostSignIn({ auth }: { auth: OrderboostAuthConfig }) {
const [signedIn, setSignedIn] = useState(false);
return (
<OrderboostWidget
config={{
apiBaseUrl: "https://api.orderboost.example",
appId: "your_app_id",
auth,
displayMode: "modal",
initialScreen: "sign-in",
}}
onAuthComplete={async (result) => {
await exchangeOrderboostAuth(result);
setSignedIn(true);
}}
signedIn={signedIn}
/>
);
}
Your same-origin backend exchanges the authorization result and creates the application session. Do not persist the PKCE verifier or resulting tokens in browser storage.
Render a hosted tip
Tip uses the same server-created checkout session as Buy Now. Omit shipping collection when the contribution has no physical fulfillment:
<OrderboostWidget
config={{
apiBaseUrl: session.apiBaseUrl,
appId: "your_app_id",
checkout: {
collectBillingAddress: false,
collectShippingAddress: false,
kind: "tip",
merchantName: "Northline Supply",
tipPreset: { amount: "5.00", currency: "USD" },
title: "Support the field guide",
},
commerceSession: session,
displayMode: "popup",
initialScreen: "send-tip",
}}
/>
The amount in browser configuration is presentation data. Your backend-created checkout remains authoritative.
Connect Page Guard to a paid endpoint
Page Guard renders the locked, pending, error, and unlocked states. Your callback makes the Machine Payments Protocol (MPP) or x402 request:
<OrderboostWidget
config={{
apiBaseUrl: "https://api.orderboost.example",
appId: "your_app_id",
displayMode: "page",
initialScreen: "payment-gate",
paymentGate: {
amount: "0.05",
asset: "USDC",
protocol: "x402",
resource: "https://merchant.example/field-report",
},
}}
onGatePayment={async ({ payment }) => {
const response = await paidFetch(payment.resource);
if (!response.ok) {
return { message: `Payment failed (${response.status}).`, unlocked: false };
}
await verifySettlementEvidence(response);
return { message: "Payment verified.", unlocked: true };
}}
/>
paidFetch and verifySettlementEvidence are functions that your application supplies. Page Guard does not include a wallet, signer, facilitator, or paid endpoint.
Orderboost’s hosted-checkout Tempo MPP endpoint is a separate server-side checkout flow. Do not point Page Guard at it unless your application implements that checkout contract.
Validate the integration
Test these conditions before launch:
- Your production and preview origins resolve the expected App ID
- Popup checkout opens from a direct buyer action
- Product and cart requests use canonical merchant URLs
- Browser code contains no merchant credentials or payment secrets
- Success handling requires a persisted
orderId - Cancel, popup-close, and network-error paths leave your application recoverable
If Orderboost returns payment_adapter_unavailable, the checkout environment cannot accept payment. Contact the Orderboost integration owner instead of changing browser configuration.
Read Understand Orderboost button flows for the lifecycle and security boundaries behind each element.