Connect Shopify and Whop to Sable
A custom app for the store, an API key for the money, one webhook so payments become orders, and one script tag in the theme. Every step lives in the dashboard.
What you need before you start
Four things, all of which you already have or can create in a few minutes:
- Access to the Shopify admin for the store, with permission to create apps in Shopify's Dev Dashboard (dev.shopify.com).
- A Whop account with a business on it. The company id starts with
biz_and appears in the Whop dashboard URL and under Settings. - The Sable dashboard password. Sable is operated for you; there is no self-serve signup.
- A duplicate of your live theme to install on, so nothing changes for shoppers until you publish.
Nothing about your store changes until the script tag is in a published theme, and even then the checkout button falls back to Shopify's own checkout whenever Sable cannot be reached.
1. Create the Shopify custom app
Sable talks to your store through a custom app of your own, so the credentials stay yours. In the Dev Dashboard create an app for the store, then on the app version grant these access scopes:
write_orders read_orders read_products read_customers write_customers write_draft_orders unauthenticated_read_product_listings unauthenticated_read_product_inventory unauthenticated_read_checkouts unauthenticated_write_checkouts
Install the app on the store and copy the Client ID and Client secret from the app's settings page. Sable uses them to mint 24-hour Admin API tokens with the client-credentials grant and creates the Storefront API token itself on first use, which is why the unauthenticated_* scopes matter: without them the Storefront token cannot be created and carts cannot be priced.
2. Add the store in the dashboard
Open the dashboard and choose Add store. It starts from Shopify: Sable reads the shop's details with the app's credentials, so there is nothing to type twice. Nothing is saved until Create store, and everything is editable later in Settings.
| Step | What happens |
|---|---|
| Shopify | The myshopify.com address (pasting the admin URL works too) and the custom app's Client ID and Client secret, then Connect. Sable mints an Admin token, reads the shop's name, currency, timezone and primary domain, and keeps none of it yet. A legacy custom app opens Legacy custom app tokens instead and pastes its static Admin API and Storefront API tokens. If Shopify cannot be reached, Skip detection and fill the next step in by hand. |
| Details | Confirm what was read: the store name (how it is listed in the dashboard; shoppers never see it), the currency and timezone pickers prefilled with the shop's own settings, and the storefront addresses shoppers buy from, prefilled from the primary domain with its www twin. Checkout clicks are only accepted from those addresses. |
| Whop | Company id (biz_…), environment (Production or Sandbox) and an API key, then Create store. Sandbox stores talk to sandbox-api.whop.com; sandbox accounts, ids and keys live at sandbox.whop.com and are separate from production. The Whop side can also be added later in Settings. |
| Done | The store exists. Three short steps on Connections make it live, in any order: register the Whop webhook, create the checkout product and paste the theme snippet (sections 3 to 5 below). Branding the checkout in the editor and a custom checkout domain on Domains are optional and work any time. |
Secrets are encrypted at rest with a key only the platform holds. The dashboard never shows a saved secret again, only whether one is saved. If the shop's currency, timezone or domain change later, Sync from Shopify on Settings re-reads them; a store name you typed is kept.
3. Connect Whop and register the webhook
On Connections the Payment account section shows the company id, the environment and whether an API key is saved. Three buttons finish the Whop side:
- Test Whop lists products with the saved API key, so you know the key and the company id match.
- Create product creates one hidden Whop product for the store. Every checkout is a one-time plan under it; buyers never see it in a Whop storefront.
- Register webhook creates the webhook through the Whop API, pointed at the store's own endpoint (
https://sable.veyraengine.io/api/webhooks/whop/<store id>), and stores its signing secret on the store. Every delivery is verified against that secret before anything is read.
The webhook subscribes to payment.succeeded, payment.failed, payment.pending, refund.created, refund.updated, dispute.created, dispute.updated and dispute_alert.created. Without it a buyer can pay and the order never reaches the dashboard or Shopify, which is why Connections shows a warning until it is registered.
In the Whop dashboard, under Settings → Checkout, set the success redirect URL, the statement descriptor shoppers see on their card statement, and the payment domain (your checkout domain) so Apple Pay can work inside the embedded checkout.
4. Register the Shopify webhooks
Still on Connections, the Shopify section has Test Shopify Admin, which reads the shop name and currency with the saved credentials, and Register webhooks, which subscribes the app to refunds/create and orders/cancelled at https://sable.veyraengine.io/api/webhooks/shopify/<store id>. Deliveries are verified with the app's client secret. Registering is idempotent: pressing it again changes nothing.
These two topics are what carry a refund made in the Shopify admin over to Whop, and what records a cancellation made in Shopify. Payments themselves never come from Shopify; they come from the Whop webhook.
5. Install the theme snippet
The snippet is one script tag, shown on Connections with the right host filled in. It looks like this:
<script src="https://checkout.yourstore.com/s/sk_XXXXXXXXXXXXXXXXXXXXXXXX" defer></script>
On every page it records ad attribution (gclid, gbraid, wbraid, fbclid, ttclid, msclkid and the utm_* parameters) in a first-party cookie. When a shopper clicks Check out it reads the Shopify cart, hands the variant ids and quantities to Sable and sends the browser to the checkout. Prices are never sent from the browser.
- Shopify admin → Online Store → Themes → on the live theme choose Duplicate. Do the next steps on the copy.
- Edit code →
layout/theme.liquid→ paste the tag on its own line just before</head>→ Save. - Turn off dynamic checkout buttons. "Buy it now", Shop Pay and PayPal express buttons skip the cart and cannot be intercepted. In the theme editor untick Show dynamic checkout buttons on the product page; on the cart page and drawer untick any "additional checkout buttons" setting; in the code, search for
additional_checkout_buttonsand remove that block. Keep the regular Add to cart and Check out buttons: those are what the snippet hooks. - Preview the theme, test it as described below, then Publish.
6. Check it worked
- Open the preview theme with a test parameter, for example
https://yourstore.com/?gclid=test123. In DevTools → Application → Cookies, a_wc_attrcookie now exists on.yourstore.com; in the console,WhopCheckout.attribution()prints the decoded value. - Add a product to the cart and click Check out, from the cart page and from the cart drawer. In the Network tab (with "Preserve log" ticked) you should see
GET /cart.js, thenPOST …/api/handoffanswering200with a URL, then the browser navigating there. The button reads "Loading…" while this happens. - Failure drill: block the checkout host in DevTools (Network → request blocking) and click Check out again. The console logs a
[whop-checkout]warning and the shopper lands on Shopify's native checkout. That is what happens during any outage. - Back on Connections, the Theme snippet card flips from "Not detected" to "Active" the moment the first checkout click reaches Sable, and the card footer counts clicks from then on.
- Place a sandbox order end to end before publishing. It appears in Orders as Paid, syncs to Shopify as a test order, and the Events page shows the
payment.succeededdelivery that created it.
Switching it off
Two ways, both reversible. Remove the script tag from the theme, or set the store's status to Paused in Settings: a paused store refuses hand-offs, so the checkout button goes back to Shopify's own checkout on the next click. Re-enable the dynamic checkout buttons if you removed the tag for good.
Questions people ask
Do I need Shopify Plus?
No. Sable does not change Shopify's checkout; the script tag sends the cart to Sable's checkout when the button is clicked, and Shopify's own checkout stays in place as the fallback. Any plan that lets you edit the theme works.
What does the snippet send to Sable?
Variant ids and quantities from /cart.js, the discount codes applied in the cart, and the attribution cookie. Never prices: the cart is priced again by Shopify's Storefront API on the checkout.
Can I run sandbox and production at the same time?
Yes, as two stores. Environment is per store: a sandbox store uses sandbox keys and sandbox-api.whop.com, a production store uses live keys. Sandbox payments are not real and sync to Shopify as test orders.
Where are my credentials stored?
On the store's row, encrypted with the platform's secrets key. The dashboard shows whether a secret is saved, never the secret itself, and the Admin tokens minted from the client secret expire after 24 hours.
Set it up on your own store
Connect Shopify, connect Whop, add one script tag. If it is not for you, removing the tag puts Shopify's checkout back.
Read next
Serve the checkout on your own domain
One CNAME puts the checkout on checkout.yourstore.com, with a certificate issued for you. Why it has to be a subdomain, what to add at your DNS provider, and what the domain serves.
Google Ads conversions, uploaded from the server
Checkout has moved off Shopify, so Sable reports purchases to Google Ads itself: click ids captured in a first-party cookie, conversions uploaded through the Data Manager API, de-duplicated with the thank-you page tag.