JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 25
  • Score
    100M100P100Q79240F
  • License MIT

Commerce Engine Checkout - Embeddable checkout SDK

Package Exports

  • @commercengine/js
  • @commercengine/js/cdn
  • @commercengine/js/package.json

Readme

@commercengine/js

Embed Commerce Engine checkout in any website.

Installation

<script src="https://cdn.commercengine.com/v1.js" async></script>

npm

npm install @commercengine/js

Quick 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

  // === 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 ID
  • variantId (string | null, required) - Variant ID, or null for non-variant products
  • quantity (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("", "");
});

TypeScript

All types are exported:

import {
  Commercengine,
  Checkout,
  type CheckoutConfig,
  type CheckoutEventType,
  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

Auth Modes

  • managed (default): Checkout manages token lifecycle with auto-refresh
  • provided: Parent manages tokens. Checkout uses in-memory only, syncs changes via events

Session Modes

  • 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.

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.