npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@commercengine/js

v0.3.5

Published

Commerce Engine Checkout - Embeddable checkout SDK

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/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

  // === 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 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("", "");
});

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