Commerce Engine Checkout - Embeddable checkout SDK
Embed Commerce Engine checkout in any website.
``html`
`bash`
npm install @commercengine/js
`html`
`typescript
interface CheckoutConfig {
// === Credentials (required) ===
storeId: string; // Your Commerce Engine Store ID
apiKey: string; // Your Commerce Engine API Key
environment?: "production" | "staging"; // Default: "production"
// === Development ===
url?: string; // Direct checkout URL (for local dev)
// Overrides environment-based URL
// === Theme ===
theme?: "light" | "dark" | "system"; // Default: "system"
// === Appearance ===
appearance?: {
zIndex?: number; // Overlay z-index. Default: 99999
};
// === Authentication ===
authMode?: "managed" | "provided"; // Default: "managed"
accessToken?: string; // Initial access token (if user logged in)
refreshToken?: string; // Initial refresh token
// === Quick Buy (add item on init) ===
quickBuy?: {
productId: string; // Product ID (required)
variantId: string | null; // Variant ID (required, null for non-variant)
quantity?: number; // Default: 1
};
sessionMode?: "continue-existing" | "force-new"; // Default: "continue-existing"
autoDetectQuickBuy?: boolean; // Auto-detect from parent URL. Default: false
// === Features ===
features?: {
loyalty?: boolean; // Loyalty points redemption. Default: true
coupons?: boolean; // Coupon/promo codes. Default: true
collectInStore?: boolean; // Collect-in-store option. Default: false
freeShippingProgress?: boolean; // Free shipping progress tracker. Default: true
productRecommendations?: boolean; // Product recommendations in cart. Default: true
};
// === Callbacks ===
onReady?: () => void;
onOpen?: () => void;
onClose?: () => void;
onComplete?: (order: OrderData) => void;
onCartUpdate?: (cart: CartData) => void;
onLogin?: (data: AuthLoginData) => void;
onLogout?: (data: AuthLogoutData) => void;
onTokenRefresh?: (data: AuthRefreshData) => void;
onSessionError?: () => void;
onError?: (error: ErrorData) => void;
}
`
`typescript/thank-you?order=${order.orderNumber}
const checkout = await Commercengine.init({
storeId: "store_xxx",
apiKey: "ak_xxx",
environment: "production",
theme: "dark",
appearance: {
zIndex: 100000,
},
accessToken: userSession?.accessToken,
refreshToken: userSession?.refreshToken,
onReady: () => {
console.log("Checkout loaded");
},
onComplete: (order) => {
window.location.href = ;`
},
onCartUpdate: (cart) => {
updateCartBadge(cart.count);
},
onLogin: ({ accessToken, user, loginMethod }) => {
// User logged in via checkout - sync to your auth system
console.log("User logged in via", loginMethod, ":", user?.email || user?.phone);
saveUserSession(accessToken);
},
onLogout: () => {
// User logged out - they now have anonymous tokens
clearUserSession();
},
onSessionError: () => {
// Session corrupted - SDK cleared all tokens, user needs to re-authenticate
clearUserSession();
},
});
Open the cart drawer.
`typescript`
checkout.openCart();
Open checkout directly, bypassing cart. Use for "Buy Now" flows.
`typescript`
checkout.openCheckout();
Close the checkout overlay.
`typescript`
checkout.close();
Sync authentication state from parent site. Call when user logs in/out on your site.
`typescript
// When user logs in on your site
checkout.updateTokens(session.accessToken, session.refreshToken);
// When user logs out
checkout.updateTokens("", "");
`
Add an item to cart and open the cart drawer. This is the canonical implementation of "quick buy" functionality.
`typescript
// Add a product (non-variant)
checkout.addToCart("prod_123", null, 1);
// Add a product variant
checkout.addToCart("prod_123", "var_456", 2);
// Quantity defaults to 1
checkout.addToCart("prod_123", "var_456");
`
Parameters:
- productId (string, required) - Product IDvariantId
- (string | null, required) - Variant ID, or null for non-variant productsquantity
- (number, optional) - Quantity to add, defaults to 1
Behavior:
- Adds item to cart and automatically opens the cart drawer
- If item already in cart: adds to existing quantity
- If item not in cart: adds new item
- If no cart exists: creates cart with the item
Get current cart state.
`typescript`
const cart = checkout.getCart();
console.log(cart.count, cart.total, cart.currency);
Remove checkout iframe and cleanup event listeners.
`typescript`
checkout.destroy();
| Property | Type | Description |
|----------|------|-------------|
| ready | boolean | Whether checkout is initialized and ready |open
| | boolean | Whether checkout overlay is currently visible |
Subscribe via callbacks (in config) or the event emitter.
| Event | Callback | Data | Description |
|-------|----------|------|-------------|
| ready | onReady | - | Checkout iframe loaded |open
| | onOpen | - | Drawer opened |close
| | onClose | - | All drawers closed |complete
| | onComplete | OrderData | Order placed successfully |cart:updated
| | onCartUpdate | CartData | Cart state changed |auth:login
| | onLogin | AuthLoginData | User logged in |auth:logout
| | onLogout | AuthLogoutData | User logged out |auth:refresh
| | onTokenRefresh | AuthRefreshData | Tokens auto-refreshed |auth:session-error
| | onSessionError | - | Session corrupted, tokens cleared |error
| | onError | ErrorData | Configuration error |
`typescript
interface OrderData {
id: string; // Order ID
orderNumber: string; // Human-readable order number
}
interface CartData {
count: number; // Number of items
total: number; // Subtotal amount
currency: string; // Currency code (e.g., "USD", "INR")
}
interface AuthLoginData {
accessToken: string;
refreshToken?: string;
user?: UserInfo;
loginMethod?: LoginMethod;
}
interface AuthLogoutData {
accessToken: string; // New anonymous token
refreshToken?: string;
user?: UserInfo; // Anonymous user info
}
interface AuthRefreshData {
accessToken: string;
refreshToken?: string;
}
interface ErrorData {
message: string;
}
type LoginMethod = "whatsapp" | "phone" | "email";
interface Channel {
id: string;
name: string;
type: string;
}
interface UserInfo {
id: string;
email: string | null;
phone: string | null;
username: string;
firstName: string | null;
lastName: string | null;
storeId: string;
isLoggedIn: boolean;
isAnonymous: boolean;
customerId: string | null;
customerGroupId: string | null;
anonymousId: string;
channel: Channel;
tokenExpiry: Date;
tokenIssuedAt: Date;
}
`
`typescript
// Subscribe
checkout.on("cart:updated", (cart) => {
console.log("Cart:", cart.count, cart.total);
});
// Subscribe once
checkout.once("complete", (order) => {
console.log("Order:", order.orderNumber);
});
// Unsubscribe
const handler = (cart) => console.log(cart);
checkout.on("cart:updated", handler);
checkout.off("cart:updated", handler);
`
User will be prompted to login within checkout (WhatsApp, Phone, or Email OTP).
`typescript`
const checkout = await Commercengine.init({
storeId: "store_xxx",
apiKey: "ak_xxx",
onLogin: ({ accessToken, refreshToken }) => {
// Save tokens to your auth system
saveSession({ accessToken, refreshToken });
},
});
Pass tokens to skip login screen.
`typescript`
const checkout = await Commercengine.init({
storeId: "store_xxx",
apiKey: "ak_xxx",
accessToken: currentSession.accessToken,
refreshToken: currentSession.refreshToken,
});
When user logs in/out on your site, sync to checkout.
`typescript
// User logs in on your site
myAuth.onLogin((session) => {
checkout.updateTokens(session.accessToken, session.refreshToken);
});
// User logs out on your site
myAuth.onLogout(() => {
checkout.updateTokens("", "");
});
`
Configure checkout features as needed:
`typescript`
const checkout = await Commercengine.init({
storeId: "store_xxx",
apiKey: "ak_xxx",
features: {
loyalty: false, // Disable loyalty points redemption
coupons: false, // Disable coupon/promo codes
collectInStore: false, // Disable collect-in-store option
freeShippingProgress: false, // Disable free shipping progress tracker
productRecommendations: false, // Disable product recommendations
},
});
| Feature | Default | Description |
|---------|---------|-------------|
| loyalty | true | Loyalty points redemption at checkout |coupons
| | true | Coupon and promo code input |collectInStore
| | false | Option to collect order in-store |freeShippingProgress
| | true | Progress bar showing amount needed for free shipping |productRecommendations
| | true | "You may also like" product carousel in cart |
All types are exported:
`typescript`
import {
Commercengine,
Checkout,
type CheckoutConfig,
type CheckoutEventType,
type CheckoutFeatures,
type Environment,
type CartData,
type OrderData,
type AuthLoginData,
type AuthLogoutData,
type AuthRefreshData,
type ErrorData,
type UserInfo,
type Channel,
type LoginMethod,
} from "@commercengine/js";
For direct iframe integration without the SDK, checkout accepts these URL parameters:
| Parameter | Description | Example |
|-----------|-------------|---------|
| store_id | Store ID | store_xxx |api_key
| | API Key | ak_xxx |environment
| | SDK environment | production, staging |mode
| | Deployment mode | iframe |parent_origin
| | Parent origin for postMessage | https://brand.com |theme
| | Theme preference | light, dark |token
| | Access token | JWT string |refresh_token
| | Refresh token | JWT string |auth_mode
| | Auth management | provided, managed |product_id
| | Quick buy product | Product ID |variant_id
| | Quick buy variant | Variant ID |qty
| | Quick buy quantity | 1 |session_mode
| | Session behavior | continue-existing, force-new |loyalty
| | Loyalty feature | false to disable |coupons
| | Coupons feature | false to disable |collect_in_store
| | Collect-in-store feature | false to disable |free_shipping_progress
| | Free shipping progress | false to disable |product_recommendations
| | Product recommendations | false to disable |
- managed (default): Checkout manages token lifecycle with auto-refresh
- provided: Parent manages tokens. Checkout uses in-memory only, syncs changes via events
- continue-existing (default): Add quick-buy item to existing cart
- force-new: Delete existing cart and start fresh with only the quick-buy item
Note: When quick buy params are provided (via config or auto-detected), the cart drawer automatically opens once checkout is ready.
For ad-driven traffic, enable autoDetectQuickBuy to automatically parse quick buy params from the parent page URL:
`typescript
// Ad link: https://brand.com?product_id=prod_123&variant_id=var_456&qty=2
const checkout = await Commercengine.init({
storeId: "store_xxx",
apiKey: "ak_xxx",
autoDetectQuickBuy: true, // Reads product_id, variant_id, qty from parent URL
});
`
This allows embedded checkout to handle ad clicks natively without custom URL parsing.
URL Cleanup: When quick buy params are detected, they are automatically removed from the browser URL (using replaceState`) to prevent duplicate adds on page refresh.