Skip to main content

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.

npm install @c15t/integrations
src/consent-scripts.ts
import { ada } from '@c15t/integrations/ada';

export const scripts = [ada({ handle: 'YOUR_ADA_HANDLE' })];

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:

import { defineConsentConfig } from 'c15t/next';
import { scripts } from './src/consent-scripts';

export default defineConsentConfig({ scripts });

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

OptionDefaultBehavior
handleRequiredPublic 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.
clusterAda's default regionRegional segment, such as eu, us2 or maple, or a full cluster domain supplied by Ada. Trimmed. Blank values are omitted.
domainAda's default domainAda 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 createAdaEmbedInterface export, or start() rejects, it logs ada: 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 logs ada: failed to stop Messaging.

Cookies and storage

Ada's client-side storage list covers several SDK generations and optional integrations. Entries include:

NamePurpose 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-storageSDK state, session values and version caches. Ada lists these as persistent Web Storage.
chatter, created, inLiveChat, messagingAuthStateConversation, 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:

  1. Load the page without granting functionality. No Ada module, manifest, iframe or API request appears, and the fresh browser context has no Ada storage.
  2. Reject optional consent and reload. Ada still makes no request.
  3. Allow functionality. Look for sdk.js, the rollout manifest, the versioned SDK module and the Ada launcher. window.adaEmbed stays undefined.
  4. 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.
  5. 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:

  1. Load the page. No request goes to the vendor before you choose.
  2. Click Reject, then reload. There is still no vendor request.
  3. Open Privacy settings and allow the helper's category. The vendor script loads without a page reload.
  4. 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.