Appearance
Events
There are no callbacks
The SDK exposes no onReady, no onSubmit, no onMessage, and it dispatches no custom DOM events. This is the first thing most integrators look for, so it is worth stating plainly.
The entire public surface is:
- three functions —
init(),scan(),destroy()— and theversionstring; - the
./extractsubpath, for server-side use; - the
data-nam-*attributes; - the CSS custom properties on the host element.
What you would use a callback for, the platform already records. The events below are written to the funnel and are available in reporting rather than in your page.
The funnel events
lp_* keys, written either by the SDK in the browser or by the platform as it processes a turn.
| Event | Written by | Fires when | Once? |
|---|---|---|---|
lp_view | SDK | At least half the form has been on screen. Where IntersectionObserver is unavailable it fires immediately. | Once per session |
lp_assist_start | SDK | The widget has mounted and the agent has taken over. | Once |
lp_field_set | SDK | 400 ms after the visitor — or their password manager — writes into one of your fields. | Every time |
lp_question | Platform | The visitor typed something while a field was open that was not taken as its answer. | Every time |
lp_choice | Platform | A card, a stage action or a sheet action was chosen. | Every time |
lp_beat | Platform | A stage block reached the page. | Every time |
lp_submit | SDK | Your form really submitted. Sent with keepalive so it survives the navigation. | Once |
lp_abandon | SDK | pagehide without a submit and without a restore. Carries the controller state it died in. | Once, and never after a conversion |
Every beacon carries the arm (assist or control) and the landing page id, so a control visitor's funnel is directly comparable to an assisted one.
What is not in them
lp_submit carries the final snapshot as field states and counters — never typed values. The session row records which fields are filled, valid and required, not what was in them.
Controller states
ControllerState is exported for typing, and is the value lp_abandon reports.
idle → arming → control
↘ booting → live → confirm → submittedrestored is reachable from anywhere.
| State | Meaning |
|---|---|
idle | Constructed, not started. |
arming | Session being created; the arm is not known yet. |
control | Holdout control. The view beacon is running and nothing else will happen. |
booting | Assist arm; waiting for the stream and the greeting. |
live | The conversation is running. |
confirm | Every required field is filled; the recap is up and a panel has docked. |
submitted | Your form submitted. |
restored | The SDK stood down and put the form back. |
Snapshot triggers
Every message the SDK posts carries a snapshot of the form and the reason it was taken.
| Trigger | Cause |
|---|---|
assist_start | The opening post, before the greeting. |
user_message | The visitor typed something. |
field_change | The visitor edited one of your fields directly. |
control_answer | They picked a chip, a select option or a tile. |
card_choice | They chose a card or a stage action. |
sheet_action | They acted on a sheet — copying a plan, for instance. |
submit_result | Your form submitted. |
assist_start and submit_result are SDK-authored: they carry a marker string rather than anything the visitor wrote. Platform-side classifiers that read visitor language skip them for that reason.
Stream frames
The SDK reads a Server-Sent Events stream and assembles turns from it.
| Frame | Fields |
|---|---|
connected | sessionId |
message | content, timestamp, and on the final chunk of a turn formActions and offerCards |
A turn announced with chunkIndex / chunkTotal / turnId ends deterministically on its last chunk, or after 15 s if the tail never arrives. A turn with no such metadata ends after 1.5 s of silence. Chunks are joined with a blank line between them.