LedgerBee Developer
  • Getting started
  • Conventions
  • Products
  • API Reference
Subscriptions
Products & Pricing
Billing documents
WebhooksMCP (AI agents)
Customer Portal
    Portal SSO
    Embedded Checkout
      OverviewPricing cards & snippetLifecycle eventsBind to a customerGated plansFulfillment & errors
Embedded Checkout

Lifecycle events

embed.js validates each message's origin against the iframe it owns, then re-dispatches these as CustomEvents on your window. Wire a handler with addEventListener:

Code
window.addEventListener('ledgerbee:embed:checkoutConfirmed', (e) => { const { planVersionId, planItemId, status, frame } = e.detail; if (status === 'CONFIRMED') frame.remove(); // swap the frame for your thank-you });

Every event's detail carries the fields listed below plus frame, the source <iframe> element, so a page with several embeds can tell which one fired. These events carry ids, the plan slug, and a coarse status only; no email or other PII crosses the iframe boundary.

ledgerbee:embed:pageLoaded

The cards finished their first data-driven paint. Reveal the frame or drop your loading skeleton.

No payload beyond frame.

ledgerbee:embed:checkoutInitiated

The visitor clicked a buy CTA, fired just before the break-out to checkout. In target=callback mode it fires instead of opening anything, so your listener owns the buy action (e.g. route to your signup funnel first, then resume into the bound checkout).

FieldDescription
planVersionIdThe plan version being purchased.
planItemIdThe chosen item within the plan.
vanityThe plan's public vanity slug — build the resume URL …/embed/checkout/<vanity>/<planItemId> straight from it.
deferredtrue only in target=callback mode, where the iframe opened nothing and your listener owns the action; absent otherwise.

ledgerbee:embed:customCtaClicked

The visitor clicked a custom CTA card's button (a "talk to sales" / "book a demo" card, not a checkout). Fired only when the embed was generated with ctaCallback=1: the iframe navigates nothing and hands the click to your page.

FieldDescription
planVersionIdThe plan version the card belongs to.
planItemIdThe card item that was clicked.
vanityThe plan's public slug, so you can correlate which embed fired.
ctaLinkThe operator-configured link the card would otherwise have followed (absolute URL, relative path, mailto:, tel:), or null if unset. Navigate to it yourself, or open your own chat / contact UI instead.

ledgerbee:embed:checkoutConfirmed

The in-frame checkout finished — swap the frame for your own thank-you or remove the iframe. A bound OnPay checkout does not fire this (it breaks out to OnPay to take payment first); reconcile that path via webhooks instead.

FieldDescription
planVersionIdThe plan version that was purchased.
planItemIdThe item that was purchased.
statusHow the in-frame flow finished: CONFIRMED (subscribed directly — safe to remove the frame), PENDING_VERIFICATION (anonymous buyer, magic link sent — keep the frame so they can read "check your inbox").

ledgerbee:embed:checkoutError

An in-frame checkout attempt failed. The buyer still sees the actionable message inside the frame; hook this for analytics or your own retry chrome. A coarse reason only — never the buyer's email, the raw backend error, or any PII.

FieldDescription
planVersionIdThe plan version the attempt was for.
planItemIdThe item the attempt was for.
reasonCoarse, non-sensitive classification: SESSION_MINT_FAILED (the checkout session could not be created — self-signup turned off mid-flow, or a transient 5xx), CONFIRM_FAILED (a confirm submit was rejected — expired or double-spent session, stale terms, invalid start date).

ledgerbee:embed:checkoutClosed

The buyer closed a forced single-item checkout (Cancel/Back on a …/embed/checkout/<vanity>/<planItemId> or gated …/by-id/… surface, which has no cards to fall back to, so it lands on a terminal "Checkout closed" state). The pricing-card surface instead returns the buyer to its cards and emits nothing. A failed session mint emits checkoutError, not this — you never see both for one attempt.

FieldDescription
planVersionIdThe plan version that was abandoned.
planItemIdThe item that was abandoned.

When no event fires

checkoutError is session-mint/confirm-specific — it covers in-frame checkout attempts only. If the browser refuses to frame the embed at all (CSP frame-ancestors — your origin isn't on the partner-origin allowlist), no embed event fires and pageLoaded never arrives. Detect it by the absence of pageLoaded plus the console error, not by listening for an error event. See Errors.

Last modified on June 15, 2026
Pricing cards & snippetBind to a customer
On this page
  • ledgerbee:embed:pageLoaded
  • ledgerbee:embed:checkoutInitiated
  • ledgerbee:embed:customCtaClicked
  • ledgerbee:embed:checkoutConfirmed
  • ledgerbee:embed:checkoutError
  • ledgerbee:embed:checkoutClosed
  • When no event fires
Javascript