npm.io
1.3.6 • Published 2d ago

shopmate-sdk

Licence
MIT
Version
1.3.6
Deps
0
Size
173 kB
Vulns
0
Weekly
437

ShopMate SDK

Lightweight browser SDK for storefront carts and ShopMate checkout.

Use it to:

  • add products to a local browser cart from storefront controls;
  • retain cart state in localStorage;
  • open ShopMate checkout in a secure cross-origin iframe;
  • receive minimal user-facing notifications plus lifecycle events;
  • integrate through npm ESM imports in browser apps or through HTML attributes;
  • receive verified checkout lifecycle and order-success events.

The SDK is browser-only at runtime. It can be installed from npm and imported into React, Vite, and other client-side browser bundles, but it must not be executed in Node.js or during server-side rendering because it uses native browser APIs (window, document, URL, URLSearchParams, CustomEvent, localStorage, and iframe).


Installation

npm install shopmate-sdk

Quick start

JavaScript, TypeScript, or React client application
import ShopMate from 'shopmate-sdk';

const shopmate = new ShopMate({
  orgId: 2,
  cartPosition: 'right-bottom',
});

shopmate.extract();

new ShopMate(...) creates an instance only. Call extract() after the storefront markup has been rendered.

For React, initialize it from a client-only effect so the SDK runs after the browser has mounted the page:

import { useEffect } from 'react';
import ShopMate from 'shopmate-sdk';

export function Storefront() {
  useEffect(() => {
    const shopmate = new ShopMate({
      orgId: 2,
      cartPosition: 'right-bottom',
    });

    shopmate.extract();
  }, []);

  return <button data-shopmate-product-id="101">Add to cart</button>;
}
Explicit initialization helper

Use initShopMate() when you want the SDK to register itself as window.ShopMateInstance and automatically scan the page when the body is ready.

import { initShopMate } from 'shopmate-sdk';

const shopmate = initShopMate({
  orgId: 2,
  cartPosition: 'right-bottom',
  onOrderSuccess: ({ payload }) => {
    console.log('Order completed:', payload);
  },
});
Plain script tag
<script
  src="https://cdn.jsdelivr.net/npm/shopmate-sdk@latest/shopmate-sdk.min.js"
  data-org-id="2"
  data-cart-position="right-bottom"
></script>

The browser bundle exposes:

window.ShopMate;
window.initShopMate;
window.ShopMateInstance;

When the script is loaded through a normal <script src="..."> tag with data-org-id, it initializes after the page load event and scans the document automatically.


Smallest storefront integration

<button data-shopmate-product-id="101" data-shopmate-quantity="1">
  Add to cart
</button>

<button data-shopmate-checkout="true">
  Checkout
</button>

<script
  src="https://cdn.jsdelivr.net/npm/shopmate-sdk@latest/shopmate-sdk.min.js"
  data-org-id="2"
  data-cart-position="right-bottom"
></script>

The floating cart button uses a recolorable SVG cart icon; the checkout close button uses .


Supported storefront markup

Add a product
<button data-shopmate-product-id="101" data-shopmate-quantity="1">
  Add to cart
</button>

Supported attributes:

  • data-shopmate-product-id — positive numeric product ID; required.
  • data-shopmate-quantity — positive integer quantity; optional, defaults to 1.
  • data-shopmate-coupon-id — optional coupon applied before adding the product.

Calling the same product trigger again increments its existing cart quantity. The SDK caps a product quantity at 999.

Apply or clear a coupon
<button data-shopmate-coupon-id="WELCOME10">
  Apply coupon
</button>

Coupon-only triggers must not also have data-shopmate-product-id.

Open checkout
<button data-shopmate-checkout="true">
  Checkout
</button>
URL-based checkout trigger
<a href="https://shopmate.hoshonto.com/api/v1/pub/checkout?pid=101,102">
  Checkout now
</a>

For URL triggers, ShopMate supports:

  • pid=101,102 — adds each listed product with quantity 1;
  • couponId=WELCOME10 — applies a coupon;
  • c=<JSON cart> — imports a cart payload such as {"i":[{"i":101,"q":2}],"c":"WELCOME10"}.

For c, use URL encoding when constructing the link manually. The raw checkout cart uses backend field names: i for items and c for the coupon code. Prefer URLSearchParams rather than string concatenation.


Configuration

const shopmate = new ShopMate({
  orgId: 2,
  baseUrl: 'https://shopmate.hoshonto.com',
  checkoutPath: '/api/v1/pub/checkout',
  cartPosition: 'right-bottom',
  enableFloatingCart: true,
  showNotifications: true,
  checkoutLoadTimeoutMs: 5_000,
});
Option Type Default Description
orgId number Required Positive integer organization ID.
baseUrl string https://shopmate.hoshonto.com HTTP/HTTPS origin hosting ShopMate APIs and checkout.
checkoutPath string /api/v1/pub/checkout Checkout iframe route.
cartPosition ShopMateCartPosition right-bottom Floating cart location.
storageKey string | (orgId) => string shopmate:cart:${orgId} Cart storage-key override.
enableFloatingCart boolean true Renders the floating cart control.
autoExtract boolean true Used by initShopMate() and browser auto-init to scan the page when ready.
selectors object See below Custom product, checkout, and URL checkout selectors.
labels object See below Accessible labels and checkout copy.
theme object See below UI colors, radius, and stacking level.
showNotifications boolean true Shows minimal SDK toast notifications. Events and callbacks still run when false.
notificationDurationMs number 4500 Default visible duration for toast notifications.
checkoutLoadTimeoutMs number 5000 Time to wait for a validated checkout-ready message before redirecting to checkout in the current tab.
onNotify (notification) => void Receives every SDK status notification.
onWarn (warning) => void Receives recoverable SDK warnings.
onOrderSuccess (event) => void Receives verified order-success events from checkout.
Cart positions
left-top      top      right-top
left-center   center   right-center
left-bottom   bottom   right-bottom
selectors
selectors: {
  product: '[data-shopmate-product-id]',
  checkout: '[data-shopmate-checkout="true"]',
  checkoutLink: 'https://shopmate.hoshonto.com/api/v1/pub/checkout?',
}
labels
labels: {
  floatingCartAriaLabel: 'Open ShopMate checkout',
  closeCheckout: 'Close checkout',
  openingCheckout: 'Opening checkout...',
}
theme
theme: {
  brandColor: '#2563eb',
  brandAccentColor: '#0f766e',
  brandTextColor: '#ffffff',
  primaryColor: '#2563eb',
  accentColor: '#0f766e',
  successColor: '#0f766e',
  warningColor: '#c2410c',
  dangerColor: '#ef4444',
  textColor: '#0f172a',
  surfaceColor: '#ffffff',
  overlayColor: 'rgba(15,23,42,.62)',
  cartColor: 'linear-gradient(135deg,#2563eb,#0f766e)',
  cartTextColor: '#ffffff',
  cartIconColor: '#ffffff',
  cartBadgeColor: '#ef4444',
  notificationAccentColor: '#2563eb',
  notificationSurfaceColor: '#ffffff',
  notificationTextColor: '#0f172a',
  notificationActionColor: '#2563eb',
  borderRadius: '22px',
  zIndex: 2147483647,
}

brandColor, brandAccentColor, and brandTextColor feed cart and notification defaults. Use the cart or notification-specific fields only when those UI pieces need different colors.


Public API

extract(rootElement?: HTMLElement): void

Scans the supplied element, or document.body, and attaches click handlers to supported storefront triggers. Calling it more than once is safe; the SDK does not attach duplicate handlers to previously processed elements.

shopmate.extract();
shopmate.extract(document.querySelector('#product-list'));
addToCart(itemId: number, quantity?: number, element?: HTMLElement): boolean

Adds quantity to an existing product or creates a cart item. Returns false for invalid values, unavailable SDK state, or the maximum distinct-item limit.

shopmate.addToCart(101, 2);

The cart allows up to 100 distinct products and up to 999 units per product.

setCartItemQuantity(itemId: number, quantity: number): boolean

Sets an absolute quantity for an item. Use 0 to remove it.

shopmate.setCartItemQuantity(101, 3);
shopmate.setCartItemQuantity(101, 0);
setCoupon(couponId?: string | null): void

Applies a coupon. Pass null, undefined, or an empty string to clear it.

shopmate.setCoupon('WELCOME10');
shopmate.setCoupon(null);

The SDK exposes coupons as couponId in getCart(), but checkout serializes the coupon into the backend raw-cart field c.

getCart(): ShopMateCart

Returns an isolated copy of the cart.

const cart = shopmate.getCart();
// { i: [{ i: 101, q: 2 }], couponId: 'WELCOME10' }
getCartStorageKey(): string

Returns the active cart localStorage key.

shopmate.getCartStorageKey();
// shopmate:cart:2
getCheckoutQuery(optionsOrNextUrl?, prevUrl?): ShopMateCheckoutQuery

Returns the current checkout query contract:

shopmate.getCheckoutQuery({
  nextUrl: 'https://storefront.example/cart',
  prevUrl: 'https://storefront.example/products',
});

// {
  orgId: '2',
  c: '{"i":[{"i":101,"q":2}],"c":"WELCOME10"}',
  next: 'https://storefront.example/cart',
  prev: 'https://storefront.example/products',
// }

next is used after successful checkout. prev is used when the customer cancels checkout. When omitted, next defaults to window.location.href, and prev defaults to document.referrer or window.location.href.

For backward compatibility, getCheckoutQuery(nextUrl, prevUrl) is also supported.

buildCheckoutUrl(optionsOrNextUrl?, prevUrl?): string

Builds the checkout iframe URL. Returns an empty string and reports a notification when URL construction fails or exceeds the 8,000-character safety limit.

For backward compatibility, buildCheckoutUrl(nextUrl, prevUrl) is also supported.

openCheckout(buttonElement?: HTMLElement, options?: { nextUrl?: string; prevUrl?: string }): boolean

Builds and opens the checkout iframe. It shows a processing state on the supplied button and returns false when checkout cannot be opened.

shopmate.openCheckout(document.querySelector('#checkout-button'), {
  nextUrl: 'https://storefront.example/cart',
  prevUrl: 'https://storefront.example/products',
});

The SDK adds only the full-viewport checkout container and close button. Authentication, payment methods, customer account state, and checkout content are handled inside the iframe.

closeCheckout(showNotification = true): void

Closes the iframe, clears the iframe src, restores page scrolling, and optionally shows a close notification.

createCheckoutIframe(): HTMLIFrameElement

Creates the checkout iframe with the required sandbox and payment permissions. This is an advanced API; normal integrations should call openCheckout().

runWhenBodyReady(action: () => void): void

Runs a DOM operation immediately when document.body exists, otherwise after DOMContentLoaded.

initShopMate(config): ShopMate

Creates an instance, assigns it to window.ShopMateInstance, and runs extract() when autoExtract is not false.


Notifications and error handling

ShopMate keeps visible notifications minimal and professional. The SDK still emits every lifecycle notification through callbacks and browser events, but built-in toast UI is reserved for user-impacting states.

Built-in toast UI is shown for:

  • invalid configuration;
  • cart and storage warnings;
  • cart addition and coupon updates;
  • checkout failures;
  • order success.

Checkout opening, opened, ready, and closed states are still emitted to onNotify and shopmate:notification; they are not shown as redundant toasts.

const shopmate = initShopMate({
  orgId: 2,
  onNotify(notification) {
    console.log(notification.level, notification.code, notification.message);
  },
  onWarn(warning) {
    console.warn(warning.code, warning.message, warning.cause);
  },
});

To suppress built-in toast UI but retain callbacks and browser events:

const shopmate = initShopMate({
  orgId: 2,
  showNotifications: false,
});

Callback exceptions are isolated. An exception thrown inside onNotify, onWarn, or onOrderSuccess is logged and does not interrupt core SDK behavior.


Browser events

The SDK dispatches native CustomEvent events on window.

shopmate:notification

Dispatched for every SDK notification. event.detail is a ShopMateNotification.

window.addEventListener('shopmate:notification', (event) => {
  console.log(event.detail);
});
shopmate:order-success

Dispatched after a verified checkout order-success message. event.detail is:

{
  orgId: 2,
  cart: { i: [{ i: 101, q: 2 }] },
  payload: { /* checkout-provided result */ },
}
window.addEventListener('shopmate:order-success', (event) => {
  console.log('Order success:', event.detail);
});
shopmate:close

Dispatch this event from host code to close the checkout.

window.dispatchEvent(
  new CustomEvent('shopmate:close', {
    detail: { orgId: 2 },
  }),
);

If no orgId is supplied, each active ShopMate instance can react to the close event. Provide orgId when more than one instance may exist on a page.


Cross-origin checkout contract

Checkout is intentionally cross-origin. The parent storefront sends cart context in the iframe URL and does not inspect iframe DOM, storage, cookies, or authentication state.

The checkout application is responsible for its own authentication, including any cookies or redirect flow it requires.

The SDK accepts postMessage events only when both conditions are true:

  1. event.origin matches the configured baseUrl origin; and
  2. event.source is the currently active checkout iframe window.

Supported checkout messages:

Message type Effect
closeCheckout or shopmate:close Closes checkout.
shopmate:checkout-loading or shopmate:loading Emits a processing notification.
shopmate:checkout-ready or shopmate:ready Marks checkout ready and clears the load timeout.
shopmate:checkout-error or shopmate:error Shows an error notification and retry action.
shopmate:order-success, shopmate:orderSuccess, or orderSuccess Clears the cart, closes checkout, and emits order success.
Checkout-frame example

The checkout application must send messages to the exact, allowlisted storefront origin. Do not derive this origin from untrusted request values.

const storefrontOrigin = 'https://storefront.example';

function notifyParent(type: string, payload?: unknown) {
  if (window.parent !== window) {
    window.parent.postMessage({ type, payload }, storefrontOrigin);
  }
}

notifyParent('shopmate:checkout-loading');

try {
  await initializeCheckout();
  notifyParent('shopmate:checkout-ready');
} catch (error) {
  notifyParent('shopmate:checkout-error', {
    code: 'CHECKOUT_INITIALIZATION_FAILED',
  });
}

After order creation:

notifyParent('shopmate:order-success', {
  orderId: createdOrder.id,
});

Security requirements

The SDK cart payload is convenience state, not a trusted order record. The checkout backend must validate all client-provided values.

The backend must:

  • verify that every product exists, is active, and belongs to orgId;
  • recalculate prices, discounts, taxes, delivery charges, inventory, and totals server-side;
  • validate coupon eligibility and usage server-side;
  • validate and constrain quantities server-side;
  • validate next against a strict redirect allowlist before redirecting;
  • treat c, pid, couponId, and all URL query values as untrusted input;
  • use short-lived, server-side checkout sessions when cart URLs can become large or sensitive.

Do not expose credentials, privileged API keys, or trusted pricing data in cart URLs.


Script-tag attributes

The browser bundle supports these attributes:

<script
  src="https://cdn.jsdelivr.net/npm/shopmate-sdk@latest/shopmate-sdk.min.js"
  data-org-id="2"
  data-base-url="https://shopmate.hoshonto.com"
  data-auth-token="optional-token"
  data-persist-auth-token="true"
  data-brand-color="#2563eb"
  data-brand-accent-color="#0f766e"
  data-cart-badge-color="#ef4444"
  data-notification-surface-color="#ffffff"
  data-notification-text-color="#0f172a"
  data-cart-position="right-bottom"
  data-auto-extract="true"
  data-floating-cart="true"
  data-show-notifications="true"
  data-checkout-load-timeout-ms="5000"
></script>
Attribute Description
data-org-id Required positive organization ID.
data-base-url Optional ShopMate base URL.
data-auth-token Optional token used only by the SDK request helper.
data-persist-auth-token Set to false to avoid token persistence.
data-brand-color Primary brand color for SDK UI.
data-brand-accent-color Secondary brand color for gradients and success states.
data-brand-text-color Text/icon color over brand surfaces.
data-cart-color Floating cart background. CSS gradients are allowed.
data-cart-text-color Floating cart text color and fallback icon color.
data-cart-icon-color Floating cart SVG icon color.
data-cart-badge-color Floating cart badge color.
data-notification-accent-color Default toast accent color.
data-notification-surface-color Toast background color.
data-notification-text-color Toast text color.
data-notification-action-color Toast action button color.
data-cart-position Floating cart position.
data-auto-extract Set to false to skip automatic DOM extraction.
data-floating-cart Set to false to hide the floating cart.
data-show-notifications Set to false to disable built-in toast UI.
data-checkout-load-timeout-ms Positive millisecond timeout before redirecting to checkout in the current tab. Defaults to 5000.

Build outputs

npm run build generates the package artifacts:

  • shopmate-sdk.js — readable browser global bundle;
  • shopmate-sdk.min.js — minified browser global bundle;
  • dist/index.mjs — ESM bundle;
  • dist/index.min.mjs — minified ESM bundle;
  • dist/index.d.ts — TypeScript declarations.

NPM scripts

npm run build      Build all artifacts
npm run watch      Build in watch mode
npm run typecheck  Run TypeScript type checking only
npm test           Build and verify browser bundle behavior

Package exports

shopmate-sdk          Default ShopMate class export
shopmate-sdk/min      Minified module build
shopmate-sdk/browser  Browser bundle path

Local demo

Build the package, then open examples/storefront-demo.html in a browser.


Publishing to npm

Prerequisites
  • npm account with publish permission for shopmate-sdk;
  • authenticated npm session:
npm login
Release process
  1. Update version:

    npm version patch
    npm version minor
    npm version major
  2. Validate and build:

    npm run typecheck
    npm test
    npm run build
  3. Inspect the package contents:

    npm pack --dry-run
  4. Publish:

    npm publish
  5. Verify:

    npm view shopmate-sdk

The CDN browser bundle is available through jsDelivr after publication:

https://cdn.jsdelivr.net/npm/shopmate-sdk@latest/shopmate-sdk.min.js
https://cdn.jsdelivr.net/npm/shopmate-sdk@<version>/shopmate-sdk.min.js
Publishing checklist
  • Version updated and committed.
  • npm run typecheck succeeds.
  • npm test succeeds.
  • npm run build succeeds.
  • README and changelog are updated.
  • npm pack --dry-run includes only intended files.
  • npm whoami confirms the correct npm account.
  • Package published with npm publish.
  • CDN path checked after publication.

Keywords