Skip to content

Tier 1 — Stencil widget integration

Generated from the canonical integration guide

This page is generated from docs/integration/stencil.md — the single source of truth shared with the public marketing site. Edit the canonical file, then run npm --prefix tools/integration-docs-derive run derive.

Package: No npm install required — delivery is a CDN IIFE via BC Script Manager. API surface reference: packages/storefront-webcomponent/README.md


Who this is for

Merchants on BigCommerce-managed Stencil themes (Cornerstone or customized variants). If you're not managing a custom build pipeline, this is the zero-friction path: the bc-subscriptions widget is injected by the Script Manager and requires no theme modification.

Stencil custom-build shops that want tighter control over widget placement should use Tier 2 (headless) instead — the same IIFE is available directly but gives you manual mount control.


Prerequisites

  • BC store with bc-subscriptions app installed
  • Merchant admin access (Scripts Manager is under Storefront → Script Manager)
  • At least one subscription plan configured in bc-subscriptions admin
  • API Worker deployed and its base URL available

Install

The bc-subscriptions admin wizard detects Stencil storefronts automatically and enables the Script Manager entry for you. Merchants complete this from the bc-subscriptions admin:

  1. Open bc-subscriptions admin → Settings → Storefront activation
  2. If the wizard detects a Stencil storefront it shows "Enable Stencil widget"
  3. Click Enable — the wizard calls POST /api/admin/stencil/enable which registers the script via the BC Scripts API and stores the UUID on the store record

To verify the script is active, check Storefront → Script Manager in the BC control panel — look for an entry named bc-subscriptions-widget.

Manual path

If the wizard is unavailable, add the script manually in Script Manager:

Field Value
Name bc-subscriptions-widget
Location Footer
Load method Async
Script type Script
Pages Storefront

Script content:

<script
  src="https://bc-subscriptions-cdn.pages.dev/v1/bc-subscriptions-widget.iife.js"
  async
></script>

CDN note: The CDN is hosted on Cloudflare Pages. Future production promotion to cdn.subscriptions.bigcommerce.com requires a one-line STENCIL_SCRIPT_SRC change in the API — no change to this guide.


Minimal working example

Once the script is active, the widget renders automatically on product detail pages (PDPs) for products that have subscription plans. No theme code changes are required.

The IIFE scans the page DOM for <bc-subscriptions-widget> elements and auto-registers the custom element. The Script Manager entry injects the tag:

<!-- injected by Script Manager (you don't write this directly) -->
<bc-subscriptions-widget
  data-store-hash="{{settings.store_hash}}"
  data-api-base-url="https://subs-api.bigcommerce-testing-7727.workers.dev"
></bc-subscriptions-widget>

The data-store-hash is interpolated by Stencil's template context. The widget calls /api/plans?bc_product_id=<id> on mount; if zero plans are returned for the current product, the widget renders nothing (existing PDP unchanged).

To test: navigate to a product page on a subscribable product — the widget should appear alongside the existing add-to-cart flow.


Configuration

The IIFE accepts configuration via data-* attributes on the <bc-subscriptions-widget> element:

Attribute Type Required Description
data-store-hash string yes BC store hash — used to scope API requests
data-api-base-url string yes Base URL of the deployed apps/api Worker
data-bc-product-id number no Pre-populate product context; if absent the widget reads window.BCData.product_attributes.id
data-initial-auth-token string no Skip magic-link flow if a session JWT is already available

Stencil templates can inject dynamic values using {{}} syntax:

<bc-subscriptions-widget
  data-store-hash="{{settings.store_hash}}"
  data-api-base-url="https://subs-api.bigcommerce-testing-7727.workers.dev"
  data-bc-product-id="{{product.id}}"
></bc-subscriptions-widget>

Common pitfalls

1. Script loads but widget doesn't appear

Cause: The product has no subscription plans configured in bc-subscriptions admin. Fix: Open bc-subscriptions admin → Plans and create at least one plan, then enable it for the product.

2. CORS errors in the browser console

Cause: The API Worker's CORS_ORIGINS binding does not include the store's storefront domain. Fix: In the API Worker's wrangler.toml (or Cloudflare dashboard), add the store domain to CORS_ORIGINS. Wildcard (*) is acceptable for dev; use explicit origins for production.

3. Widget appears but "subscribe" action fails with 401

Cause: Magic-link flow requires the visitor's email. Most commonly caused by an expired or malformed JWT in data-initial-auth-token. Fix: Either omit data-initial-auth-token (let the widget run the magic-link flow) or verify the token is freshly minted and the API Worker's JWT_SECRET matches.

4. Script Manager entry shows "Inactive" after enabling

Cause: The BC Scripts API returns a UUID but the store's storefront rendering is cached. Fix: Hard-refresh the storefront or wait ~60s for the BC edge cache to invalidate. The Script Manager entry itself will show "Active" immediately after the API call succeeds.

5. Multiple <bc-subscriptions-widget> renders on the same page

Cause: The Script Manager entry is active AND a theme template also injects the tag directly. Fix: Remove the manual tag from the theme template — the Script Manager entry is sufficient.


Advanced: Subscriber portal integration

Once a subscriber has authenticated via magic-link, they can access their subscriptions at /account/subscriptions. On Stencil storefronts this route is typically rendered by the BC account section. The subscriber portal web component can be embedded there:

{{!-- templates/pages/account/subscriptions.html --}}
{{#partial "page"}}
  <div class="account-subscriptions">
    <h1>My Subscriptions</h1>

    <bc-subscriptions-widget
      data-store-hash="{{settings.store_hash}}"
      data-api-base-url="{{settings.subs_api_base_url}}"
      data-initial-auth-token="{{customer.subscriptions_token}}"
    ></bc-subscriptions-widget>
  </div>
{{/partial}}

customer.subscriptions_token is a Stencil custom attribute — populate it server-side by exchanging the BC customer JWT for a bc-subscriptions portal token via the API:

// In your Stencil theme's custom JavaScript
async function loadPortalToken(bcCustomerId) {
  const res = await fetch(
    `${window.bcSubscriptionsApiBase}/api/portal/auth/token`,
    {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ bc_customer_id: bcCustomerId }),
    }
  );
  if (!res.ok) return null;
  const { token } = await res.json();
  return token;
}

If the token is unavailable, the widget falls back to the magic-link flow automatically.

Advanced: Disabling the widget for specific products

Products without subscription plans already render the widget as invisible (zero-plans check on mount). To explicitly suppress the widget for a product category, set a custom product metafield subscription.enabled = false. The API returns plans: [] for products where the metafield is explicitly disabled.


Next steps

  • Enable the subscriber portal — merchants access it at /account/subscriptions after completing a magic-link login
  • Review the SDK reference if you want to build custom Stencil UI around the subscription state
  • See ADR-0013 for the canonical component-shape decisions
  • Headless integration — if you want direct DOM placement control rather than Script Manager