@helpai/elements 0.21.0 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { A as Asset, B as BlocksConfig, C as ConnectionConfig, a as ConnectionConfigPartial, L as Link, S as ServerConfig, b as SiteConfig, c as StartConversationResponse, W as WidgetConfig, d as WidgetConfigPartial, e as WidgetSettings, f as WidgetSettingsPartial } from './deployment-CA9yYj8Y.js';
1
+ export { A as Asset, B as BlocksConfig, C as ConnectionConfig, a as ConnectionConfigPartial, L as Link, S as ServerConfig, b as SiteConfig, c as StartConversationResponse, W as WidgetConfig, d as WidgetConfigPartial, e as WidgetSettings, f as WidgetSettingsPartial } from './deployment-C-Sv0e6E.js';
2
2
  import 'zod';
3
3
 
4
4
  /**
@@ -978,6 +978,45 @@ interface Endpoints {
978
978
  submitForm?: string;
979
979
  }
980
980
 
981
+ /**
982
+ * Built-in anonymous usage tracking — utm.gif-style pixel hits that give
983
+ * the widget OWNER (the site embedding it) insights about how visitors
984
+ * use the widget: events, pages, devices, locales, funnels.
985
+ *
986
+ * Privacy contract (enforced in `src/core/tracking.ts`):
987
+ * - never sends message text, form values, or any user content —
988
+ * event payloads pass through a static per-event allowlist;
989
+ * - the only identifier is the widget's existing anonymous `visitorId`;
990
+ * - geo + browser are derived server-side (IP + User-Agent header),
991
+ * never collected client-side;
992
+ * - `navigator.globalPrivacyControl` / Do-Not-Track force it off
993
+ * regardless of config.
994
+ */
995
+ /** Section: anonymous owner-facing usage tracking. */
996
+ interface TrackingOptions {
997
+ /**
998
+ * Master switch. Default `false` — tracking stays off until the
999
+ * deployment (or the embedding page) explicitly turns it on.
1000
+ */
1001
+ enabled?: boolean;
1002
+ /**
1003
+ * Pixel collector URL. Default: `https://t.<brand domain>/api/ai-elements/px.gif`
1004
+ * (e.g. `https://t.help.ai/api/ai-elements/px.gif`).
1005
+ */
1006
+ endpoint?: string;
1007
+ /**
1008
+ * Per-visitor sampling 0..1. `0.25` tracks ~a quarter of visitors
1009
+ * (decided once per page load, so funnels stay intact). Default `1`.
1010
+ */
1011
+ sampleRate?: number;
1012
+ }
1013
+ /** Post-resolve shape — every field concrete. */
1014
+ interface ResolvedTracking {
1015
+ enabled: boolean;
1016
+ endpoint: string;
1017
+ sampleRate: number;
1018
+ }
1019
+
981
1020
  /**
982
1021
  * The three composing roots: raw input ({@link ChatWidgetOptions}),
983
1022
  * post-normalisation runtime shape ({@link ResolvedOptions}), and the
@@ -1049,6 +1088,8 @@ interface ChatWidgetOptions {
1049
1088
  forms?: FormsOptions;
1050
1089
  /** Messenger modules (Chat / Home / Messages / Help / News tabs). Server-pushable. */
1051
1090
  modules?: ModulesOptions;
1091
+ /** Anonymous owner-facing usage tracking (pixel hits). Server-pushable. */
1092
+ tracking?: TrackingOptions;
1052
1093
  /**
1053
1094
  * Custom client-side storage adapter. Implements the {@link ClientStorage}
1054
1095
  * interface (`get` / `set` / `remove` / `clear`).
@@ -1148,6 +1189,8 @@ interface ResolvedOptions {
1148
1189
  };
1149
1190
  /** Resolved messenger modules — per-module config + ordered enabled list + default tab. */
1150
1191
  modules: ResolvedModules;
1192
+ /** Resolved anonymous usage tracking. */
1193
+ tracking: ResolvedTracking;
1151
1194
  /** Resolved storage adapter — defaults to `LocalStorageAdapter`. */
1152
1195
  storage: ClientStorage;
1153
1196
  onMessage?: ChatWidgetOptions["onMessage"];
@@ -1175,6 +1218,7 @@ interface ServerConfig {
1175
1218
  features?: FeatureFlags;
1176
1219
  forms?: FormsOptions;
1177
1220
  modules?: ModulesOptions;
1221
+ tracking?: TrackingOptions;
1178
1222
  endpoints?: Endpoints;
1179
1223
  }
1180
1224
 
package/index.mjs CHANGED
@@ -468,6 +468,11 @@ var DEFAULT_FEATURES = {
468
468
  humanInLoop: true
469
469
  };
470
470
  var DEFAULT_FORMS = { list: [], byTrigger: {} };
471
+ var DEFAULT_TRACKING = {
472
+ enabled: false,
473
+ endpoint: `https://t.${BRAND.domain}/api/ai-elements/px.gif`,
474
+ sampleRate: 1
475
+ };
471
476
  var DEFAULT_ENDPOINTS = {
472
477
  upload: "/ai/agent/upload-file",
473
478
  transcribe: "/ai/agent/transcribe-audio",
@@ -562,6 +567,7 @@ function resolveOptions(rawOpts) {
562
567
  poweredBy: resolvePoweredBy(footer.poweredBy),
563
568
  composer: resolveComposer(opts.composer),
564
569
  modules: resolveModules(opts.modules),
570
+ tracking: resolveTracking(opts.tracking),
565
571
  storage: opts.storage ?? defaultStorage,
566
572
  onMessage: opts.onMessage,
567
573
  onOpen: opts.onOpen,
@@ -594,6 +600,16 @@ function resolveHaptics(overrides) {
594
600
  events: overrides?.events
595
601
  };
596
602
  }
603
+ function resolveTracking(overrides) {
604
+ const sampleRate = overrides?.sampleRate ?? DEFAULT_TRACKING.sampleRate;
605
+ return {
606
+ enabled: overrides?.enabled ?? DEFAULT_TRACKING.enabled,
607
+ endpoint: overrides?.endpoint ?? DEFAULT_TRACKING.endpoint,
608
+ // Clamp instead of reject — a malformed rate must never turn a
609
+ // disabled tracker on or crash resolve (no Zod on the IIFE path).
610
+ sampleRate: Math.min(1, Math.max(0, Number.isFinite(sampleRate) ? sampleRate : 1))
611
+ };
612
+ }
597
613
  function resolvePoweredBy(overrides) {
598
614
  const brandDefault = {
599
615
  text: `Powered by ${BRAND.displayName}`,
@@ -736,6 +752,7 @@ var SECTION_KEYS = [
736
752
  "i18n",
737
753
  "footer",
738
754
  "features",
755
+ "tracking",
739
756
  "endpoints"
740
757
  ];
741
758
  function mergeServerConfig(user, server) {
@@ -4750,6 +4767,7 @@ function LoadingSpinner({ label }) {
4750
4767
  import { jsx as jsx17, jsxs as jsxs14 } from "preact/jsx-runtime";
4751
4768
  var p15 = BRAND.cssPrefix;
4752
4769
  var STICK_THRESHOLD = 120;
4770
+ var INTERACTION_GRACE_MS = 350;
4753
4771
  var DIVIDER_IDLE_MS = 1200;
4754
4772
  function MessageList({
4755
4773
  messagesSig,
@@ -4770,6 +4788,8 @@ function MessageList({
4770
4788
  const hasHydratedRef = useRef5(false);
4771
4789
  const detachedRef = useRef5(false);
4772
4790
  const interactingRef = useRef5(false);
4791
+ const interactionEndedAtRef = useRef5(0);
4792
+ const inInteractionGrace = () => interactingRef.current || performance.now() - interactionEndedAtRef.current < INTERACTION_GRACE_MS;
4773
4793
  const autoPinAtRef = useRef5(0);
4774
4794
  const pinBottom = (el) => {
4775
4795
  autoPinAtRef.current = performance.now();
@@ -4810,7 +4830,7 @@ function MessageList({
4810
4830
  pinBottom(el);
4811
4831
  return;
4812
4832
  }
4813
- if (detachedRef.current || interactingRef.current) return;
4833
+ if (detachedRef.current || inInteractionGrace()) return;
4814
4834
  const distanceFromBottom = el.scrollHeight - el.scrollTop - el.clientHeight;
4815
4835
  if (distanceFromBottom < STICK_THRESHOLD) pinBottom(el);
4816
4836
  }, [messages.value.length]);
@@ -4820,7 +4840,7 @@ function MessageList({
4820
4840
  const last = messages.value.at(-1);
4821
4841
  if (!last) return;
4822
4842
  const pinIfNear = () => {
4823
- if (detachedRef.current || interactingRef.current) return;
4843
+ if (detachedRef.current || inInteractionGrace()) return;
4824
4844
  const distance = el.scrollHeight - el.scrollTop - el.clientHeight;
4825
4845
  if (distance < STICK_THRESHOLD * 2) pinBottom(el);
4826
4846
  };
@@ -4870,6 +4890,7 @@ function MessageList({
4870
4890
  };
4871
4891
  const endInteraction = () => {
4872
4892
  interactingRef.current = false;
4893
+ interactionEndedAtRef.current = performance.now();
4873
4894
  };
4874
4895
  const onPointerDown = () => {
4875
4896
  interactingRef.current = true;
@@ -5576,10 +5597,10 @@ function createHomeNav(initialTab, tabs, onSwitch) {
5576
5597
  sig.value = { ...sig.value, activeTab: tab };
5577
5598
  onSwitch?.(tab);
5578
5599
  },
5579
- push(screen) {
5600
+ push(screen2) {
5580
5601
  const s = sig.value;
5581
5602
  const stack = s.stacks[s.activeTab] ?? [];
5582
- sig.value = { ...s, stacks: { ...s.stacks, [s.activeTab]: [...stack, screen] } };
5603
+ sig.value = { ...s, stacks: { ...s.stacks, [s.activeTab]: [...stack, screen2] } };
5583
5604
  },
5584
5605
  pop() {
5585
5606
  const s = sig.value;
@@ -7238,6 +7259,118 @@ var EventBus = class {
7238
7259
  }
7239
7260
  };
7240
7261
 
7262
+ // src/core/tracking.ts
7263
+ var PROTOCOL_VERSION = "1";
7264
+ var MAX_HITS_PER_MINUTE = 60;
7265
+ var MAX_URL_LENGTH = 2e3;
7266
+ var TRACKED = {
7267
+ // Panel lifecycle — the owner's "is the widget used at all" funnel.
7268
+ open: () => void 0,
7269
+ close: () => void 0,
7270
+ expand: (on) => ({ on }),
7271
+ fullscreen: (on) => ({ on }),
7272
+ popOut: () => void 0,
7273
+ // Conversation funnel. `send` is the key conversion; text never rides.
7274
+ send: (p33) => ({ attachments: p33.attachmentCount }),
7275
+ message: (p33) => ({ role: p33.role }),
7276
+ stop: () => void 0,
7277
+ clear: () => void 0,
7278
+ suggestion: () => void 0,
7279
+ toggleHistory: (p33) => ({ view: p33.view }),
7280
+ conversationStarted: () => void 0,
7281
+ // Forms + human-in-the-loop — ids and outcomes, never values.
7282
+ formSubmit: (p33) => ({ formId: p33.formId, skipped: p33.skipped }),
7283
+ toolResult: () => void 0,
7284
+ toolDecision: (p33) => ({ approved: p33.approved }),
7285
+ // Composer / attachments / voice.
7286
+ attach: (p33) => ({ count: p33.count, bytes: p33.totalBytes }),
7287
+ voiceStart: () => void 0,
7288
+ voiceStop: (p33) => ({ ms: p33.durationMs }),
7289
+ voiceCancel: () => void 0,
7290
+ // Preferences — how visitors tune the surface.
7291
+ localeChange: (locale) => ({ locale }),
7292
+ themeChange: (theme) => ({ theme }),
7293
+ textSizeChange: (size) => ({ size }),
7294
+ soundToggle: (p33) => ({ muted: p33.muted }),
7295
+ sidebarToggle: (p33) => ({ collapsed: p33.collapsed }),
7296
+ calloutDismiss: () => void 0,
7297
+ // Health signal only — the error object itself never leaves the page.
7298
+ error: () => void 0
7299
+ };
7300
+ function privacySignalsOff() {
7301
+ const nav = navigator;
7302
+ return nav.globalPrivacyControl === true || nav.doNotTrack === "1";
7303
+ }
7304
+ function pageUrl() {
7305
+ return location.origin + location.pathname;
7306
+ }
7307
+ function referrerOrigin() {
7308
+ try {
7309
+ return document.referrer ? new URL(document.referrer).origin : "";
7310
+ } catch {
7311
+ return "";
7312
+ }
7313
+ }
7314
+ function createTracker(bus, deps) {
7315
+ const sampleRoll = Math.random();
7316
+ let windowStart = 0;
7317
+ let windowHits = 0;
7318
+ const inflight = /* @__PURE__ */ new Set();
7319
+ const hit = (event, dims) => {
7320
+ const { tracking, publicKey, aiAgentDeploymentId, mode, themeMode } = deps.getOptions();
7321
+ if (!tracking.enabled || privacySignalsOff()) return;
7322
+ if (sampleRoll >= tracking.sampleRate) return;
7323
+ const now = performance.now();
7324
+ if (now - windowStart > 6e4) {
7325
+ windowStart = now;
7326
+ windowHits = 0;
7327
+ }
7328
+ if (++windowHits > MAX_HITS_PER_MINUTE) return;
7329
+ const params = new URLSearchParams();
7330
+ params.set("v", PROTOCOL_VERSION);
7331
+ params.set("e", event);
7332
+ if (publicKey) params.set("pk", publicKey);
7333
+ if (aiAgentDeploymentId) params.set("dep", aiAgentDeploymentId);
7334
+ params.set("vid", deps.getVisitorId());
7335
+ const cid = deps.getConversationId();
7336
+ if (cid) params.set("cid", cid);
7337
+ params.set("url", pageUrl());
7338
+ const ref = referrerOrigin();
7339
+ if (ref) params.set("ref", ref);
7340
+ params.set("sw", String(screen.width));
7341
+ params.set("sh", String(screen.height));
7342
+ params.set("vw", String(innerWidth));
7343
+ params.set("vh", String(innerHeight));
7344
+ params.set("dpr", String(devicePixelRatio));
7345
+ params.set("lang", navigator.language);
7346
+ try {
7347
+ params.set("tz", Intl.DateTimeFormat().resolvedOptions().timeZone);
7348
+ } catch {
7349
+ }
7350
+ params.set("m", mode);
7351
+ params.set("th", themeMode);
7352
+ if (dims) {
7353
+ for (const [k, val] of Object.entries(dims)) {
7354
+ if (val !== void 0) params.set(k, String(val));
7355
+ }
7356
+ }
7357
+ params.set("ts", String(Date.now()));
7358
+ const url = `${tracking.endpoint}?${params}`;
7359
+ if (url.length > MAX_URL_LENGTH) return;
7360
+ const img = new Image(1, 1);
7361
+ inflight.add(img);
7362
+ img.onload = img.onerror = () => inflight.delete(img);
7363
+ img.src = url;
7364
+ };
7365
+ const offs = Object.keys(TRACKED).map(
7366
+ (event) => bus.on(event, (payload) => hit(event, TRACKED[event]?.(payload)))
7367
+ );
7368
+ return () => {
7369
+ for (const off of offs) off();
7370
+ inflight.clear();
7371
+ };
7372
+ }
7373
+
7241
7374
  // src/core/hooks.ts
7242
7375
  var log19 = logger.scope("hooks");
7243
7376
  var HOOK_WILDCARD = "*";
@@ -7377,6 +7510,11 @@ function mount(opts) {
7377
7510
  applyResolvedHostAttributes();
7378
7511
  renderApp();
7379
7512
  });
7513
+ const unsubscribeTracker = createTracker(bus, {
7514
+ getOptions: () => currentOptions,
7515
+ getVisitorId: () => persistence.getVisitorId(),
7516
+ getConversationId: () => persistence.loadConversationId()
7517
+ });
7380
7518
  const host = mountResult.hostElement;
7381
7519
  let unsubscribeHooks = null;
7382
7520
  const applyUpdate = (patch) => {
@@ -7426,6 +7564,7 @@ function mount(opts) {
7426
7564
  destroy: () => {
7427
7565
  log20.info("destroy", { widgetId });
7428
7566
  unsubscribeHooks?.();
7567
+ unsubscribeTracker();
7429
7568
  bus.clear();
7430
7569
  render(null, mountResult.appRoot);
7431
7570
  mountResult.destroy();
package/package.json CHANGED
@@ -80,5 +80,5 @@
80
80
  ],
81
81
  "type": "module",
82
82
  "types": "./index.d.ts",
83
- "version": "0.21.0"
83
+ "version": "0.22.0"
84
84
  }
package/schema.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { A as Asset, B as BlocksConfig, C as ConnectionConfig, a as ConnectionConfigPartial, E as Endpoints, L as Link, P as PAGE_AREA_SUGGESTIONS, g as PageContext, S as ServerConfig, b as SiteConfig, c as StartConversationResponse, U as UserContext, W as WidgetConfig, d as WidgetConfigPartial, e as WidgetSettings, f as WidgetSettingsPartial, h as assetSchema, i as blocksConfigSchema, j as connectionConfigPartialSchema, k as connectionConfigSchema, l as cssColorSchema, m as cssLengthSchema, n as endpointsSchema, o as linkSchema, p as localeSchema, q as pageContextSchema, s as serverConfigSchema, r as siteConfigSchema, t as startConversationResponseSchema, u as userContextSchema, v as uuid7Schema, w as widgetConfigPartialSchema, x as widgetConfigSchema, y as widgetSettingsPartialSchema, z as widgetSettingsSchema } from './deployment-CA9yYj8Y.js';
1
+ export { A as Asset, B as BlocksConfig, C as ConnectionConfig, a as ConnectionConfigPartial, E as Endpoints, L as Link, P as PAGE_AREA_SUGGESTIONS, g as PageContext, S as ServerConfig, b as SiteConfig, c as StartConversationResponse, U as UserContext, W as WidgetConfig, d as WidgetConfigPartial, e as WidgetSettings, f as WidgetSettingsPartial, h as assetSchema, i as blocksConfigSchema, j as connectionConfigPartialSchema, k as connectionConfigSchema, l as cssColorSchema, m as cssLengthSchema, n as endpointsSchema, o as linkSchema, p as localeSchema, q as pageContextSchema, s as serverConfigSchema, r as siteConfigSchema, t as startConversationResponseSchema, u as userContextSchema, v as uuid7Schema, w as widgetConfigPartialSchema, x as widgetConfigSchema, y as widgetSettingsPartialSchema, z as widgetSettingsSchema } from './deployment-C-Sv0e6E.js';
2
2
  import { z } from 'zod';
3
3
 
4
4
  /**
@@ -56,9 +56,9 @@ declare const presentationSchema: z.ZodObject<{
56
56
  inset: z.ZodOptional<z.ZodString>;
57
57
  initialSize: z.ZodDefault<z.ZodEnum<{
58
58
  fullscreen: "fullscreen";
59
- normal: "normal";
60
59
  expanded: "expanded";
61
60
  auto: "auto";
61
+ normal: "normal";
62
62
  }>>;
63
63
  autoSizeBreakpoint: z.ZodDefault<z.ZodNumber>;
64
64
  }, z.core.$loose>>;
@@ -148,9 +148,9 @@ declare const launcherSizeSchema: z.ZodEnum<{
148
148
  }>;
149
149
  type LauncherSize = z.infer<typeof launcherSizeSchema>;
150
150
  declare const calloutShapeSchema: z.ZodEnum<{
151
+ callout: "callout";
151
152
  pill: "pill";
152
153
  bubble: "bubble";
153
- callout: "callout";
154
154
  }>;
155
155
  type CalloutShape = z.infer<typeof calloutShapeSchema>;
156
156
  declare const calloutPositionSchema: z.ZodEnum<{
@@ -162,9 +162,9 @@ type CalloutPosition = z.infer<typeof calloutPositionSchema>;
162
162
  declare const launcherCalloutSchema: z.ZodObject<{
163
163
  text: z.ZodDefault<z.ZodString>;
164
164
  shape: z.ZodDefault<z.ZodEnum<{
165
+ callout: "callout";
165
166
  pill: "pill";
166
167
  bubble: "bubble";
167
- callout: "callout";
168
168
  }>>;
169
169
  position: z.ZodDefault<z.ZodEnum<{
170
170
  auto: "auto";
@@ -195,9 +195,9 @@ declare const launcherOptionsSchema: z.ZodObject<{
195
195
  callout: z.ZodOptional<z.ZodObject<{
196
196
  text: z.ZodDefault<z.ZodString>;
197
197
  shape: z.ZodDefault<z.ZodEnum<{
198
+ callout: "callout";
198
199
  pill: "pill";
199
200
  bubble: "bubble";
200
- callout: "callout";
201
201
  }>>;
202
202
  position: z.ZodDefault<z.ZodEnum<{
203
203
  auto: "auto";
@@ -240,9 +240,9 @@ type LauncherOptions = z.infer<typeof launcherOptionsSchema>;
240
240
 
241
241
  declare const initialSizeSchema: z.ZodEnum<{
242
242
  fullscreen: "fullscreen";
243
- normal: "normal";
244
243
  expanded: "expanded";
245
244
  auto: "auto";
245
+ normal: "normal";
246
246
  }>;
247
247
  declare const resizeOptionsSchema: z.ZodObject<{
248
248
  enabled: z.ZodDefault<z.ZodBoolean>;
@@ -269,9 +269,9 @@ declare const sizeOptionsSchema: z.ZodObject<{
269
269
  inset: z.ZodOptional<z.ZodString>;
270
270
  initialSize: z.ZodDefault<z.ZodEnum<{
271
271
  fullscreen: "fullscreen";
272
- normal: "normal";
273
272
  expanded: "expanded";
274
273
  auto: "auto";
274
+ normal: "normal";
275
275
  }>>;
276
276
  autoSizeBreakpoint: z.ZodDefault<z.ZodNumber>;
277
277
  }, z.core.$loose>;
@@ -323,43 +323,43 @@ type FeatureFlags = z.infer<typeof featureFlagsSchema>;
323
323
  */
324
324
 
325
325
  declare const actionNameSchema: z.ZodEnum<{
326
+ close: "close";
326
327
  expand: "expand";
327
328
  fullscreen: "fullscreen";
328
329
  popOut: "popOut";
329
- close: "close";
330
- language: "language";
330
+ clear: "clear";
331
331
  theme: "theme";
332
+ language: "language";
332
333
  textSize: "textSize";
333
334
  history: "history";
334
- clear: "clear";
335
335
  sound: "sound";
336
336
  }>;
337
337
  type ActionName = z.infer<typeof actionNameSchema>;
338
338
  declare const headerActionsSchema: z.ZodArray<z.ZodEnum<{
339
+ close: "close";
339
340
  expand: "expand";
340
341
  fullscreen: "fullscreen";
341
342
  popOut: "popOut";
342
- close: "close";
343
- language: "language";
343
+ clear: "clear";
344
344
  theme: "theme";
345
+ language: "language";
345
346
  textSize: "textSize";
346
347
  history: "history";
347
- clear: "clear";
348
348
  sound: "sound";
349
349
  }>>;
350
350
  type HeaderActions = z.infer<typeof headerActionsSchema>;
351
351
  /** Section wrapper — `actions` list wrapped under `header` in the dashboard form. */
352
352
  declare const headerSchema: z.ZodObject<{
353
353
  actions: z.ZodOptional<z.ZodArray<z.ZodEnum<{
354
+ close: "close";
354
355
  expand: "expand";
355
356
  fullscreen: "fullscreen";
356
357
  popOut: "popOut";
357
- close: "close";
358
- language: "language";
358
+ clear: "clear";
359
359
  theme: "theme";
360
+ language: "language";
360
361
  textSize: "textSize";
361
362
  history: "history";
362
- clear: "clear";
363
363
  sound: "sound";
364
364
  }>>>;
365
365
  }, z.core.$loose>;
@@ -375,33 +375,33 @@ type HeaderOptions = z.infer<typeof headerSchema>;
375
375
  */
376
376
 
377
377
  declare const feedbackEventSchema: z.ZodEnum<{
378
+ voiceStart: "voiceStart";
379
+ voiceStop: "voiceStop";
378
380
  error: "error";
379
381
  messageReceived: "messageReceived";
380
382
  messageSent: "messageSent";
381
- voiceStart: "voiceStart";
382
- voiceStop: "voiceStop";
383
383
  }>;
384
384
  type FeedbackEvent = z.infer<typeof feedbackEventSchema>;
385
385
  declare const soundOptionsSchema: z.ZodObject<{
386
386
  enabled: z.ZodDefault<z.ZodBoolean>;
387
387
  volume: z.ZodDefault<z.ZodNumber>;
388
388
  events: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
389
+ voiceStart: "voiceStart";
390
+ voiceStop: "voiceStop";
389
391
  error: "error";
390
392
  messageReceived: "messageReceived";
391
393
  messageSent: "messageSent";
392
- voiceStart: "voiceStart";
393
- voiceStop: "voiceStop";
394
394
  }> & z.core.$partial, z.ZodUnion<readonly [z.ZodBoolean, z.ZodString]>>>;
395
395
  }, z.core.$loose>;
396
396
  type SoundOptions = z.infer<typeof soundOptionsSchema>;
397
397
  declare const hapticsOptionsSchema: z.ZodObject<{
398
398
  enabled: z.ZodDefault<z.ZodBoolean>;
399
399
  events: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
400
+ voiceStart: "voiceStart";
401
+ voiceStop: "voiceStop";
400
402
  error: "error";
401
403
  messageReceived: "messageReceived";
402
404
  messageSent: "messageSent";
403
- voiceStart: "voiceStart";
404
- voiceStop: "voiceStop";
405
405
  }> & z.core.$partial, z.ZodUnion<readonly [z.ZodBoolean, z.ZodNumber, z.ZodArray<z.ZodNumber>]>>>;
406
406
  }, z.core.$loose>;
407
407
  type HapticsOptions = z.infer<typeof hapticsOptionsSchema>;
@@ -410,21 +410,21 @@ declare const feedbackSchema: z.ZodObject<{
410
410
  enabled: z.ZodDefault<z.ZodBoolean>;
411
411
  volume: z.ZodDefault<z.ZodNumber>;
412
412
  events: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
413
+ voiceStart: "voiceStart";
414
+ voiceStop: "voiceStop";
413
415
  error: "error";
414
416
  messageReceived: "messageReceived";
415
417
  messageSent: "messageSent";
416
- voiceStart: "voiceStart";
417
- voiceStop: "voiceStop";
418
418
  }> & z.core.$partial, z.ZodUnion<readonly [z.ZodBoolean, z.ZodString]>>>;
419
419
  }, z.core.$loose>>;
420
420
  haptics: z.ZodOptional<z.ZodObject<{
421
421
  enabled: z.ZodDefault<z.ZodBoolean>;
422
422
  events: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
423
+ voiceStart: "voiceStart";
424
+ voiceStop: "voiceStop";
423
425
  error: "error";
424
426
  messageReceived: "messageReceived";
425
427
  messageSent: "messageSent";
426
- voiceStart: "voiceStart";
427
- voiceStop: "voiceStop";
428
428
  }> & z.core.$partial, z.ZodUnion<readonly [z.ZodBoolean, z.ZodNumber, z.ZodArray<z.ZodNumber>]>>>;
429
429
  }, z.core.$loose>>;
430
430
  }, z.core.$loose>;
@@ -544,16 +544,16 @@ type FooterOptions = z.infer<typeof footerSchema>;
544
544
 
545
545
  declare const fieldTypeSchema: z.ZodEnum<{
546
546
  number: "number";
547
+ select: "select";
548
+ textarea: "textarea";
549
+ time: "time";
547
550
  text: "text";
551
+ checkbox: "checkbox";
552
+ radio: "radio";
548
553
  url: "url";
549
554
  email: "email";
550
555
  tel: "tel";
551
556
  date: "date";
552
- time: "time";
553
- textarea: "textarea";
554
- select: "select";
555
- radio: "radio";
556
- checkbox: "checkbox";
557
557
  multiselect: "multiselect";
558
558
  }>;
559
559
  type FieldType = z.infer<typeof fieldTypeSchema>;
@@ -578,16 +578,16 @@ declare const formFieldSchema: z.ZodObject<{
578
578
  label: z.ZodString;
579
579
  type: z.ZodEnum<{
580
580
  number: "number";
581
+ select: "select";
582
+ textarea: "textarea";
583
+ time: "time";
581
584
  text: "text";
585
+ checkbox: "checkbox";
586
+ radio: "radio";
582
587
  url: "url";
583
588
  email: "email";
584
589
  tel: "tel";
585
590
  date: "date";
586
- time: "time";
587
- textarea: "textarea";
588
- select: "select";
589
- radio: "radio";
590
- checkbox: "checkbox";
591
591
  multiselect: "multiselect";
592
592
  }>;
593
593
  placeholder: z.ZodOptional<z.ZodString>;
@@ -638,16 +638,16 @@ declare const formDefSchema: z.ZodObject<{
638
638
  label: z.ZodString;
639
639
  type: z.ZodEnum<{
640
640
  number: "number";
641
+ select: "select";
642
+ textarea: "textarea";
643
+ time: "time";
641
644
  text: "text";
645
+ checkbox: "checkbox";
646
+ radio: "radio";
642
647
  url: "url";
643
648
  email: "email";
644
649
  tel: "tel";
645
650
  date: "date";
646
- time: "time";
647
- textarea: "textarea";
648
- select: "select";
649
- radio: "radio";
650
- checkbox: "checkbox";
651
651
  multiselect: "multiselect";
652
652
  }>;
653
653
  placeholder: z.ZodOptional<z.ZodString>;
@@ -696,16 +696,16 @@ declare const formsSchema: z.ZodArray<z.ZodObject<{
696
696
  label: z.ZodString;
697
697
  type: z.ZodEnum<{
698
698
  number: "number";
699
+ select: "select";
700
+ textarea: "textarea";
701
+ time: "time";
699
702
  text: "text";
703
+ checkbox: "checkbox";
704
+ radio: "radio";
700
705
  url: "url";
701
706
  email: "email";
702
707
  tel: "tel";
703
708
  date: "date";
704
- time: "time";
705
- textarea: "textarea";
706
- select: "select";
707
- radio: "radio";
708
- checkbox: "checkbox";
709
709
  multiselect: "multiselect";
710
710
  }>;
711
711
  placeholder: z.ZodOptional<z.ZodString>;
@@ -777,18 +777,18 @@ type I18nOptions = z.infer<typeof i18nSchema>;
777
777
  */
778
778
 
779
779
  declare const moduleLayoutSchema: z.ZodEnum<{
780
+ home: "home";
780
781
  chat: "chat";
781
782
  help: "help";
782
- home: "home";
783
783
  news: "news";
784
784
  }>;
785
785
  type ModuleLayout = z.infer<typeof moduleLayoutSchema>;
786
786
  declare const moduleSchema: z.ZodObject<{
787
787
  label: z.ZodString;
788
788
  layout: z.ZodEnum<{
789
+ home: "home";
789
790
  chat: "chat";
790
791
  help: "help";
791
- home: "home";
792
792
  news: "news";
793
793
  }>;
794
794
  contentTags: z.ZodOptional<z.ZodArray<z.ZodString>>;
@@ -814,9 +814,9 @@ type ModuleOptions = z.infer<typeof moduleSchema>;
814
814
  declare const modulesSchema: z.ZodArray<z.ZodObject<{
815
815
  label: z.ZodString;
816
816
  layout: z.ZodEnum<{
817
+ home: "home";
817
818
  chat: "chat";
818
819
  help: "help";
819
- home: "home";
820
820
  news: "news";
821
821
  }>;
822
822
  contentTags: z.ZodOptional<z.ZodArray<z.ZodString>>;
@@ -840,6 +840,22 @@ declare const modulesSchema: z.ZodArray<z.ZodObject<{
840
840
  }, z.core.$loose>>;
841
841
  type ModulesOptions = z.infer<typeof modulesSchema>;
842
842
 
843
+ /**
844
+ * Tracking section schema — built-in anonymous usage analytics for the
845
+ * widget owner (utm.gif-style pixel hits). Off by default; a deployment
846
+ * turns it on to get event / page / device / locale insights without
847
+ * wiring its own analytics. No message content or form values ever ride
848
+ * a hit — payload fields pass a static per-event allowlist in the
849
+ * runtime tracker.
850
+ */
851
+
852
+ declare const trackingSchema: z.ZodObject<{
853
+ enabled: z.ZodOptional<z.ZodBoolean>;
854
+ endpoint: z.ZodOptional<z.ZodURL>;
855
+ sampleRate: z.ZodOptional<z.ZodNumber>;
856
+ }, z.core.$loose>;
857
+ type TrackingSettings = z.infer<typeof trackingSchema>;
858
+
843
859
  /**
844
860
  * Per-mode widget-settings projection.
845
861
  *
@@ -881,4 +897,4 @@ declare const ALL_MODES: readonly Mode[];
881
897
  */
882
898
  declare function emitJsonSchema(): unknown;
883
899
 
884
- export { ALL_MODES, type ActionName, type AttachmentLimits, type Behavior, type CalloutPosition, type CalloutShape, type ComposerOptions, type FeatureFlags, type FeedbackEvent, type FeedbackOptions, type FieldOption, type FieldType, type FieldValidation, type FooterOptions, type FormCondition, type FormDef, type FormField, type Forms, type HapticsOptions, type HeaderActions, type HeaderOptions, type I18nOptions, type LauncherCallout, type LauncherOptions, type LauncherSize, type LauncherVariant, type Mode, type ModuleLayout, type ModuleOptions, type ModulesOptions, type Position, type PoweredBy, type Presentation, type ResizeOptions, type ResponseMode, type SendButtonOptions, type SizeOptions, type SoundOptions, type StringsOverride, type ThemeOverrides, type ThemePreference, type VoiceMode, actionNameSchema, attachmentLimitsSchema, behaviorSchema, calloutPositionSchema, calloutShapeSchema, composerOptionsSchema, emitJsonSchema, featureFlagsSchema, feedbackEventSchema, feedbackSchema, fieldOptionSchema, fieldTypeSchema, fieldValidationSchema, footerSchema, formConditionSchema, formDefSchema, formFieldSchema, formTriggerSchema, formsSchema, hapticsOptionsSchema, headerActionsSchema, headerSchema, i18nSchema, initialSizeSchema, launcherCalloutSchema, launcherOptionsSchema, launcherSizeSchema, launcherVariantSchema, modeSchema, moduleLayoutSchema, moduleSchema, modulesSchema, positionSchema, poweredBySchema, presentationSchema, resizeOptionsSchema, responseModeSchema, sendButtonIconSchema, sendButtonOptionsSchema, sendButtonShapeSchema, sendButtonVariantSchema, sizeOptionsSchema, soundOptionsSchema, stringsOverrideSchema, themeFieldSchema, themeOverridesSchema, themePreferenceSchema, toolRefSchema, voiceModeSchema, widgetSettingsSchemaForMode };
900
+ export { ALL_MODES, type ActionName, type AttachmentLimits, type Behavior, type CalloutPosition, type CalloutShape, type ComposerOptions, type FeatureFlags, type FeedbackEvent, type FeedbackOptions, type FieldOption, type FieldType, type FieldValidation, type FooterOptions, type FormCondition, type FormDef, type FormField, type Forms, type HapticsOptions, type HeaderActions, type HeaderOptions, type I18nOptions, type LauncherCallout, type LauncherOptions, type LauncherSize, type LauncherVariant, type Mode, type ModuleLayout, type ModuleOptions, type ModulesOptions, type Position, type PoweredBy, type Presentation, type ResizeOptions, type ResponseMode, type SendButtonOptions, type SizeOptions, type SoundOptions, type StringsOverride, type ThemeOverrides, type ThemePreference, type TrackingSettings, type VoiceMode, actionNameSchema, attachmentLimitsSchema, behaviorSchema, calloutPositionSchema, calloutShapeSchema, composerOptionsSchema, emitJsonSchema, featureFlagsSchema, feedbackEventSchema, feedbackSchema, fieldOptionSchema, fieldTypeSchema, fieldValidationSchema, footerSchema, formConditionSchema, formDefSchema, formFieldSchema, formTriggerSchema, formsSchema, hapticsOptionsSchema, headerActionsSchema, headerSchema, i18nSchema, initialSizeSchema, launcherCalloutSchema, launcherOptionsSchema, launcherSizeSchema, launcherVariantSchema, modeSchema, moduleLayoutSchema, moduleSchema, modulesSchema, positionSchema, poweredBySchema, presentationSchema, resizeOptionsSchema, responseModeSchema, sendButtonIconSchema, sendButtonOptionsSchema, sendButtonShapeSchema, sendButtonVariantSchema, sizeOptionsSchema, soundOptionsSchema, stringsOverrideSchema, themeFieldSchema, themeOverridesSchema, themePreferenceSchema, toolRefSchema, trackingSchema, voiceModeSchema, widgetSettingsSchemaForMode };