@commercengine/js
v0.3.5
Published
Commerce Engine Checkout - Embeddable checkout SDK
Maintainers
Readme
@commercengine/js
Embed Commerce Engine checkout in any website.
Installation
CDN (Recommended)
<script src="https://cdn.commercengine.com/v1.js" async></script>npm
npm install @commercengine/jsQuick Start
<script src="https://cdn.commercengine.com/v1.js" async></script>
<script>
window.Commercengine.onLoad = async () => {
const checkout = await Commercengine.init({
storeId: "store_xxx",
apiKey: "ak_xxx",
environment: "production", // or "staging"
});
document.getElementById("cart-btn").onclick = () => checkout.openCart();
};
</script>Configuration
CheckoutConfig
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;
}Example: Full Configuration
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 = `/thank-you?order=${order.orderNumber}`;
},
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();
},
});Methods
openCart()
Open the cart drawer.
checkout.openCart();openCheckout()
Open checkout directly, bypassing cart. Use for "Buy Now" flows.
checkout.openCheckout();close()
Close the checkout overlay.
checkout.close();updateTokens(accessToken, refreshToken?)
Sync authentication state from parent site. Call when user logs in/out on your site.
// When user logs in on your site
checkout.updateTokens(session.accessToken, session.refreshToken);
// When user logs out
checkout.updateTokens("", "");addToCart(productId, variantId, quantity?)
Add an item to cart and open the cart drawer. This is the canonical implementation of "quick buy" functionality.
// 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, ornullfor 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
getCart()
Get current cart state.
const cart = checkout.getCart();
console.log(cart.count, cart.total, cart.currency);destroy()
Remove checkout iframe and cleanup event listeners.
checkout.destroy();Properties
| Property | Type | Description |
|----------|------|-------------|
| ready | boolean | Whether checkout is initialized and ready |
| open | boolean | Whether checkout overlay is currently visible |
Events
Subscribe via callbacks (in config) or the event emitter.
Event Types
| 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 |
Event Data Types
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;
}Event Emitter API
// 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);Authentication Flow
Scenario 1: User Not Logged In
User will be prompted to login within checkout (WhatsApp, Phone, or Email OTP).
const checkout = await Commercengine.init({
storeId: "store_xxx",
apiKey: "ak_xxx",
onLogin: ({ accessToken, refreshToken }) => {
// Save tokens to your auth system
saveSession({ accessToken, refreshToken });
},
});Scenario 2: User Already Logged In
Pass tokens to skip login screen.
const checkout = await Commercengine.init({
storeId: "store_xxx",
apiKey: "ak_xxx",
accessToken: currentSession.accessToken,
refreshToken: currentSession.refreshToken,
});Scenario 3: Sync Auth Changes
When user logs in/out on your site, sync to checkout.
// 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("", "");
});Features
Configure checkout features as needed:
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 |
TypeScript
All types are exported:
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";URL Parameters (Advanced)
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 |
Auth Modes
managed(default): Checkout manages token lifecycle with auto-refreshprovided: Parent manages tokens. Checkout uses in-memory only, syncs changes via events
Session Modes
continue-existing(default): Add quick-buy item to existing cartforce-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.
Auto-Detect Quick Buy
For ad-driven traffic, enable autoDetectQuickBuy to automatically parse quick buy params from the parent page URL:
// 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.
