Browse Packages

Class: Plandalf

This is the ES module class returned by new Plandalf() or init(). The script-tag plandalf object exposes a smaller, intentional public surface. In particular, preload() appears below because it exists on the class, but it is absent from the browser object and the PlandalfSDK interface.

Defined in: packages/sdk/src/core/sdk.ts:213

Plandalf SDK - Main Entry Point

For ES module imports: import { Plandalf, init } from '@plandalf/sdk';

Implements

Constructors

Constructor

new Plandalf(config?): Plandalf

Defined in: packages/sdk/src/core/sdk.ts:228

Parameters

config?

PlandalfConfig = {}

Returns

Plandalf

Properties

harnesses

harnesses: object

Defined in: packages/sdk/src/core/sdk.ts:780

get

get: (id) => HarnessDefinition

Parameters
id

string

Returns

HarnessDefinition

register

register: (harness) => void

Parameters
harness

HarnessDefinition

Returns

void

Implementation of

PlandalfSDK.harnesses

Methods

addGate()

addGate(
  name: string,
  flow: string,
  check?: GateCheck<any>,
): void

Defined in: packages/sdk/src/core/sdk.ts:376

Register a gate. A gate wraps a feature behind an access check. If the check fails (or is absent), the SDK presents the linked flow.

plandalf.addGate("export", "upgrade", () => user.plan !== "free") plandalf.addGate("course", "buy-course") // no check = always presents

Parameters

name

string

flow

string

check?

GateCheck<any>

Returns

void

Implementation of

PlandalfSDK.addGate


configure()

configure(config: Partial<PlandalfConfig>)

Defined in: packages/sdk/src/core/sdk.ts:806

Parameters

config

Partial<PlandalfConfig>

Returns

Plandalf


gate()

async gate(
    name: string,
    sync?: GateSyncCallback,
    options?: Partial<FlowOpenOptions>,
  ): Promise<GateResult>

Defined in: packages/sdk/src/core/sdk.ts:396

Check a gate. If the check passes, resolves immediately with access: true. If it fails, presents the linked flow. After completion, sync returns fresh entitlements and the same check runs again with those values. Check/sync failures deny access without opening another checkout.

Parameters

name

string

sync?

GateSyncCallback

options?

Partial<FlowOpenOptions>

Returns

Promise<GateResult>

Example

import { Plandalf } from '@plandalf/sdk'

declare function readAccessFromServer(): Promise<{ canExport: boolean }>
const sdk = new Plandalf({
  apiBase: 'https://your-org.plandalf.dev',
})
let access = await readAccessFromServer()
sdk.addGate('export', 'upgrade', (fresh) =>
  (fresh as typeof access | undefined)?.canExport ?? access.canExport,
)
const result = await sdk.gate('export', async () => {
  access = await readAccessFromServer()
  return access
})
if (result.access) {
  // Your server must enforce access again for the protected action.
}

The sync callback is your application's code. The returned browser result is useful for UI state; enforce the entitlement on your server. Read the gate guide.

Implementation of

PlandalfSDK.gate


getAnonId()

getAnonId(): string

Defined in: packages/sdk/src/core/sdk.ts:330

Get the anonymous device ID. Always present — generated on first visit, persists forever. Use this to track anonymous visitors and link them to identified users later.

Returns

string

Implementation of

PlandalfSDK.getAnonId


getIdentity()

getIdentity(): VisitorIdentity

Defined in: packages/sdk/src/core/sdk.ts:338

Get the full visitor identity record. Contains anonymous_id, ref, first_seen_at, last_seen_at.

Returns

VisitorIdentity


getRef()

getRef(): string | null

Defined in: packages/sdk/src/core/sdk.ts:345

Get the visitor ref (external identity from ?pf_ref=), or null.

Returns

string | null


getSessionAge()

getSessionAge(): number

Defined in: packages/sdk/src/core/sdk.ts:361

Get seconds elapsed since this visitor first arrived (first_seen_at).

Returns

number


getUserToken()

getUserToken(): string | null

Defined in: packages/sdk/src/core/sdk.ts:321

Get the current user token, or null if anonymous.

Returns

string | null


identify()

identify(token: string): void

Defined in: packages/sdk/src/core/sdk.ts:296

Identify the current user. Accepts a JWT (signed with your API key) or a plain email string.

The token is persisted to localStorage and restored on page reload. It's sent on all subsequent API calls (Authorization header). The anonymous ID is also sent (X-Plandalf-Anon header) so the backend can link anonymous sessions to this user.

plandalf.identify("eyJhbGciOiJIUzI1NiJ9...") // JWT plandalf.identify("jane@acme.com") // email

Parameters

token

string

Returns

void

Implementation of

PlandalfSDK.identify


mount()

mount(
    target: HTMLElement | string,
    slug: string,
    opts: MountOptions = {},
  ): FlowHandle<Flow>

Defined in: packages/sdk/src/core/sdk.ts:602

Mount an offer inline. Mirrors present() but renders into the merchant's own container instead of a frame.

opts.promo accepts a plain promo slug — the SDK resolves the active tier internally and applies its tier price to the cart. Refs come from the existing identity record (auto-captured from ?pf_ref= on init).

Parameters

target

string | HTMLElement

slug

string

opts?

MountOptions = {}

Returns

FlowHandle<Flow>

Example

import { Plandalf } from '@plandalf/sdk'

const sdk = new Plandalf({
  apiBase: 'https://your-org.plandalf.dev',
})
const target = document.querySelector<HTMLElement>('#checkout')
if (!target) throw new Error('Checkout container is missing')
const flow = await sdk.mount(target, 'pro-plan')

The handle resolves when the Flow is mounted. It does not resolve to the final payment outcome.

Implementation of

PlandalfSDK.mount


preload()

preload(...moduleNames: Array<'checkout'>)

Defined in: packages/sdk/src/core/sdk.ts:801

Parameters

moduleNames

..."checkout"[]

Returns

Plandalf


Surface note

This method exists on an ES module Plandalf instance and accepts only 'checkout'. It is not exposed on the browser plandalf object or declared in the PlandalfSDK interface. present() and mount() already load checkout when needed.

optional-preload.ts
import { Plandalf } from '@plandalf/sdk'

const sdk = new Plandalf()
sdk.preload('checkout')

present()

present(
  slug: string,
  options: Partial<FlowOpenOptions> = {},
): FlowHandle<FlowResult>

Defined in: packages/sdk/src/core/sdk.ts:450

Present a flow and wait for it to finish.

Always resolves with a FlowResult describing the outcome. Only real errors (network failure, bad slug, etc.) reject. User-supplied onComplete/onClose/onError callbacks still fire.

Parameters

slug

string

options?

Partial<FlowOpenOptions> = {}

Returns

FlowHandle<FlowResult>

Example

import { Plandalf } from '@plandalf/sdk'

const sdk = new Plandalf({
  apiBase: 'https://your-org.plandalf.dev',
})
const result = await sdk.present('upgrade', { frame: 'modal' })
if (result.status === 'complete') {
  // Refresh access from your server before unlocking a feature.
}

present() returns an awaitable FlowHandle. A dismissal resolves with status: 'dismissed'; genuine loading or session errors reject. See the complete flow.

Implementation of

PlandalfSDK.present


promo()

promo(slug: string, options?: PromoHandleOptions): PromoHandle

Defined in: packages/sdk/src/core/sdk.ts:712

Open a live promo handle. Single entry point for everything promo-related on a host page.

Default behaviour auto-redirects the page to the active tier's redirect_url when the current URL doesn't match (covers both tier-rolled-while-here AND arrived-on-stale-URL). Pass { redirect: false } to disable the side effect and use the handle as a pure listener.

Skipped while a Plandalf checkout frame is open — the in-frame countdown reloads the iframe; we don't yank the host page. One promo per page is the canonical pattern; the SDK dedupes by slug.

DOM attach: every element on the page that names this slug via data-plandalf-promo="<slug>" or data-plandalf-apply-promo="<slug>" is registered against the handle. So plandalf.from(el) returns the same handle for any of them, and plandalf:tier-change / plandalf:expired bubble as DOM CustomEvents on each.

Parameters

slug

string

options?

PromoHandleOptions

Returns

PromoHandle

Example

import { Plandalf } from '@plandalf/sdk'

const sdk = new Plandalf({
  apiBase: 'https://your-org.plandalf.dev',
})
const monitor = sdk.promo('early-bird', { redirect: false })
const state = await monitor
console.log(state?.activeTier?.label, state?.remaining)
monitor.close()

The returned PromoHandle is awaitable and also exposes live .events. Close it when you stop monitoring.

Implementation of

PlandalfSDK.promo


reset()

reset(): void

Defined in: packages/sdk/src/core/sdk.ts:306

Clear the current user identity. The anonymous device ID is preserved — only the user token is removed. Next gate/present call will be anonymous.

Returns

void

Implementation of

PlandalfSDK.reset


resetUser()

resetUser(): void

Defined in: packages/sdk/src/core/sdk.ts:316

Returns

void

Deprecated

Use reset(). Retained as an alias during the migration.


setRef()

setRef(ref: string | null): void

Defined in: packages/sdk/src/core/sdk.ts:354

Set the visitor ref and persist it. Call this once you know who the visitor is (email after opt-in, CRM id after login). Survives reloads and future sessions on the same browser.

Parameters

ref

string | null

Returns

void


setUser()

setUser(token): void

Defined in: packages/sdk/src/core/sdk.ts:313

Parameters

token

string

Returns

void

Deprecated

Use identify(). Retained as an alias during the migration.

Feature detail