Skip to main content

Getting Started

The SDK is loaded automatically on every storefront page — you do not install it from npm or add a <script> tag yourself. This guide shows how to initialize it and make your first request.

What the platform injects

When a page renders, SitePack injects the SDK bundle and a small block of global configuration:

<script src="/js/sitepack_sdk.js"></script>
<script>
window.SITEPACK_CLIENT_ID = '…'; // request-binding hash
window.SITEPACK_CSRF_TOKEN = '…'; // CSRF token for /api/sdk/*
window.SITEPACK_SITE_UUID = '…'; // the current site
window.SITEPACK_DOMAIN = 'https://example.com';
</script>

It also creates a shared, ready-to-use instance for core theme code:

window.coreThemeSdk = new SitePackSDK({ type: 'theme', id: 'theme-core' });
Never set the SITEPACK_* globals yourself

These are provided by the server for the current visitor and site. The SDK constructor reads them and throws if any is missing. Overwriting them will break request signing.

Creating your own instance

Create a named instance so your requests are attributed to your theme or app:

// In a theme
const sdk = new SitePackSDK({ type: 'theme', id: 'my-theme' });

// In an app
const sdk = new SitePackSDK({ type: 'app', id: 'my-app' });
OptionValuesDefaultPurpose
type'theme' | 'app''theme'Who is making the call (sent as the initiator type).
idnon-empty string'default'Your theme or app identifier, used for attribution and logging.

Multiple instances can coexist on one page — they share the same request queue, rate-limit budget, and cart-sync channel.

Your first call

Every network method returns a Promise. Always handle failures:

const sdk = new SitePackSDK({ type: 'theme', id: 'my-theme' });

try {
const cart = await sdk.ecommerce.getCart();
console.log(`Cart has ${cart.total_products} product(s).`);
} catch (error) {
// Network error, validation error, or a 429 rate-limit response
console.error('SDK call failed:', error.message);
}

Reacting to cart changes

Cart-mutating calls (addToCart, updateCartQuantity, clearCart) emit a DOM event on window, both in the current tab and — via BroadcastChannel — in every other open tab and SDK instance:

window.addEventListener('sitepack:cart:updated', (event) => {
const { cart, source } = event.detail; // source: 'local' | 'sync'
renderCartBadge(cart.total_products);
});

A minimal working example

document.addEventListener('DOMContentLoaded', async () => {
const sdk = new SitePackSDK({ type: 'theme', id: 'my-theme' });

// Keep a cart badge in sync across tabs
window.addEventListener('sitepack:cart:updated', (e) => {
document.querySelector('#cart-count').textContent = e.detail.cart.total_products;
});

// Wire up add-to-cart buttons
document.querySelectorAll('[data-add-to-cart]').forEach((btn) => {
btn.addEventListener('click', async () => {
try {
await sdk.ecommerce.addToCart(btn.dataset.addToCart, 1);
} catch (err) {
sdk.ui.notify('Could not add product to cart.', 'error');
}
});
});
});

Rate limits at a glance

There are two layers of rate limiting — see Security & Rate Limiting for the full picture:

  • Client-side — a shared token bucket (15 requests, refilling over 10 seconds). Exceeding it throws Too Many Requests (Client-side Rate Limit) before any network call is made.
  • Server-side — a per-IP limiter on /api/sdk/* (15 requests / 10 seconds). Exceeding it returns HTTP 429, which the SDK surfaces as a rejected promise.
Design for the limits

Batch UI updates, debounce search-as-you-type, and cache results you can reuse (the SDK already caches the cart and order-capability lookups). Don't poll in tight loops.

Next steps