@kelviq/js-checkout SDK you can keep the customer on your site instead: open checkout as a modal overlay over your current page, or mount it inline inside your own layout. The SDK reports the checkout lifecycle (loaded, success, close, error) back to callbacks you provide.
It is a small script with no dependencies. It works with plain HTML and with any framework.
Embedded checkout needs a checkout session URL created with the Checkout API. Static
/buy/ links are not supported in embedded mode yet.1. Install the SDK
- npm
- Script tag
Kelviq global; with npm, call open() and embed() directly instead.2. Create a checkout session
Create the session from your backend with your server API key and pass the returnedcheckoutUrl to the browser. The same call accepts a customer, discount code, metadata, and the other options described in Create a checkout session.
checkoutUrl to the browser exactly as returned. Do not rewrite its host: the script only accepts messages from the origin of the URL you give it.
3. Open checkout
- Overlay
- Inline
Open checkout as a modal over the current page. Good for a Buy button anywhere on your site.
Kelviq.open() returns a handle with close(). The overlay also closes when the customer clicks the × button, presses Escape, or clicks the backdrop.Options
Both methods takeurl, the optional theme, and the callbacks below. Kelviq.open() also accepts the overlay options.
Color mode (theme)
Pass the mode your page is currently showing. When you omit it, the Default mode configured in the dashboard applies. The checkout’s own light/dark switcher is hidden whenever it is embedded; your page decides.
Callbacks
onClose does not fire when the checkout is about to redirect your page (see below). Use onError to recover, for example by creating a fresh session and opening it again.
Overlay options (Kelviq.open only)
The modal never exceeds the viewport: width and height are capped at the viewport size minus a 24px margin on each side. On phones (viewports up to 519px wide) it opens as a full-screen sheet instead.
Handles
close() or destroy() twice is safe.
Change the plan from your page (update)
update({ planIdentifier?, chargePeriod? }) switches the plan or billing period of the running checkout in place, without reloading it or losing what the customer typed. Use it when your own page has the pricing controls, for example a monthly/yearly toggle next to an inline checkout. Requires @kelviq/js-checkout 1.1.0 or later.
- Values must exist on the session: a plan from the offering and one of its enabled billing periods. The checkout ignores anything else.
- If you change only the period and the current plan has no price for it, the checkout picks the first plan that does, as its own period tabs do.
- Calls made before
onLoadedare queued and applied once the checkout has loaded. - To hide the checkout’s own plan selector and keep yours as the single source of truth, create the session with
plansEnabled: false.
Use with a framework
Call the SDK only in the browser, after the component has mounted, and clean up with the handle when the component unmounts. Never call it during server rendering.- React
- Vue
'use client'. The url comes from a server action or route handler that calls the Checkout API with your server API key.Success callback or redirect
A checkout session ends in exactly one of two ways, decided by whether it has asuccessUrl:
If you rely on
onSuccess for analytics or to update your UI, create the session without a successUrl. For fulfilment, use the checkout.completed webhook in either case: a browser callback can be missed if the customer closes the tab.
Sandbox
Sessions created with a sandbox server API key return a sandboxcheckoutUrl. Pass it to kelviq.js the same way; the script works with both environments. Use a test card (for example 4242 4242 4242 4242) to complete a test payment. See Sandbox and Test payments.
Browser support
- Your page (the SDK): every browser Stripe.js supports, including Chrome 38+, Safari 10.1+, Firefox 29+, Edge 15+, iOS Safari 9+ and Android Chrome 38+. The script never breaks the host page on an unsupported browser.
- The checkout inside the frame: Chrome and Edge 99+, Firefox 97+, Safari 15.4+. On older browsers the customer sees a “browser not supported” message instead of the form, and
onClosestill fires if they dismiss it.
Limitations
- Static checkout links (
https://www.kelviq.com/buy/…) cannot be embedded yet. Create a session with the Checkout API and embed itscheckoutUrl. - Redirect-based payment methods such as iDEAL and Bancontact are not supported in embedded mode. Card payments, including 3D Secure challenges, work.
- Kelviq controls which sites may frame the checkout. If your embed renders blank and the browser console reports a
frame-ancestorsviolation, contact hi@kelviq.com with the domain you embed from.
Troubleshooting
The overlay opens but stays blank
The overlay opens but stays blank
Check the browser console. A Content-Security-Policy
frame-ancestors error means the page is not allowed to frame Kelviq Checkout from your domain. A 404 inside the frame means the session ID is wrong or the session has expired.onSuccess never fires
onSuccess never fires
The session was created with a
successUrl, so the page redirected instead. Create the session without a successUrl, or handle the redirect landing page on your side.The frame shows an error page
The frame shows an error page
The session has expired, was already used, or could not be loaded.
onError fires with a code such as ERR_SESSION_EXPIRED; create a new session and open it again.The inline frame does not resize
The inline frame does not resize
Make sure you passed the
checkoutUrl exactly as the API returned it. The script ignores messages from any other origin, including a different subdomain of the same host.