localStorage under the widget’s configured key.
- Normal (visible) mode: the widget shows its built-in consent popup; there is nothing for you to do.
- Headless Mode: the widget renders nothing, so it cannot show its popup. Instead, it hands the consent step to you.
The flow
The action pauses
The visitor triggers
startCall() or sendChatMessage(). Because consent hasn’t been given yet, the widget pauses the action instead of executing it.widget.consent-required fires
The widget dispatches
widget.consent-required with { pendingAction: 'voice' | 'chat' } so you know what the visitor was trying to do.Example
Good to know
- Asked once per browser. Consent is persisted in
localStorage, so subsequent visits skip straight to the action. - One flow covers both surfaces. A single consent acceptance covers both voice and chat - you don’t ask twice.
acceptConsent()is always safe. If consent wasn’t requested, the call is a no-op.
The voice-and-chat example includes a complete consent modal serving both surfaces.

