Skip to main content
Widgets can have “Require consent” enabled - a legal popup the visitor must accept before conversations start. Consent is stored in 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.
In Headless Mode, displaying the consent text is your responsibility. If you have legal requirements for AI-call disclosure or recording notices, your own consent UI must satisfy them.

The flow

1

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.
2

widget.consent-required fires

The widget dispatches widget.consent-required with { pendingAction: 'voice' | 'chat' } so you know what the visitor was trying to do.
3

You show your own consent UI

A modal, a checkbox, an inline banner - whatever fits your design.
4

Accept or decline

On accept, call widget.acceptConsent(): consent is persisted and the paused action resumes automatically - the call starts, or the queued message sends. On decline, do nothing; the action is simply dropped.

Example

const widget = document.querySelector('voiceai-widget');
const modal = document.getElementById('consent-modal');

widget.addEventListener('widget.consent-required', (e) => {
  // e.detail.pendingAction is 'voice' or 'chat' - useful for tailoring the copy
  modal.classList.add('show');
});

document.getElementById('consent-accept').onclick = () => {
  modal.classList.remove('show');
  widget.acceptConsent(); // the paused call/message resumes automatically
};

document.getElementById('consent-decline').onclick = () => {
  modal.classList.remove('show'); // declining = simply not calling acceptConsent()
};

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.