Catalyst version 1.13.1 release notes
Catalyst 1.13.1 is a patch release. It reduces the requests a storefront sends to BigCommerce for bots and ad traffic, restricts the /graphql relay to the operations wallet buttons need, and forwards the shopper IP on more requests so BigCommerce can apply per-IP limits. For a full list of Catalyst changes, see the changeset on GitHub.
GraphQL proxy limited to wallet button operations
The GraphQL proxy lets checkout-sdk-js call the GraphQL Storefront API through the storefront domain to render wallet buttons. It used to relay any query or mutation sent with the x-catalyst-graphql-proxy-requester header, and anyone can set that header.
The proxy now parses each request and forwards it only when it is exactly one of the mutations checkout-sdk-js sends for wallet buttons:
The operation type, name, and root field path must all match, and the document must contain a single operation. Anything else gets a 403, and a body that isn’t valid JSON or has no query gets a 400. Requests without the header continue down the proxy chain as before. Relayed requests now forward the shopper IP.
Tracking parameters share the route cache
The withRoutes proxy resolves each URL with a GraphQL route lookup and caches the result in the KV store. The cache key included the full query string, so every unique utm_source or click ID was a cache miss and a blocking request to BigCommerce, and ad traffic bypassed the cache.
Tracking parameters are now removed from the lookup and the cache key: every parameter that starts with utm_, plus _branch_match_id, _ga, _gl, _hsenc, _hsmi, _kx, dclid, epik, fbclid, gad_campaignid, gad_source, gbraid, gclid, gclsrc, igshid, irclickid, li_fat_id, mc_cid, mc_eid, mkt_tok, msclkid, rdt_cid, sccid, srsltid, ttclid, twclid, wbraid, and yclid. Other parameters keep their original order, because BigCommerce matches redirect sources against the query string as written.
Pages and redirects still receive the original query string. When a 301 redirect matches on a query parameter, the tracking parameters are carried over to the target.
A 301 redirect whose source matches on a tracking parameter, such as /old?utm_campaign=spring, no longer matches. Match on the path or on a parameter that isn’t a tracking parameter instead.
Analytics events only for page navigations
The proxy used to send a VisitStarted mutation for every request without visit cookies, and ProductViewed on the first product view of a visit. Bots and scripts rarely keep cookies, so each of their requests cost one or two uncached mutations.
Catalyst now sends these events only for requests that look like a page load in a browser. A request is skipped when any of the following is true:
- The
User-Agentis empty, or theisbotpackage identifies it as a bot, crawler, or script client. Sec-Fetch-Modeis present and isn’tnavigate, orSec-Fetch-Destis present and isn’tdocument.- Neither fetch metadata header is present and
Acceptdoesn’t includetext/html.
A skipped request gets no visit cookie, so the next real page load still starts a visit. Visits that already exist keep their cookies refreshed on every request. Consent handling and DISABLE_ANALYTICS are unchanged.
Explicit cache options
The root layout sets fetchCache = 'default-cache', so a GraphQL request under [locale] with no cache option was stored in the Data Cache with no expiry. Every client.fetch call now passes an explicit option:
- Shared reads revalidate with
DEFAULT_REVALIDATE_TARGET, 1 hour by default. A changed maintenance message now shows within that window, and the gift certificate settings and favicon refresh the same way. - Mutations and per-customer reads use
cache: 'no-store', so they forward the shopper IP. This covers changing a password, newsletter subscribe and unsubscribe, and switching the cart currency or locale.
Switching back to the store’s default currency now clears the currency cookie, so a cookie set to the default no longer creates a second cache entry for the same data.
Legacy password reset links
When a customer is flagged with “Request customer to set their password on next login”, BigCommerce emails a link in the legacy Stencil format, /login?action=change_password&c=<id>&t=<token>. The login page ignored those parameters. It now forwards the link to /change-password, so the customer can set a new password.
Shopper IP forwarding
- UCP proxy: requests relayed to
/.well-known/ucpand/api/ucp/*now send the caller’s IP asX-Forwarded-ForandTrue-Client-IP, as the GraphQL client already does. - Route and storefront status lookups: the proxy’s lookups now use
cache: 'no-store'. They were never stored in the Data Cache, because the KV store is their cache, so the only change is that they forward the shopper IP.
Route cache warning
Without a shared KV store, the route cache falls back to per-instance memory, and every instance and cold start repeats the route, storefront status, and locale lookups. Catalyst now logs a warning once per process in production when this happens.
Route caching on Storefront Hosting and Vercel
Route caching works out of the box on both documented hosts, with no external KV store or extra configuration:
- Storefront Hosting: each project gets its own Cloudflare Workers KV namespace, bound to the deployment automatically.
- Vercel: route caching uses the Vercel Runtime Cache.
On any other host, set UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN to cache routes in Upstash. Without one of these, route data is cached only in memory, which isn’t shared across server instances, and Catalyst logs a warning in production.
Migration
No migration steps are required, and no environment variables were added or renamed.
Review these behavior changes when you upgrade:
- Redirects on tracking parameters: 301 redirects whose source matches on a tracking parameter no longer match.
- Other libraries on the GraphQL proxy: a client-side library you added to
ALLOWED_REQUESTERSnow gets a403unless its operations are added tocore/lib/graphql-proxy/wallet-operations.ts. - Analytics: visit counts no longer include bots, crawlers, scripts, headless browsers, or synthetic monitors.
If you customized any of these files, review the changes. The changeset on GitHub has the code for each one.
- GraphQL proxy:
core/proxies/with-graphql-proxy.tsuses the newcore/lib/graphql-proxy/wallet-operations.ts. - Routes:
core/proxies/with-routes.tsuses the newcore/lib/routes/route-lookup-search.ts, and its route and storefront status lookups usecache: 'no-store'. - Analytics:
core/proxies/with-analytics-cookies.tsandcore/proxies/with-routes.tsuse the newcore/lib/analytics/is-interactive-request.ts, which adds theisbotdependency. - GraphQL client:
beforeRequestmoved fromcore/client/index.tstocore/client/before-request.ts, with no behavior change.core/lib/currency.tsclears the currency cookie when the default currency is selected. - Login:
core/app/[locale]/(default)/(auth)/login/page.tsxhandles theaction,c, andtsearch parameters. - UCP proxy:
core/lib/ucp/upstream.tsforwards the client IP. - KV store:
core/lib/kv/index.tslogs the memory fallback warning.
Release tags
- @bigcommerce/catalyst-core@1.13.1
- @bigcommerce/catalyst-makeswift@1.13.1
- @bigcommerce/catalyst-b2b-makeswift@1.13.1
Latest stable: