Quickstart

Install the Plandalf SDK, open an offer from a button, and handle the completed checkout result.

This guide adds Plandalf checkout to any page with a script tag and one button.

Prerequisites

  • A Plandalf account with an organization subdomain.
  • An offer slug from the Offers editor.
  • A live or test payment integration connected before you accept real payments.

Install the SDK

Add the stub before the SDK script. The stub lets you queue calls before the async SDK file finishes loading.

<script>
  // Queue SDK calls until the async Plandalf bundle is ready.
  window.plandalf = window.plandalf || function () {
    (window.plandalf.q = window.plandalf.q || []).push(arguments);
  };
</script>

<!-- Replace acme with your Plandalf organization subdomain. -->
<script src="https://acme.plandalf.com/js/plandalf-sdk.js" async></script>

Install snippet explained

This script is intentionally small so it can live in page builders, CMS templates, and app layouts.

window.plandalf = window.plandalf || function () { ... }
Creates a temporary function before the real SDK has loaded. Calls made early are not lost.
window.plandalf.q.push(arguments)
Stores queued SDK commands in order. When the SDK initializes, it replays them against the real SDK instance.
https://acme.plandalf.com/js/plandalf-sdk.js
Loads the browser bundle from your Plandalf organization host. Replace acme with your own organization subdomain.

Open an offer

Replace pro-plan with your offer slug.

<button id="buy-pro">Buy Pro</button>

<script>
  document.getElementById("buy-pro").addEventListener("click", async () => {
    // Open the published offer by slug and wait for the final checkout result.
    const result = await plandalf.present("pro-plan");

    // Redirect only after checkout completes successfully.
    if (result.status === "complete") {
      window.location.href = result.redirectUrl ?? "/thank-you";
    }
  });
</script>

plandalf.present() returns a FlowHandle. It behaves like a Promise, so await gives you the final checkout result. It also exposes .events for live purchase events and .close() for dismissing the frame programmatically.

Checkout snippet explained

plandalf.present("pro-plan")
Opens the published offer with the slug pro-plan. The offer controls the products, prices, layout, payment methods, and completion behavior.
await plandalf.present(...)
Waits until the customer completes or dismisses the checkout. Network errors and invalid offer slugs reject the promise.
result.status === "complete"
Confirms that checkout finished successfully before you redirect, unlock access, or call your backend.
result.redirectUrl ?? "/thank-you"
Uses the offer's configured redirect when present, otherwise falls back to your own local thank-you page.

What happens when the customer clicks

1

Button click

Your page calls `plandalf.present()` with the offer slug.

2

Checkout opens

Plandalf creates or resumes a checkout session and renders the published offer.

3

Result resolves

Your code receives a completed or dismissed result and can decide what to do next.

Use declarative HTML

For simple buttons, you can skip custom JavaScript.

<button data-plandalf-present="pro-plan">
  Buy Pro
</button>

Add frame and mode options as attributes.

<button
  data-plandalf-present="pro-plan"
  data-plandalf-frame="slideout"
  data-plandalf-mode="test"
  data-plandalf-size="wide"
>
  Test checkout
</button>

The same checkout trigger in different stacks

HTML

Use the HTML version in no-code builders, the JavaScript version in static pages, and the React version inside app components.

The SDK listens for data attributes and opens the offer when the customer clicks the button.

<button
data-plandalf-present="pro-plan"
data-plandalf-frame="slideout"
data-plandalf-mode="test"
>
Buy Pro
</button>

Expected result

Clicking the button opens the offer in a Plandalf checkout frame. A completed checkout resolves with:

{
  status: "complete",
  session: {
    uuid: "ck_...",
    total: 2900,
    currency: "usd",
    customer: { email: "jane@example.com" }
  },
  customer: { email: "jane@example.com" },
  redirectUrl: "https://example.com/thanks"
}

Customer dismissal is not an exception:

{ status: "dismissed", reason: "cancel" }

Only real errors, such as network failures or an invalid offer slug, reject the Promise.

Next steps

Builder context

Keep building from here.

Use the related Plandalf pages to connect this doc to offers, checkout, timers, integrations, automation, and implementation recipes.

The Numi offer editor with product, theme, automation, invoice, and checkout controls.
The offer editor is the central product surface for checkout and commerce setup.
The Numi platform settings screen showing connected stack configuration.
Integrations connect the offer to the rest of the stack.
The Numi sequences screen showing automated workflow configuration.
Sequences route work after checkout.

Feature detail