Funnel Navigation
tagada.funnel.navigate() takes the cart from the loaded checkout session, bootstraps an anonymous CMS session, and returns a redirect URL into a specific funnel step. It’s the JS equivalent of the WooCommerce / Shopify checkout plugins — one call from your own site, one URL to redirect to.
When to use it:
- The cart lives in your store (Shopify, WooCommerce, PrestaShop, custom) and you want to route the shopper into a TagadaPay marketing funnel.
- You want the shopper to enter at a specific funnel step (
step_xxx) rather than the funnel default.
- You’re building a fully self-hosted checkout page — use Checkout Flow directly. Do not follow
createSession().checkoutUrl. - You only need a one-shot Tagada-hosted checkout link without a funnel — use
tagada.checkout.createSession()and follow itscheckoutUrl. - You need a self-hosted checkout URL with no funnel — use
tagada.checkout.createSessionUrl()so the shopper stays on your origin.
Prerequisites
accountId is required on createHeadlessClient() — funnel.navigate() will throw TagadaError('missing_account_id') without it.
A checkout session must be loaded first (tagada.checkout.loadSession(...)). The SDK sources the cart, currency, customer email, and promotion code from that session.
React provider:
TagadaHeadlessProvider only forwards accountId through the full config prop, not the individual named props. Pass config={{ storeId, accountId, environment }} if you need funnel navigation in React.Quick Start
- Vanilla JavaScript
- React
- CDN / Script Tag
What Happens Under the Hood
navigate() runs the same sequence the WooCommerce plugin does, with caching so repeat calls in the same page are cheap:
POST /api/v1/cms/session/anonymous— creates an anonymous CMS session, returns a token.POST /api/v1/cms/session/v2/init— initializes the CMS session and binds a CMS customer id.POST /api/v1/funnel/initialize— creates the funnel session forfunnelId+stepId.POST /api/v1/funnel/navigate— fires anINIT_CHECKOUTevent with the cart and returns{ url }.
navigate() again in the same page skips steps 1–3.
navigate() Input Reference
Carrying Your Own Shipping Amount
If your storefront already charges its own shipping, passexternalShipping so the
shopper is charged the amount they agreed to instead of whatever rate the platform
would auto-select:
Keeping your rate when the checkout re-evaluates shipping
The hosted checkout re-evaluates shipping rates when the page loads, when the shopper changes country, and when discount codes move the cart across a rate’s amount bracket. If the rate your storefront picked stops matching the store’s rate conditions — for example a “150” rate on a cart whose catalogue price is $170 before the discount — the checkout swaps it for an eligible one. If your storefront is the authority on shipping, opt out of that re-selection by sendinglockShippingRate: true in metadata alongside your pre-selected rate:
- The checkout keeps the pre-selected rate on load, on country changes and on discount changes; it never auto-selects another one.
- The shipping selector shows that single rate and the shopper cannot change it.
- The lock only applies once a rate is actually on the session (
externalShipping, or a latersetShippingRatecall). With no rate yet, the checkout behaves as if the flag were absent.
Return Value
window.location.assign(url), router.push(url), or whatever your framework uses.
Errors
funnel.navigate() throws typed TagadaErrors:no_cart_loaded—sdk.checkout.loadSession(...)was not called first. The SDK has no cart to send.missing_account_id—accountIdwas not provided oncreateHeadlessClient()and not passed per call.
TagadaNetworkError / TagadaValidationError.SSR & Non-Browser Environments
The SDK readsglobalThis.location?.href for currentUrl when running in a browser. In SSR / Node contexts, pass currentUrl explicitly:
navigate() returns { url } rather than redirecting, it composes cleanly with SPA routers (react-router, next/router) and server-side handoffs.
