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¶
Automatic path (recommended)¶
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:
- Open bc-subscriptions admin → Settings → Storefront activation
- If the wizard detects a Stencil storefront it shows "Enable Stencil widget"
- Click Enable — the wizard calls
POST /api/admin/stencil/enablewhich 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.comrequires a one-lineSTENCIL_SCRIPT_SRCchange 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/subscriptionsafter 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