Developer guide · Limited release

Only Bundles SDK

Build your own Product Page Bundle interface while Only Bundles owns hydrated Shopify product data, selection validation, pricing, and Cart Transform authorization.

01 · Availability

Support-enabled, not self-service

The Only Bundles SDK is in limited release. It is enabled by the Only Bundles support team for an approved Product Page Bundle and delivered through the installed Shopify theme app extension. Use the support option on the Only Bundles Shopify listing to request access.

02 · Prerequisites

What must already be in place

  • An installed Only Bundles app and a synchronized Product Page Bundle.
  • An Online Store 2.0 theme with the Only Bundles product-page app block placed on the bundle product template.
  • SDK access enabled by support for that bundle.
  • Your custom storefront script loaded early enough to register event listeners before the SDK becomes ready.

03 · Initialization

Listen before you render

The extension parses the synchronized schema-v3 bundle snapshot, applies the active Shopify locale, checks offer eligibility, and hydrates current products and variants from Shopify's Storefront API. Only then does it expose window.WolfpackBundles and dispatch wbp:ready.

const root = document.querySelector('[data-custom-bundle]');

window.addEventListener('wbp:ready', () => {
  const { steps, selections } = window.WolfpackBundles.state;
  root.replaceChildren();

  for (const step of steps) {
    const heading = document.createElement('h2');
    heading.textContent = step.name;
    root.append(heading);

    for (const product of step.products) {
      const button = document.createElement('button');
      button.type = 'button';
      button.textContent = `Add ${product.title}`;
      button.addEventListener('click', () => {
        const result = window.WolfpackBundles.addItem(step.id, product.variantId, 1);
        if (!result.success) console.warn(result.error);
      });
      root.append(button);
    }

    console.log('Current selection', selections[step.id] || {});
  }
});

window.addEventListener('wbp:init-failed', (event) => {
  console.error(event.detail.code, event.detail.message);
});

04 · State

A read-only snapshot

WolfpackBundles.state returns immutable configuration data and a copied selection map. Read a fresh snapshot after a mutation event; changing a returned object does not change SDK state.

isReadyTrue only after hydration succeeds.
bundleIdSynchronized bundle identifier.
bundleNameMerchant-configured name.
stepsLocalized steps with hydrated products.
selectionsstepId → variantId → quantity.
discountConfigurationConfigured pricing rules.

Hydrated products include IDs, title, image, descriptions, price and compare-at price in cents, availability, inventory quantity, normalized gram weight, options, and variants. Variants include their Shopify ID, title, prices, availability, inventory state, normalized weight, image, and selected options.

05 · Methods

Public methods

addItem(stepId, variantId, quantity)

Adds a positive integer quantity of a known, available hydrated variant. Invalid quantities, unavailable variants, unknown variants, per-product limits, and rule-breaking increases return { success: false, error } without changing state.

removeItem(stepId, variantId, quantity)

Removes a positive integer quantity from a selected variant and deletes the selection when it reaches zero.

clearStep(stepId)

Clears selections for a known step.

validateStep(stepId)

Validates quantity, amount, weight, or category rules with current hydrated variant metrics.

validateBundle()

Returns { valid, errors } for required steps. Default and free-gift steps do not block completion.

getDisplayPrice()

Returns the current subtotal, discounted total, savings, percentage, and formatted display total.

addBundleToCart()

Validates, obtains a signed Cart Transform runtime token, and submits the selected component variants to Shopify's Ajax cart.

06 · Events

Window event reference

EventDetail
wbp:ready{ bundleId, steps }
wbp:init-failed{ code, message }
wbp:item-added{ stepId, variantId, quantity }
wbp:item-removed{ stepId, variantId, quantity }
wbp:step-cleared{ stepId }
wbp:discount-tier-reached{ bundleId, tierId, tierIndex, tierCount, feedbackState }
wbp:cart-success{ bundleId }
wbp:cart-failed{ error }

07 · Pricing

Display cents, checkout authority

getDisplayPrice() uses hydrated Shopify variant prices and current Only Bundles rules. original, discounted, and savings are integer cents. The formatted string is for display. Shopify cart and checkout remain authoritative.

08 · Cart handling

Wait for the result event

addBundleToCart() does not redirect. Listen for wbp:cart-success to refresh your theme cart drawer or navigate, and for wbp:cart-failed to show a recoverable error. Never build your own bundle authorization fields or bypass the SDK's runtime-token request.

09 · Debugging

Inspect events locally

Add ?wbp_debug=true to the product-page URL to log SDK state and events in the browser console. Confirm the served storefront build with window.__BUNDLE_WIDGET_VERSION__ after a cache-bypassed reload.

10 · Errors

Initialization fails closed

Technical initialization failures dispatch wbp:init-failed with one of these stable codes:

  • INVALID_CONFIGURATION — the synchronized snapshot is missing or invalid.
  • MISSING_STOREFRONT_RUNTIME — Shopify Storefront API configuration is unavailable.
  • PRODUCT_HYDRATION_FAILED — current Shopify catalog data could not be loaded.

An ineligible offer remains silently hidden and does not expose the SDK global.

11 · Limitations

Current release boundary

  • Product Page Bundles only; Full Page Bundles are not supported.
  • Online Store 2.0 themes only; Hydrogen and other headless storefronts are not supported.
  • Load one SDK bundle per page.
  • There is no npm or public CDN distribution.
  • Bundle creation, synchronization, gifts, add-ons, and Admin configuration stay in Only Bundles.

12 · Launch checklist

Verify the real Shopify path

  1. Ask Only Bundles support to enable SDK access.
  2. Synchronize the Product Page Bundle and place its app block.
  3. Register wbp:ready and wbp:init-failed listeners before initialization.
  4. Render only hydrated products and variants from SDK state.
  5. Handle every unsuccessful mutation result without assuming state changed.
  6. Test quantity, amount, weight, and category rules on desktop and mobile.
  7. Verify price, runtime-token cart success, cart failure, and the served widget version in a cache-bypassed storefront session.