Chat and embeds
Ada
Ada Messaging adds an Ada AI Agent chat widget to your site. The c15t ada
helper waits for functionality consent before it imports Ada's Messaging Web
SDK, and it keeps the Messaging interface private.
When the visitor withdraws, the helper calls Ada's stop() to remove the
widget, and c15t reloads the page by default. stop() doesn't delete stored
conversations or cookies.
Configure Ada Messaging
Get your AI Agent's public handle from your Ada team. Most installations
need only the handle. Set cluster or domain only when Ada gives you a
regional configuration.
Remove any existing Ada module snippet, embed2.js script tag, or tag-manager
installation. A separate Ada installation can load before c15t grants consent,
and Ada allows only one Messaging interface per page.
Register the scripts
Complete your framework quickstart first. Keep its Inth endpoint, policy, styles and consent UI. Remove the vendor's original script, SDK initializer or tag-manager entry, so the vendor loads only through c15t.
The vendor pages put the helper in src/consent-scripts.ts. If your framework
quickstart already has a scripts array, such as the one in c15t.config.ts
in the Next.js guide, add the helper to that array instead of creating a
second file.
The scripts export is a configuration, not an initializer. Add it to the c15t provider you already have, at the registration
point for your framework below. These are edits to that provider, not a second
provider.
Add the configuration to scripts in c15t.config.ts, next to
next.config.ts:
Keep the rest of your config, such as mode and routePrefix, in the
same call. ConsentRoot reads the config in the browser, so the layout
keeps passing only state. App Router, Pages Router and static export all
read the same file. See
Next.js scripts and embeds.
This helper targets the Messaging Web SDK. It doesn't load the legacy Chat SDK
and has no legacy option.
Options
| Option | Default | Behavior |
|---|---|---|
handle | Required | Public AI Agent handle passed to start(). Surrounding whitespace is trimmed. If it's missing or blank, c15t logs ada: missing or invalid handle and never loads Ada. |
cluster | Ada's default region | Regional segment, such as eu, us2 or maple, or a full cluster domain supplied by Ada. Trimmed. Blank values are omitted. |
domain | Ada's default domain | Ada base-domain segment. Use only the value Ada gives you. Trimmed. Blank values are omitted. |
The helper imports https://messaging-assets.ada.support/sdk.js. You can't
set a custom SDK URL, and the helper doesn't bundle the runtime into your app.
Ada's entry module imports the current runtime from its CDN.
If your site has a Content Security Policy, allow
https://messaging-assets.ada.support in script-src, connect-src and
frame-src. Also allow your Agent's API origin in connect-src. Follow
Ada's CSP instructions
for the origin that matches your handle and region.
Loading and revocation
The helper returns a callback-only c15t script with no src. When its consent
is granted, it imports the SDK, calls the module's createAdaEmbedInterface()
export, and awaits start({ handle, cluster, domain }). It creates no
window.adaEmbed or window.adaSettings global. Repeated consent updates don't
start a second widget.
The helper checks the permission c15t passes to it, so if you change the script's category, the gate changes too. The visitor's Ada vendor switch applies inside an allowed category.
One configuration per page
Keep one Ada helper in your scripts array. Helpers with the same handle, cluster and domain share one private interface, and Messaging stops when the last of them is revoked or disposed.
A helper with different settings doesn't change the running widget. When it
gets consent while another configuration is active, it logs a console.warn
(ada: Ada supports one configuration per page) and does nothing until the
page reloads. It stays ignored even after the first configuration stops.
Stopping the widget
When the last granted registration loses consent or is disposed, the helper
calls stop(). Ada documents that stop() removes the SDK frames and
interrupts a pending start(). A later grant waits for the earlier start and
stop to finish, then starts the same interface again. Once every registration
is gone and stop() has run, a new registration can start it with different
settings.
If consent is withdrawn while the SDK import is still pending, the helper
doesn't create or start the interface when the import finishes. Browsers can't
cancel a dynamic import that has already begun, so the SDK can still fetch its
dependencies and write its own bootstrap storage. Keep reloadOnConsentRevoked
enabled to end that work. Imported code stays in memory until the page unloads.
Ada has no documented consent signal or opt-out action. stop() doesn't
promise to erase conversation history, stored tokens or cookies. The helper
doesn't call deleteHistory(), which permanently deletes the conversation and
resets the session.
Errors
The helper logs failures with console.error and doesn't throw:
- If the import fails, the module has no
createAdaEmbedInterfaceexport, orstart()rejects, it logsada: failed to start Messaging.and drops the current registrations. The next consent update can try again, or another configuration can start instead. - If
stop()rejects, it logsada: failed to stop Messaging.
Cookies and storage
Ada's client-side storage list covers several SDK generations and optional integrations. Entries include:
| Name | Purpose and retention |
|---|---|
__Host-ada-session-[session ID]-[generation] | Server-set HttpOnly refresh credential on the Agent's Ada subdomain. Ada lists a session duration of up to seven days. |
ada-embed_*, ada-embed-*, ada-functional-storage | SDK state, session values and version caches. Ada lists these as persistent Web Storage. |
chatter, created, inLiveChat, messagingAuthState | Conversation, session, handoff and authentication state. Ada lists persistent Web Storage, including entries on the Ada domain. |
The hosted SDK bootstrap also stores rollout assignments under
ada-messaging-sdk-rollout:* in the host page's local storage. This happens
while the module evaluates, which is why c15t gates the import itself.
Rollout assignments can remain after stop().
Your Agent can embed other services, such as Calendly, YouTube or a live support platform. Their storage depends on your configuration, so inspect the widget's frames as well as the host page. JavaScript on your page can't read or clear Ada's HttpOnly cookies on another origin.
Verify Ada Messaging
Use a private window with an opt-in policy and your real Ada handle. In
DevTools, disable the Network cache and filter by ada.support:
- Load the page without granting functionality. No Ada module, manifest, iframe or API request appears, and the fresh browser context has no Ada storage.
- Reject optional consent and reload. Ada still makes no request.
- Allow functionality. Look for
sdk.js, the rollout manifest, the versioned SDK module and the Ada launcher.window.adaEmbedstays undefined. - Revoke functionality or turn off the Ada vendor switch. The helper calls
stop(), and c15t reloads by default. The new page makes no Ada request. Stored conversation data can remain. - Allow functionality again. The widget starts once. Repeat the grant and revoke steps on a throttled network to check a pending startup.
Check the console too. An ada: warning means a second configuration with
different settings is in your scripts array.
The helper already calls stop(), the opt-out step the shared checklist below
asks for. Keep the reload enabled anyway, for an import that's still pending.
Sources: Messaging Web SDK installation, settings and lifecycle actions, keep the Messaging interface private, and Ada's client-side storage list.
Test in a private window with an opt-in policy. Open DevTools Network, disable the cache and filter by the vendor's domain:
- Load the page. No request goes to the vendor before you choose.
- Click Reject, then reload. There is still no vendor request.
- Open Privacy settings and allow the helper's category. The vendor script loads without a page reload.
- Turn the category off again and save. c15t reloads the page, and the new page makes no vendor request.
c15t reloads on revocation because removing a script element does not stop
code that already ran. The vendor's listeners, timers and queued events stay
alive until the page unloads. If you set reloadOnConsentRevoked: false, stop
the vendor yourself. Register a callback-only script whose onConsentChange
calls the vendor's opt-out API, as shown in
custom integrations, and check the
permission before each of your own event calls. The reload does not delete
cookies the vendor already set; see
clear on revocation for your framework.
The helper lists its vendor by name in the preference dialog, so a visitor can turn it off inside an allowed category. See vendor consent for your framework. The consent verification guide covers navigation, expiry and hosting checks.