BigCommerce Cutover Runbook
Step-by-step plan for putting this site on josemadridsalsa.com in front of BigCommerce, with the soft launch, domain move, webhook updates and rollback
BigCommerce Cutover Runbook
This site runs headless on BigCommerce. BigCommerce stays the system of record for the catalog, prices, stock, checkout, payments, tax, shipping, order emails, retail customers and gift certificates, and staff keep using the BigCommerce admin they already know. This site is the storefront in front of it: product pages, heat ratings, recipes, fundraising, wholesale and the blog. When a shopper checks out, their cart is rebuilt in BigCommerce and they finish on BigCommerce's hosted checkout.
There are two stores:
| Store | Domain today | Store hash | Role after cutover |
|---|---|---|---|
| Main | josemadridsalsa.com | dsk4gx4 | Checkout, orders, customers and gift certificates for retail |
| Fundraising | josemadridsalsafundraising.com | c034x363rd | Unchanged |
Fundraiser sales, including a retail cart that a student's referral link turns into a fundraiser sale, keep this site's own checkout. BigCommerce has no concept of campaign pricing or credit.
Order matters
Do the phases in order. Phase 1 changes nothing a shopper can see. Phase 2 can be undone in minutes. Phase 3 moves domains; it is reversible, but not instantly.
Phase 0 — Before you start
- Prices. Once the switch is on, BigCommerce's price is the price. Jars are $8 in BigCommerce (set September 2026, up from $7) and packs are unchanged. The site's own database should match, so josemadrid.net shows the same $8 before the switch too: Admin → Products, or ask a developer to update it.
- Anything sold only on this site shows as out of stock once the switch is on, because BigCommerce's checkout cannot sell it. As of September 2026 every product on the site is a salsa that BigCommerce also sells, so nothing is affected.
- API credentials stay as they are until the site is live. Rotate them in Phase 4.
Phase 1 — Ship the code with the switch off
- Merge the headless work to
main. WithNEXT_PUBLIC_COMMERCE_BACKENDunset the site behaves exactly as before, so this is safe at any time. - In Vercel → josemadridsalsa → Settings → Environment Variables (Production) add:
BIGCOMMERCE_STORE_HASH,BIGCOMMERCE_ACCESS_TOKEN,BIGCOMMERCE_CLIENT_ID,BIGCOMMERCE_CLIENT_SECRETfor the main store- the four
BIGCOMMERCE_FUNDRAISING_*values for the fundraising store BIGCOMMERCE_WEBHOOK_SECRET: any long random string (for example the output ofopenssl rand -hex 32)
Phase 2 — Soft launch on josemadrid.net
BigCommerce still serves josemadridsalsa.com during this phase, so its checkout keeps running on that domain. josemadrid.net starts sending carts there.
-
Set
NEXT_PUBLIC_COMMERCE_BACKEND=bigcommercein Vercel (Production) and redeploy. The setting is read at build time. -
Register the webhooks, so BigCommerce product edits reach the site within seconds and every BigCommerce order is copied into this site's order table (for dashboards, margin reports and "verified buyer" reviews). Run this from
apps/storefront, with the production values of the variables above in your shell:npm run bigcommerce:webhooks -- https://www.josemadrid.net -
Optional: copy past BigCommerce orders into this site too, so reports cover them. Pick a start date; re-running is safe:
npm run bigcommerce:orders -- 2026-01-01An hourly job (
/api/cron/bigcommerce-orders) also re-copies anything changed in the last three days, in case a webhook was missed. -
QuickBooks: copied orders are not sent to QuickBooks unless
BIGCOMMERCE_ORDERS_TO_QUICKBOOKS=true. Check with whoever keeps the books how online sales reach QuickBooks today. If the Stripe and PayPal deposits already book them, leave it off. -
Check it:
- A salsa page shows BigCommerce's price.
- Change a price in BigCommerce, reload the page a few seconds later, and see the new price.
- Add a jar and a Choose-6 to the cart and check out. You should land on BigCommerce's checkout showing the same items, with Jar 1–6 filled in.
- Place one real low-value order, confirm it appears in BigCommerce → Orders, then refund it there.
- Open a fundraiser referral link, add a jar, and check out. That cart must stay on this site's checkout.
- Within a minute of the test order, it appears in the website admin → Orders as
BC-<number>, marked read-only.
Rollback: remove NEXT_PUBLIC_COMMERCE_BACKEND and redeploy.
Fundraising store orders
Orders from the fundraising store (josemadridsalsafundraising.com) are copied into this site's order
table as well, as read-only BCF-<number> orders (importSource = bigcommerce-fundraising, sales
channel Fundraiser). They follow the same rules as retail copies: admin changes are refused, they
stay out of QuickBooks unless BIGCOMMERCE_ORDERS_TO_QUICKBOOKS=true, and nothing emails the buyer.
Each order is credited to the group the buyer picked at checkout. The group answer is matched by
name, ignoring case, extra spaces and curly apostrophes, so "Harper Creek band Boosters" and
"Harper Creek Band Boosters" are one campaign while "Theta Phi Alpha" and "Theta Phi Alpha 2023"
stay two. The first order for a new group creates a fundraiser for it (commission 50%, contact
fundraising@josemadridsalsa.com, dates stretched to cover its orders). These fundraisers are
records only: they are inactive, marked Ended, and have both coordinator emails marked as already
sent, so the lifecycle job never announces, closes or summarises them and they never appear as
stores. The salesperson answer is kept on the order as free text (sellerName). Each copy records
the group's 50% of the merchandise subtotal and is marked credited, and the campaign's orders,
revenue and commission are recomputed from its copies.
-
Register the fundraising store's webhooks (the same route and secret, marked with
?store=fundraising). Run fromapps/storefrontwith production'sBIGCOMMERCE_FUNDRAISING_*andBIGCOMMERCE_WEBHOOK_SECRETin your shell:npm run bigcommerce:webhooks -- https://www.josemadrid.net --store fundraising -
Copy the history (every order since the store opened; re-running is safe):
npm run bigcommerce:orders -- 2020-01-01 --store fundraisingIt prints how many orders were created, updated, skipped (not paid yet) and failed, how many fundraisers were created, and how many orders named no group.
The hourly /api/cron/bigcommerce-orders job sweeps the fundraising store too whenever its
credentials are set, whether or not the retail storefront has switched over. After the domain moves
(Phase 3), re-run the registration command with the new origin.
Purchase tracking
Purchases now happen on BigCommerce's checkout, so they are recorded by the trackers connected inside BigCommerce, not by this site. Neither site records purchases today. The website already reports "checkout started" to all of these at the hand-off. In BigCommerce → Settings → Data solutions, connect them using the same accounts the website uses:
- Google Analytics 4: the GA4 property behind the website's Google Tag Manager container
GTM-NTWG6BQW. Then in Google Analytics → Admin → Data streams → Configure tag settings → Configure your domains, listjosemadrid.net,josemadridsalsa.comandshop.josemadridsalsa.com, so a visit and its purchase count as one journey. - Meta pixel:
2546527762445636. - TikTok pixel:
D8OEDO3C77U56UIVDE3G, through BigCommerce's TikTok channel or app.
Fundraising app
The fundraiser pages (/fundraising, /fundraisers/..., /fundraise/..., /f/..., the
fundraiser portal, the arena) and the fundraising site are their own app, apps/fundraising, on
their own Vercel project and domain. The main site redirects its old fundraiser paths there. Do
this before Phase 3, or at any time after it; it does not depend on the BigCommerce switch.
Merge, then move the domain
Until the fundraising domain points at the new project, it still reaches the main site, which no longer serves those pages after the merge. Have step 4 ready before merging, and do it right after the merge deploys.
-
Create the project. Vercel → Add New → Project → import
jordolang/josemadridsalsaagain, with Root Directoryapps/fundraising(leave "Include files outside the root directory" on). The framework, build command and ignored-build step come fromapps/fundraising/vercel.json. -
Environment variables (Production). Copy all of the main project's Production variables into the new project (Vercel's "Import .env" takes a file from
vercel env pull). The two apps share the database, payment, email, upload and sign-in settings. Then set, in both projects:NEXT_PUBLIC_SITE_URL: the main site (https://www.josemadrid.nettoday,https://www.josemadridsalsa.comafter Phase 3)NEXT_PUBLIC_FUNDRAISING_SITE_URL: the fundraising site (https://fundraising.josemadrid.net)
and in the fundraising project only,
NEXTAUTH_URL= the fundraising site's address. -
Sign-in callbacks. Add
https://fundraising.josemadrid.net/api/auth/callback/<provider>to each sign-in provider (Google, Facebook, Apple), alongside the main site's. Accounts are shared, but a session is per domain, so people sign in once on each site. -
Move the domain. After the merge deploys both projects: Vercel → josemadridsalsa → Settings → Domains → remove
fundraising.josemadrid.net, then add it to the fundraising project. No DNS change; josemadrid.net's DNS is already on Vercel. -
Check.
https://www.josemadrid.net/fundraisinglands onhttps://fundraising.josemadrid.net/fundraising; a fundraiser page, the portal sign-in and a test checkout on a fundraiser link all work on the fundraising domain; the portal's logo upload works.
What stays on the main site for now: staff manage fundraisers in the main admin; the fundraiser
mobile app's API (/api/fundraiser-app, since the app has the main site's address built in);
and every webhook (Stripe, PayPal, Square, BigCommerce), so nothing in 3.4 changes for this. The
fundraising app has no Sentry project yet.
Rollback: move fundraising.josemadrid.net back to the main project and revert the merge.
Phase 3 — Move the domains
3.1 Move the BigCommerce storefront to a subdomain (call BigCommerce)
josemadridsalsa.com is about to point at this site, so BigCommerce's storefront and checkout need
an address of their own. The recommended one is shop.josemadridsalsa.com. There, BigCommerce
keeps serving checkout, customer accounts and order history, gift certificate purchase and
balance, and the links in its order emails.
shop.josemadridsalsa.com does not exist yet; this step creates it. Today the old store's
shopping pages (such as /purchase-salsa) live on josemadridsalsa.com itself. After this step,
the old store's own pages are only used for checkout and accounts, and every old
josemadridsalsa.com URL redirects to its page on the new site.
Ask BigCommerce support:
Please change the primary URL and the checkout URL of our storefront channel "Jose Madrid Salsa" (channel 1) from
josemadridsalsa.comtoshop.josemadridsalsa.com. We are moving the main domain to a headless storefront. What DNS record should we add for the subdomain?
Add the DNS record they give you. Wait until https://shop.josemadridsalsa.com loads the old
store over HTTPS, then continue.
Then keep the old store out of search results. At shop.josemadridsalsa.com the old
store still serves every product page, and Google would treat them as duplicates of the new
site's. In BigCommerce → Settings → Storefront → Search engine robots (the robots.txt for
the "Jose Madrid Salsa" storefront), replace the contents with:
User-agent: *
Disallow: /Only after the move
This robots.txt belongs to the storefront, not to a domain. Until BigCommerce support has moved
the storefront to shop.josemadridsalsa.com, that storefront is josemadridsalsa.com, and this
would hide the live store from Google. Checkout keeps working either way; search engines never
need to read it.
3.2 Point josemadridsalsa.com at Vercel
- The day before, lower the TTL on the
josemadridsalsa.comandwwwDNS records to 300 seconds. - In Vercel → josemadridsalsa → Settings → Domains, add
www.josemadridsalsa.comandjosemadridsalsa.com, with the bare domain redirecting towww. Vercel shows the DNS records to use. - At the domain registrar, change the bare-domain and
wwwrecords to Vercel's values. - In Vercel, set
josemadrid.netandwww.josemadrid.netto redirect (308) tohttps://www.josemadridsalsa.com, so there is one site in search results.
3.3 Tell the site its new address
-
In Vercel (Production) set all four to
https://www.josemadridsalsa.com:NEXT_PUBLIC_SITE_URL,NEXT_PUBLIC_BASE_URL,NEXT_PUBLIC_APP_URL,NEXTAUTH_URL. -
Set
BIGCOMMERCE_STOREFRONT_URLtohttps://shop.josemadridsalsa.com. Old links tologin.php,account.php,giftcertificates.phpandwishlist.php(including those in past BigCommerce emails) then go to the customer's real BigCommerce account instead of this site. -
Set
BIGCOMMERCE_CHANNEL_IDonly if BigCommerce support moved checkout to a different channel. Channel 1 is the default. -
In the site admin, Admin → SEO → Site URL:
https://www.josemadridsalsa.com. -
Redeploy.
-
Re-register the product webhooks at the new address:
npm run bigcommerce:webhooks -- https://www.josemadridsalsa.com
3.4 Move every other callback that names the old domain
Webhooks and sign-in callbacks do not follow redirects, so each one registered against
josemadrid.net has to be updated to https://www.josemadridsalsa.com/...:
| Service | Where | What to change |
|---|---|---|
| Stripe | Dashboard → Developers → Webhooks | /api/webhooks/stripe endpoint URL |
| PayPal | Developer dashboard → App → Webhooks | /api/webhooks/paypal |
| Square | Developer dashboard → Webhooks | /api/webhooks/square, and the SQUARE_WEBHOOK_URL variable in Vercel, which the signature check is computed against |
| EasyPost | Dashboard → Webhooks | /api/webhooks/easypost |
| Resend | Dashboard → Webhooks | /api/webhooks/resend |
| Google sign-in | Google Cloud console → OAuth client | Add /api/auth/callback/google on the new domain |
| Facebook / Apple / GitHub sign-in | Each provider's app settings | Add /api/auth/callback/<provider> on the new domain |
| QuickBooks | Intuit developer app → Redirect URIs | Add /api/integrations/quickbooks/callback on the new domain |
3.5 Check
https://www.josemadridsalsa.comloads this site.- Old addresses redirect:
/original-hot/,/choose-6/,/cart.phpand/login.phpeach land on a real page (the full list isapps/storefront/bigcommerce-redirects.mjs). - A checkout lands on
shop.josemadridsalsa.com. https://shop.josemadridsalsa.com/robots.txtshowsDisallow: /, andhttps://www.josemadridsalsa.com/robots.txtdoes not; it's this site's own, which allows the store pages.- Signing in with Google works.
- The Mac and Windows desktop admin apps still open the admin. Both have
josemadrid.net/adminbuilt in, which now redirects to josemadridsalsa.com; sign in again if they ask. - A test Stripe webhook from the Stripe dashboard returns 200.
3.6 Search Console (a person has to do these; no agent has access)
- Add or verify the
josemadridsalsa.comproperty, and submithttps://www.josemadridsalsa.com/sitemap.xml. - On the
josemadrid.netproperty, run Settings → Change of address tojosemadridsalsa.com. - Run URL Inspection on the home page,
/salsas, and two product pages. - A few weeks later, confirm the indexed-page count for
josemadridsalsa.comis rising.
Rollback for Phase 3: point the josemadridsalsa.com and www DNS records back at
BigCommerce and ask BigCommerce support to restore channel 1's primary and checkout URL to
josemadridsalsa.com. DNS changes take effect within the lowered TTL. The BigCommerce side
depends on how quickly support can make the change.
Phase 4 — After the site is live: rotate credentials
The BigCommerce API credentials used during development have been shared, so replace them once the site is running on josemadridsalsa.com:
- In each store, go to Settings → API → Store-level API accounts and create a new account with the scopes listed in Environment Variables.
- Put the new values into Vercel (
BIGCOMMERCE_*for the main store,BIGCOMMERCE_FUNDRAISING_*for the fundraising store) and redeploy. - Check that a salsa page still shows its price and a test checkout still reaches BigCommerce.
- Delete the old API account in each store.
After cutover: who to call
- Checkout, payments, order emails, the BigCommerce admin: BigCommerce support. This is a standard headless setup: a storefront channel with a custom checkout domain.
- This site (Vercel): check Vercel → Deployments. The previous deployment can be promoted back in one click.
- Product edits not showing on the site: re-run
npm run bigcommerce:webhooks -- https://www.josemadridsalsa.com. BigCommerce switches a webhook off after repeated failed deliveries, and re-running the command turns it back on. Pages also refresh on their own within five minutes regardless.
How is this guide?
Last updated on