Release preview: The headless APIs below are implemented and tested in the repository, but the referenced@puntego/embedand@puntego/reactpackages are not yet published to npm. Treat these examples as the upcoming package contract until the package release is announced. This does not affect the production hosted-script path for Puntego’s built-in Guide and Experiences.
Framework-neutral client
Load the page-level runtime once, explicitly in headless mode, then create the state adapter:destroy() detaches adapter
listeners; it does not destroy the shared page-level Puntego runtime.
To tell the guide about the signed-in account, hand the adapter plain data
whenever it changes. It keeps a JSON copy and serves it on every message:
accountId (or the signed token’s subject) names another account, the guide
starts a new conversation: once setContext resolves, the Guide and turn
snapshots no longer hold the previous account’s messages, and their subscribers
are notified. setContext(null) stops sending account facts. See
Account facts.
The adapter also carries assist, the guide as a tool for other AI agents
(query, handleToolCall, tools), when the owner turned it on. A headless
install renders no guide card, so only ask is available there: showing the
way and actions the visitor approves need the guide’s own surfaces. See
Other AI agents.
Typed turns
getGuideSnapshot() keeps its four fields for existing integrations. For a
complete custom answer surface, read the typed turn model instead: each
PuntegoTurn carries the visitor’s question, the answer text, the disclosed
sources, the follow-up chips, a tour proposal, the footer actions the built-in
guide would show, and the turn’s status and timings.
getTurnSnapshot() returns the last 20 turns, oldest first, deep-frozen. The
client re-reads it once per burst of turn:* events and returns the same
reference until the next change, so it can back useSyncExternalStore
directly. A turn never carries credentials, proofs, raw source identities,
selectors, target ids, or executable actions: web sources expose a navigable
href, published notes expose only their title and revision, and generative UI
blocks are reduced to their id, kind, title, and visible text. A chart block
also carries chart (its figures with their layout as fractions of the plot)
and a metric grid metrics (each tile’s limit, meter, change and trend), so you
can draw them yourself; see React components.
Footer actions are ordered tertiary → neutral → primary with at most one
primary. Their labels are localized in the conversation’s language (the
page’s language until the first answer says otherwise). footer.meta
includes aiLabel, the visible AI identification your answer surface should
show. It is empty on an error turn that shows no generated text and on a
notice the Worker writes itself (the site’s pause or a limit), because neither
is an AI answer.
runTurnAction(turnId, actionId) runs one of the latest turn’s footer actions
(show_me_how, do_it, point_it_out, take_me_there, …) from your own
button, through the built-in button’s path: it resolves false when the turn
does not offer that action now, and do_it/undo need a real visitor gesture,
so call it from your click handler. React apps can render the whole card with
their own components through @puntego/react/ui.
Commands are inert in privacy-only mode, while consent blocks the assistant,
and after destroy(). A runtime older than the turn model has no turn
commands: the client then returns an empty snapshot, rateTurn,
respondToProposal and replayTour resolve false, and the other commands do
nothing. replayTour also resolves false on a hosted runtime that predates
it.
React hooks
Passheadless to the page-level provider and render snapshots with normal
React components:
usePuntegoGuide() also returns the typed turn model — turn (the latest
turn, or null), turns, and the commands selectFollowUp,
respondToProposal, replayTour, rate, resolve, retry, and stop:
Experience engagements
getExperienceSnapshot() and usePuntegoExperiences() expose deployed content,
revision identity, matched route, and checklist state. They accept only typed
engagements:
- impression or dismissal;
- an authored action index;
- checklist completion;
- validated Survey or Form answers.
start_playbook action can start only the playbook bound to
the server receipt. A tour with no playbook carries a start_tour action: it
starts the tour’s authored steps and nothing else. An authored Guide prompt can start a text stream without
reopening the built-in panel. Arbitrary code and arbitrary network execution are
not part of the API.
Snapshots preserve the presentation discriminants for hint, release_feed,
and progress. Custom UI owns the local open/collapse state, while the same
typed engagement methods remain authoritative. See Hints, release feeds, and
progress badges for the content shapes and event model.
Reusable placement Collections
Resolve a stable inline placement without exposing the private match proof:Consent and security boundaries
Headless mode disables the built-in launcher, chat panel, automatic opening, automatic questions, proactive nudges, voice hotkey, and built-in Experience renderer. It does not disable required consent/privacy controls, PII scrubbing, target policy, risk confirmation, action postconditions, or audit events. Keep these boundaries in your custom UI:- Mint authenticated customer identity tokens on your server and pass each one-time token to the first loader/provider mount. Never persist it.
- Render status and errors with
aria-live; keep controls keyboard accessible and restore focus when custom dialogs close. - Show a clear confirmation for consequential action requests and a durable success/failure state. Runtime policy remains authoritative.
- Call
trackEvent(name)only for bounded, authored milestone names. Arbitrary event payloads are intentionally unsupported. CRM user/group traits must be supplied by your authenticated server through the one-time identity handoff. Account facts (plan, seats, usage, features) go throughsetContext: facts the page reports only ground answers, and anything that needs proof must be signed by your server (signedAccountFacts).
Auditability
Guide streams continue to emit typed runtime events. Experience engagement responses include only public acceptance, duplicate, action receipt, and submission receipt identifiers. The runtime’s signed matching proof never appears in a snapshot or event. Each turn emitsturn:start once, turn:status per stage change, turn:text
per released text batch, coalesced turn:update for anything else, and exactly
one of turn:complete, turn:stopped, or turn:error (a turn replaced or
cleared before it ended gets turn:stopped). turn:removed fires once when a
turn leaves the conversation (a new conversation, an account switch), so a UI
that caches turns drops it. turn:resolved, feedback:submitted,
panel:open, panel:close, and navigate (fired just before an in-product
navigation) complete the set. The chat:* events keep
firing unchanged.
Use experience:engaged, guide-action:proposed, guide-action:started,
guide-action:completed, and guide-action:failed for host-side observability.
The authoritative action and Experience audit records remain on Puntego’s
authenticated backend.