Add checkout to your site
You can add checkout to an existing page as a button that opens the offer or as an inline checkout. First publish an offer and copy its slug. The examples use upgrade and the placeholder host https://your-org.plandalf.dev.
1. Choose how the page opens checkout
| Your site | Use | What your page gets |
|---|---|---|
| Editable HTML or a site builder | Organization browser script and data-plandalf-* attributes | Automatic button or inline binding |
| JavaScript app | @plandalf/sdk | An awaitable present() result or a mount() handle |
| React app | @plandalf/react | Provider and hooks for a button, or an inline embed component |
For a first integration, use a button. It lets the existing page keep its layout and works with any of the three modes.
Add the organization script once per page. It scans for the button attribute.
<script defer src="https://your-org.plandalf.dev/js/plandalf-sdk.js"></script>
<button data-plandalf-present="upgrade">
Upgrade
</button>Install the JavaScript package with npm install @plandalf/sdk. Use status for an on-page message, then read verified access from your server if this is a paid upgrade.
import { Plandalf } from '@plandalf/sdk'
const sdk = new Plandalf({ apiBase: 'https://your-org.plandalf.dev' })
const button = document.querySelector('#upgrade')
button.addEventListener('click', async () => {
button.disabled = true
try {
const result = await sdk.present('upgrade')
if (result.status === 'complete') {
// Refresh verified access from your own server.
}
} finally {
button.disabled = false
}
})<button id="upgrade">Upgrade</button>Install the React package with npm install @plandalf/react. Hooks run inside PlandalfProvider.
import { PlandalfProvider, usePresent } from '@plandalf/react'
function UpgradeButton() {
const { present, presenting } = usePresent()
async function upgrade() {
const result = await present('upgrade')
if (result.status === 'complete') {
// Refresh verified access from your own server.
}
}
return <button disabled={presenting} onClick={upgrade}>Upgrade</button>
}
export function UpgradePage() {
return <PlandalfProvider apiBase="https://your-org.plandalf.dev">
<UpgradeButton />
</PlandalfProvider>
}2. Choose inline checkout if the page needs it
An inline checkout lives in a container on the page. Use one mounting method for a given container. Do not put data-plandalf-mount on a container that your JavaScript also passes to mount().
With the browser script already loaded, this container mounts the offer automatically:
<script defer src="https://your-org.plandalf.dev/js/plandalf-sdk.js"></script>
<div data-plandalf-mount="upgrade"></div>mount() resolves when the inline flow is ready. Its handle can emit later checkout events; the resolved value is not a completed purchase.
import { Plandalf } from '@plandalf/sdk'
const sdk = new Plandalf({ apiBase: 'https://your-org.plandalf.dev' })
const handle = sdk.mount('#checkout', 'upgrade')
const flow = await handle
// The inline checkout is now mounted; your server still verifies any purchase.<div id="checkout"></div>The React package source exports an inline offer embed. Pass the offer and organization domain; its completion callback is a page signal, not payment proof.
import { OfferStandardEmbed } from '@plandalf/react'
export function InlineUpgrade() {
return <OfferStandardEmbed
offer="upgrade"
domain="https://your-org.plandalf.dev"
onComplete={() => { /* Refresh verified access from your server. */ }}
/>
}3. Check it on your real page
Confirm the correct offer and price open, the button can be used again after a dismissal, and the inline checkout fits your page at narrow widths. For any test payment, first verify that the offer and integration are explicitly configured for sandbox use. A mode: 'test' override can fall back to live for public visitors, and mount() in the checked-out SDK does not forward a mode option to the mounted flow. If the offer does not appear, check the organization host, published slug, script request, and any content security policy blocking the script or frame. Complete a provider-supported sandbox payment and verify it server-side before delivering access.
For a button with a fuller result example, see Add checkout to a button. present() returns a checkout result; mount() returns an inline flow. Their option types show the exact configuration accepted by each method.