@customerhero/js 1.0.0 → 1.1.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/dist/index.cjs +549 -9
- package/dist/index.d.cts +237 -1
- package/dist/index.d.ts +237 -1
- package/dist/index.js +545 -8
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -123,6 +123,133 @@ interface IdentityData {
|
|
|
123
123
|
userHash?: string;
|
|
124
124
|
customProperties?: Record<string, string | number | boolean>;
|
|
125
125
|
}
|
|
126
|
+
type TriggerConditionNode = {
|
|
127
|
+
all: TriggerConditionNode[];
|
|
128
|
+
} | {
|
|
129
|
+
any: TriggerConditionNode[];
|
|
130
|
+
} | TriggerConditionLeaf;
|
|
131
|
+
type TriggerConditionLeaf = {
|
|
132
|
+
kind: "url_path";
|
|
133
|
+
op: "equals" | "contains" | "regex" | "starts_with";
|
|
134
|
+
value: string;
|
|
135
|
+
} | {
|
|
136
|
+
kind: "url_query";
|
|
137
|
+
key: string;
|
|
138
|
+
op: "equals" | "contains" | "exists";
|
|
139
|
+
value?: string;
|
|
140
|
+
} | {
|
|
141
|
+
kind: "referrer";
|
|
142
|
+
op: "contains" | "equals" | "regex";
|
|
143
|
+
value: string;
|
|
144
|
+
} | {
|
|
145
|
+
kind: "time_on_page";
|
|
146
|
+
seconds: number;
|
|
147
|
+
} | {
|
|
148
|
+
kind: "scroll_depth";
|
|
149
|
+
percent: number;
|
|
150
|
+
} | {
|
|
151
|
+
kind: "exit_intent";
|
|
152
|
+
} | {
|
|
153
|
+
kind: "device";
|
|
154
|
+
op: "equals";
|
|
155
|
+
value: "mobile" | "tablet" | "desktop";
|
|
156
|
+
} | {
|
|
157
|
+
kind: "browser_language";
|
|
158
|
+
op: "in";
|
|
159
|
+
values: string[];
|
|
160
|
+
} | {
|
|
161
|
+
kind: "visitor_trait";
|
|
162
|
+
key: string;
|
|
163
|
+
op: "equals" | "exists" | "gt" | "lt";
|
|
164
|
+
value?: string | number | boolean;
|
|
165
|
+
} | {
|
|
166
|
+
kind: "return_visit";
|
|
167
|
+
op: "gte" | "eq";
|
|
168
|
+
count: number;
|
|
169
|
+
};
|
|
170
|
+
type TriggerAction = {
|
|
171
|
+
kind: "open_widget";
|
|
172
|
+
} | {
|
|
173
|
+
kind: "send_message";
|
|
174
|
+
message: string;
|
|
175
|
+
} | {
|
|
176
|
+
kind: "show_form";
|
|
177
|
+
} | {
|
|
178
|
+
kind: "open_with_prefill";
|
|
179
|
+
prefill: string;
|
|
180
|
+
};
|
|
181
|
+
type TriggerFrequency = "once_ever" | "once_per_session" | "every_time";
|
|
182
|
+
interface TriggerDefinition {
|
|
183
|
+
id: string;
|
|
184
|
+
priority: number;
|
|
185
|
+
conditions: TriggerConditionNode;
|
|
186
|
+
action: TriggerAction;
|
|
187
|
+
frequency: TriggerFrequency;
|
|
188
|
+
}
|
|
189
|
+
type PreChatFieldKind = "name" | "email" | "phone" | "text" | "textarea" | "select" | "consent";
|
|
190
|
+
type PreChatField = {
|
|
191
|
+
kind: "name";
|
|
192
|
+
required?: boolean;
|
|
193
|
+
label?: string;
|
|
194
|
+
} | {
|
|
195
|
+
kind: "email";
|
|
196
|
+
required?: boolean;
|
|
197
|
+
label?: string;
|
|
198
|
+
validateMx?: boolean;
|
|
199
|
+
} | {
|
|
200
|
+
kind: "phone";
|
|
201
|
+
required?: boolean;
|
|
202
|
+
label?: string;
|
|
203
|
+
} | {
|
|
204
|
+
kind: "text";
|
|
205
|
+
key: string;
|
|
206
|
+
label: string;
|
|
207
|
+
required?: boolean;
|
|
208
|
+
maxLength?: number;
|
|
209
|
+
} | {
|
|
210
|
+
kind: "textarea";
|
|
211
|
+
key: string;
|
|
212
|
+
label: string;
|
|
213
|
+
required?: boolean;
|
|
214
|
+
maxLength?: number;
|
|
215
|
+
} | {
|
|
216
|
+
kind: "select";
|
|
217
|
+
key: string;
|
|
218
|
+
label: string;
|
|
219
|
+
options: Array<{
|
|
220
|
+
value: string;
|
|
221
|
+
label: string;
|
|
222
|
+
}>;
|
|
223
|
+
required?: boolean;
|
|
224
|
+
} | {
|
|
225
|
+
kind: "consent";
|
|
226
|
+
key: string;
|
|
227
|
+
label: string;
|
|
228
|
+
url?: string;
|
|
229
|
+
required: true;
|
|
230
|
+
};
|
|
231
|
+
interface PreChatFormConfig {
|
|
232
|
+
fields: PreChatField[];
|
|
233
|
+
title?: string | null;
|
|
234
|
+
description?: string | null;
|
|
235
|
+
submitLabel: string;
|
|
236
|
+
/** When true, an identified visitor (CustomerHero.identify already called)
|
|
237
|
+
* bypasses the form. */
|
|
238
|
+
skipForIdentified: boolean;
|
|
239
|
+
}
|
|
240
|
+
interface PreChatSubmission {
|
|
241
|
+
name?: string;
|
|
242
|
+
email?: string;
|
|
243
|
+
phone?: string;
|
|
244
|
+
/** Keyed answers from text/textarea/select/consent fields. */
|
|
245
|
+
properties?: Record<string, string | number | boolean>;
|
|
246
|
+
}
|
|
247
|
+
interface ConsentSettings {
|
|
248
|
+
/** When true, all condition kinds are evaluated. When false (default), only
|
|
249
|
+
* direct launcher clicks fire — URL/time/scroll/exit-intent/trait
|
|
250
|
+
* conditions stay dormant. */
|
|
251
|
+
analytics: boolean;
|
|
252
|
+
}
|
|
126
253
|
interface ChatState {
|
|
127
254
|
messages: ChatMessage[];
|
|
128
255
|
isOpen: boolean;
|
|
@@ -137,6 +264,26 @@ interface ChatState {
|
|
|
137
264
|
locale: SupportedLocale;
|
|
138
265
|
/** True when the active locale is right-to-left. */
|
|
139
266
|
isRtl: boolean;
|
|
267
|
+
/** Triggers loaded from the server config (active + in-window). */
|
|
268
|
+
triggers: TriggerDefinition[];
|
|
269
|
+
/** Pre-chat form configuration, if any. */
|
|
270
|
+
preChatForm: PreChatFormConfig | null;
|
|
271
|
+
/**
|
|
272
|
+
* True when the pre-chat form must be shown before the next chat turn.
|
|
273
|
+
* Flipped by trigger actions, by the first sendMessage when a form is
|
|
274
|
+
* configured and not yet submitted, and cleared on submit.
|
|
275
|
+
*/
|
|
276
|
+
preChatFormVisible: boolean;
|
|
277
|
+
/** Captured pre-chat submission, sent on the first chat call. */
|
|
278
|
+
preChatSubmission: PreChatSubmission | null;
|
|
279
|
+
/** Per-visitor consent. Until set explicitly, only direct launcher clicks
|
|
280
|
+
* trigger; behavioral conditions stay dormant. */
|
|
281
|
+
consent: ConsentSettings;
|
|
282
|
+
/** ID of the trigger attributed to the next conversation start, if any. */
|
|
283
|
+
pendingTriggerId: string | null;
|
|
284
|
+
/** When set, the host should preload this text into the input. Cleared
|
|
285
|
+
* once the host consumes it (or when the conversation starts). */
|
|
286
|
+
pendingPrefill: string | null;
|
|
140
287
|
}
|
|
141
288
|
|
|
142
289
|
type Listener = (state: ChatState) => void;
|
|
@@ -148,6 +295,10 @@ declare class CustomerHeroChat {
|
|
|
148
295
|
private identityData;
|
|
149
296
|
t: TranslateFn;
|
|
150
297
|
constructor(config: CustomerHeroChatConfig);
|
|
298
|
+
private triggersRuntime;
|
|
299
|
+
private preChatFormSubmitted;
|
|
300
|
+
private readStoredConsent;
|
|
301
|
+
private writeStoredConsent;
|
|
151
302
|
setLocale(tag: string): void;
|
|
152
303
|
private rebuildTranslator;
|
|
153
304
|
subscribe(listener: Listener): () => void;
|
|
@@ -179,6 +330,38 @@ declare class CustomerHeroChat {
|
|
|
179
330
|
open(): void;
|
|
180
331
|
close(): void;
|
|
181
332
|
reset(): void;
|
|
333
|
+
/** Update visitor consent. Until `analytics: true` is set, only direct
|
|
334
|
+
* launcher clicks fire — URL/time/scroll/exit-intent/trait conditions
|
|
335
|
+
* stay dormant. The setting is persisted in localStorage so revisits
|
|
336
|
+
* don't re-prompt. */
|
|
337
|
+
setConsent(consent: Partial<ConsentSettings>): void;
|
|
338
|
+
/** Set or update visitor traits used by trait-based conditions. The trait
|
|
339
|
+
* values are kept in memory (not persisted) so the integrator decides
|
|
340
|
+
* the source of truth. */
|
|
341
|
+
setTraits(traits: Record<string, string | number | boolean>): void;
|
|
342
|
+
/** Submit pre-chat form answers. Synthesizes a customer record server-side
|
|
343
|
+
* on the next sendMessage. Resumes any pending message that was deferred
|
|
344
|
+
* while the form was open. */
|
|
345
|
+
submitPreChatForm(submission: PreChatSubmission): Promise<void>;
|
|
346
|
+
/** Dismiss the pre-chat form without submitting. The form will reappear
|
|
347
|
+
* on the next sendMessage attempt — call `setConsent` to acknowledge a
|
|
348
|
+
* refusal, or `reset()` to clear pending state. */
|
|
349
|
+
cancelPreChatForm(): void;
|
|
350
|
+
/** Programmatically dispatch the action attached to a trigger. Used by
|
|
351
|
+
* integrators who want to act on a custom button, e.g. an exit-intent
|
|
352
|
+
* modal in their own UI. */
|
|
353
|
+
fireTrigger(triggerId: string): void;
|
|
354
|
+
private pendingMessageAfterPreChat;
|
|
355
|
+
private shouldShowPreChatForm;
|
|
356
|
+
private startTriggersRuntimeIfPossible;
|
|
357
|
+
private handleTriggerAction;
|
|
358
|
+
/** Read and clear the pending prefill (set by an `open_with_prefill`
|
|
359
|
+
* trigger). The host calls this once when mounting the input and seeds
|
|
360
|
+
* its controlled value with the result. */
|
|
361
|
+
consumePendingPrefill(): string | null;
|
|
362
|
+
/** Stop the triggers runtime and detach listeners. Safe to call multiple
|
|
363
|
+
* times; safe to call before the runtime started. */
|
|
364
|
+
destroy(): void;
|
|
182
365
|
identify(payload: IdentifyPayload): void;
|
|
183
366
|
}
|
|
184
367
|
|
|
@@ -202,4 +385,57 @@ declare class ScreenshotUnavailable extends Error {
|
|
|
202
385
|
declare function canCaptureScreenshot(): boolean;
|
|
203
386
|
declare function captureScreenshot(): Promise<Blob>;
|
|
204
387
|
|
|
205
|
-
|
|
388
|
+
interface VisitorContext {
|
|
389
|
+
url: string;
|
|
390
|
+
queryParams: Record<string, string>;
|
|
391
|
+
referrer: string;
|
|
392
|
+
language: string;
|
|
393
|
+
device: "mobile" | "tablet" | "desktop";
|
|
394
|
+
/** Time spent on the current page (in ms). Pauses while the tab is hidden. */
|
|
395
|
+
timeOnPageMs: number;
|
|
396
|
+
/** Scroll depth as a percentage of the document height (0..100). Tracked as
|
|
397
|
+
* a high-water mark so a quick scroll-up doesn't undo a `scroll_depth`
|
|
398
|
+
* match. */
|
|
399
|
+
scrollPercent: number;
|
|
400
|
+
/** True after the runtime detected a desktop-style exit-intent gesture or
|
|
401
|
+
* the mobile fallback (visibilitychange→hidden after a grace period). */
|
|
402
|
+
exitIntentSeen: boolean;
|
|
403
|
+
/** Number of distinct sessions this visitor has visited the page. */
|
|
404
|
+
returnVisitCount: number;
|
|
405
|
+
/** Custom traits set by the integrator via `setTraits` / `identify`. */
|
|
406
|
+
traits: Record<string, string | number | boolean>;
|
|
407
|
+
}
|
|
408
|
+
declare function evaluate(node: TriggerConditionNode, ctx: VisitorContext): boolean;
|
|
409
|
+
/** Walk `triggers` in priority order (low number = high priority) and return
|
|
410
|
+
* the first one that matches `ctx` and isn't already in `firedSet`. The
|
|
411
|
+
* caller decides what `firedSet` means — once_ever uses long-lived storage,
|
|
412
|
+
* once_per_session uses the in-memory or sessionStorage set, every_time
|
|
413
|
+
* always misses the set so it can re-fire. */
|
|
414
|
+
declare function pickFire(triggers: TriggerDefinition[], ctx: VisitorContext, firedSet: ReadonlySet<string>): TriggerDefinition | null;
|
|
415
|
+
|
|
416
|
+
interface TriggersRuntimeHandle {
|
|
417
|
+
/** Stop all watchers and remove listeners. */
|
|
418
|
+
stop(): void;
|
|
419
|
+
/** Force a re-evaluation (used after the integrator calls setTraits). */
|
|
420
|
+
reevaluate(): void;
|
|
421
|
+
/** Update visitor traits and re-evaluate. */
|
|
422
|
+
setTraits(traits: Record<string, string | number | boolean>): void;
|
|
423
|
+
/** Mark a trigger as fired (used after a direct launcher click acted on
|
|
424
|
+
* a trigger or when the runtime fired one itself). */
|
|
425
|
+
markFired(triggerId: string, frequency: TriggerFrequency): void;
|
|
426
|
+
}
|
|
427
|
+
interface StartTriggersRuntimeOptions {
|
|
428
|
+
chatbotId: string;
|
|
429
|
+
triggers: TriggerDefinition[];
|
|
430
|
+
/** Returns true when the runtime is allowed to fire a trigger. The client
|
|
431
|
+
* uses this to gate on consent — only direct launcher clicks fire until
|
|
432
|
+
* the integrator has called `setConsent({ analytics: true })`. */
|
|
433
|
+
isAllowedToFire(): boolean;
|
|
434
|
+
/** Called when a trigger is selected to fire. */
|
|
435
|
+
onFire(trigger: TriggerDefinition): void;
|
|
436
|
+
/** Optional initial traits seed. */
|
|
437
|
+
initialTraits?: Record<string, string | number | boolean>;
|
|
438
|
+
}
|
|
439
|
+
declare function startTriggersRuntime(options: StartTriggersRuntimeOptions): TriggersRuntimeHandle;
|
|
440
|
+
|
|
441
|
+
export { type ActionConfirmationBlock, type ChatMessage, type ChatState, type ConsentSettings, CustomerHeroChat, type CustomerHeroChatConfig, DEFAULTS, type IdentifyPayload, type IdentityData, type MessageBlock, type MessageRating, type MessageSource, type MessageStatus, type PreChatField, type PreChatFieldKind, type PreChatFormConfig, type PreChatSubmission, type QuickRepliesBlock, type ResolvedConfig, SUPPORTED_LOCALES, ScreenshotCancelled, ScreenshotUnavailable, type StringOverrides, type SupportedLocale, type TranslateFn, type TranslationKey, type Translations, type TriggerAction, type TriggerConditionLeaf, type TriggerConditionNode, type TriggerDefinition, type TriggerFrequency, type TriggersRuntimeHandle, type VisitorContext, canCaptureScreenshot, captureScreenshot, createTranslator, detectLocale, evaluate, isRtlLocale, pickFire, resolveLocale, startTriggersRuntime };
|
package/dist/index.d.ts
CHANGED
|
@@ -123,6 +123,133 @@ interface IdentityData {
|
|
|
123
123
|
userHash?: string;
|
|
124
124
|
customProperties?: Record<string, string | number | boolean>;
|
|
125
125
|
}
|
|
126
|
+
type TriggerConditionNode = {
|
|
127
|
+
all: TriggerConditionNode[];
|
|
128
|
+
} | {
|
|
129
|
+
any: TriggerConditionNode[];
|
|
130
|
+
} | TriggerConditionLeaf;
|
|
131
|
+
type TriggerConditionLeaf = {
|
|
132
|
+
kind: "url_path";
|
|
133
|
+
op: "equals" | "contains" | "regex" | "starts_with";
|
|
134
|
+
value: string;
|
|
135
|
+
} | {
|
|
136
|
+
kind: "url_query";
|
|
137
|
+
key: string;
|
|
138
|
+
op: "equals" | "contains" | "exists";
|
|
139
|
+
value?: string;
|
|
140
|
+
} | {
|
|
141
|
+
kind: "referrer";
|
|
142
|
+
op: "contains" | "equals" | "regex";
|
|
143
|
+
value: string;
|
|
144
|
+
} | {
|
|
145
|
+
kind: "time_on_page";
|
|
146
|
+
seconds: number;
|
|
147
|
+
} | {
|
|
148
|
+
kind: "scroll_depth";
|
|
149
|
+
percent: number;
|
|
150
|
+
} | {
|
|
151
|
+
kind: "exit_intent";
|
|
152
|
+
} | {
|
|
153
|
+
kind: "device";
|
|
154
|
+
op: "equals";
|
|
155
|
+
value: "mobile" | "tablet" | "desktop";
|
|
156
|
+
} | {
|
|
157
|
+
kind: "browser_language";
|
|
158
|
+
op: "in";
|
|
159
|
+
values: string[];
|
|
160
|
+
} | {
|
|
161
|
+
kind: "visitor_trait";
|
|
162
|
+
key: string;
|
|
163
|
+
op: "equals" | "exists" | "gt" | "lt";
|
|
164
|
+
value?: string | number | boolean;
|
|
165
|
+
} | {
|
|
166
|
+
kind: "return_visit";
|
|
167
|
+
op: "gte" | "eq";
|
|
168
|
+
count: number;
|
|
169
|
+
};
|
|
170
|
+
type TriggerAction = {
|
|
171
|
+
kind: "open_widget";
|
|
172
|
+
} | {
|
|
173
|
+
kind: "send_message";
|
|
174
|
+
message: string;
|
|
175
|
+
} | {
|
|
176
|
+
kind: "show_form";
|
|
177
|
+
} | {
|
|
178
|
+
kind: "open_with_prefill";
|
|
179
|
+
prefill: string;
|
|
180
|
+
};
|
|
181
|
+
type TriggerFrequency = "once_ever" | "once_per_session" | "every_time";
|
|
182
|
+
interface TriggerDefinition {
|
|
183
|
+
id: string;
|
|
184
|
+
priority: number;
|
|
185
|
+
conditions: TriggerConditionNode;
|
|
186
|
+
action: TriggerAction;
|
|
187
|
+
frequency: TriggerFrequency;
|
|
188
|
+
}
|
|
189
|
+
type PreChatFieldKind = "name" | "email" | "phone" | "text" | "textarea" | "select" | "consent";
|
|
190
|
+
type PreChatField = {
|
|
191
|
+
kind: "name";
|
|
192
|
+
required?: boolean;
|
|
193
|
+
label?: string;
|
|
194
|
+
} | {
|
|
195
|
+
kind: "email";
|
|
196
|
+
required?: boolean;
|
|
197
|
+
label?: string;
|
|
198
|
+
validateMx?: boolean;
|
|
199
|
+
} | {
|
|
200
|
+
kind: "phone";
|
|
201
|
+
required?: boolean;
|
|
202
|
+
label?: string;
|
|
203
|
+
} | {
|
|
204
|
+
kind: "text";
|
|
205
|
+
key: string;
|
|
206
|
+
label: string;
|
|
207
|
+
required?: boolean;
|
|
208
|
+
maxLength?: number;
|
|
209
|
+
} | {
|
|
210
|
+
kind: "textarea";
|
|
211
|
+
key: string;
|
|
212
|
+
label: string;
|
|
213
|
+
required?: boolean;
|
|
214
|
+
maxLength?: number;
|
|
215
|
+
} | {
|
|
216
|
+
kind: "select";
|
|
217
|
+
key: string;
|
|
218
|
+
label: string;
|
|
219
|
+
options: Array<{
|
|
220
|
+
value: string;
|
|
221
|
+
label: string;
|
|
222
|
+
}>;
|
|
223
|
+
required?: boolean;
|
|
224
|
+
} | {
|
|
225
|
+
kind: "consent";
|
|
226
|
+
key: string;
|
|
227
|
+
label: string;
|
|
228
|
+
url?: string;
|
|
229
|
+
required: true;
|
|
230
|
+
};
|
|
231
|
+
interface PreChatFormConfig {
|
|
232
|
+
fields: PreChatField[];
|
|
233
|
+
title?: string | null;
|
|
234
|
+
description?: string | null;
|
|
235
|
+
submitLabel: string;
|
|
236
|
+
/** When true, an identified visitor (CustomerHero.identify already called)
|
|
237
|
+
* bypasses the form. */
|
|
238
|
+
skipForIdentified: boolean;
|
|
239
|
+
}
|
|
240
|
+
interface PreChatSubmission {
|
|
241
|
+
name?: string;
|
|
242
|
+
email?: string;
|
|
243
|
+
phone?: string;
|
|
244
|
+
/** Keyed answers from text/textarea/select/consent fields. */
|
|
245
|
+
properties?: Record<string, string | number | boolean>;
|
|
246
|
+
}
|
|
247
|
+
interface ConsentSettings {
|
|
248
|
+
/** When true, all condition kinds are evaluated. When false (default), only
|
|
249
|
+
* direct launcher clicks fire — URL/time/scroll/exit-intent/trait
|
|
250
|
+
* conditions stay dormant. */
|
|
251
|
+
analytics: boolean;
|
|
252
|
+
}
|
|
126
253
|
interface ChatState {
|
|
127
254
|
messages: ChatMessage[];
|
|
128
255
|
isOpen: boolean;
|
|
@@ -137,6 +264,26 @@ interface ChatState {
|
|
|
137
264
|
locale: SupportedLocale;
|
|
138
265
|
/** True when the active locale is right-to-left. */
|
|
139
266
|
isRtl: boolean;
|
|
267
|
+
/** Triggers loaded from the server config (active + in-window). */
|
|
268
|
+
triggers: TriggerDefinition[];
|
|
269
|
+
/** Pre-chat form configuration, if any. */
|
|
270
|
+
preChatForm: PreChatFormConfig | null;
|
|
271
|
+
/**
|
|
272
|
+
* True when the pre-chat form must be shown before the next chat turn.
|
|
273
|
+
* Flipped by trigger actions, by the first sendMessage when a form is
|
|
274
|
+
* configured and not yet submitted, and cleared on submit.
|
|
275
|
+
*/
|
|
276
|
+
preChatFormVisible: boolean;
|
|
277
|
+
/** Captured pre-chat submission, sent on the first chat call. */
|
|
278
|
+
preChatSubmission: PreChatSubmission | null;
|
|
279
|
+
/** Per-visitor consent. Until set explicitly, only direct launcher clicks
|
|
280
|
+
* trigger; behavioral conditions stay dormant. */
|
|
281
|
+
consent: ConsentSettings;
|
|
282
|
+
/** ID of the trigger attributed to the next conversation start, if any. */
|
|
283
|
+
pendingTriggerId: string | null;
|
|
284
|
+
/** When set, the host should preload this text into the input. Cleared
|
|
285
|
+
* once the host consumes it (or when the conversation starts). */
|
|
286
|
+
pendingPrefill: string | null;
|
|
140
287
|
}
|
|
141
288
|
|
|
142
289
|
type Listener = (state: ChatState) => void;
|
|
@@ -148,6 +295,10 @@ declare class CustomerHeroChat {
|
|
|
148
295
|
private identityData;
|
|
149
296
|
t: TranslateFn;
|
|
150
297
|
constructor(config: CustomerHeroChatConfig);
|
|
298
|
+
private triggersRuntime;
|
|
299
|
+
private preChatFormSubmitted;
|
|
300
|
+
private readStoredConsent;
|
|
301
|
+
private writeStoredConsent;
|
|
151
302
|
setLocale(tag: string): void;
|
|
152
303
|
private rebuildTranslator;
|
|
153
304
|
subscribe(listener: Listener): () => void;
|
|
@@ -179,6 +330,38 @@ declare class CustomerHeroChat {
|
|
|
179
330
|
open(): void;
|
|
180
331
|
close(): void;
|
|
181
332
|
reset(): void;
|
|
333
|
+
/** Update visitor consent. Until `analytics: true` is set, only direct
|
|
334
|
+
* launcher clicks fire — URL/time/scroll/exit-intent/trait conditions
|
|
335
|
+
* stay dormant. The setting is persisted in localStorage so revisits
|
|
336
|
+
* don't re-prompt. */
|
|
337
|
+
setConsent(consent: Partial<ConsentSettings>): void;
|
|
338
|
+
/** Set or update visitor traits used by trait-based conditions. The trait
|
|
339
|
+
* values are kept in memory (not persisted) so the integrator decides
|
|
340
|
+
* the source of truth. */
|
|
341
|
+
setTraits(traits: Record<string, string | number | boolean>): void;
|
|
342
|
+
/** Submit pre-chat form answers. Synthesizes a customer record server-side
|
|
343
|
+
* on the next sendMessage. Resumes any pending message that was deferred
|
|
344
|
+
* while the form was open. */
|
|
345
|
+
submitPreChatForm(submission: PreChatSubmission): Promise<void>;
|
|
346
|
+
/** Dismiss the pre-chat form without submitting. The form will reappear
|
|
347
|
+
* on the next sendMessage attempt — call `setConsent` to acknowledge a
|
|
348
|
+
* refusal, or `reset()` to clear pending state. */
|
|
349
|
+
cancelPreChatForm(): void;
|
|
350
|
+
/** Programmatically dispatch the action attached to a trigger. Used by
|
|
351
|
+
* integrators who want to act on a custom button, e.g. an exit-intent
|
|
352
|
+
* modal in their own UI. */
|
|
353
|
+
fireTrigger(triggerId: string): void;
|
|
354
|
+
private pendingMessageAfterPreChat;
|
|
355
|
+
private shouldShowPreChatForm;
|
|
356
|
+
private startTriggersRuntimeIfPossible;
|
|
357
|
+
private handleTriggerAction;
|
|
358
|
+
/** Read and clear the pending prefill (set by an `open_with_prefill`
|
|
359
|
+
* trigger). The host calls this once when mounting the input and seeds
|
|
360
|
+
* its controlled value with the result. */
|
|
361
|
+
consumePendingPrefill(): string | null;
|
|
362
|
+
/** Stop the triggers runtime and detach listeners. Safe to call multiple
|
|
363
|
+
* times; safe to call before the runtime started. */
|
|
364
|
+
destroy(): void;
|
|
182
365
|
identify(payload: IdentifyPayload): void;
|
|
183
366
|
}
|
|
184
367
|
|
|
@@ -202,4 +385,57 @@ declare class ScreenshotUnavailable extends Error {
|
|
|
202
385
|
declare function canCaptureScreenshot(): boolean;
|
|
203
386
|
declare function captureScreenshot(): Promise<Blob>;
|
|
204
387
|
|
|
205
|
-
|
|
388
|
+
interface VisitorContext {
|
|
389
|
+
url: string;
|
|
390
|
+
queryParams: Record<string, string>;
|
|
391
|
+
referrer: string;
|
|
392
|
+
language: string;
|
|
393
|
+
device: "mobile" | "tablet" | "desktop";
|
|
394
|
+
/** Time spent on the current page (in ms). Pauses while the tab is hidden. */
|
|
395
|
+
timeOnPageMs: number;
|
|
396
|
+
/** Scroll depth as a percentage of the document height (0..100). Tracked as
|
|
397
|
+
* a high-water mark so a quick scroll-up doesn't undo a `scroll_depth`
|
|
398
|
+
* match. */
|
|
399
|
+
scrollPercent: number;
|
|
400
|
+
/** True after the runtime detected a desktop-style exit-intent gesture or
|
|
401
|
+
* the mobile fallback (visibilitychange→hidden after a grace period). */
|
|
402
|
+
exitIntentSeen: boolean;
|
|
403
|
+
/** Number of distinct sessions this visitor has visited the page. */
|
|
404
|
+
returnVisitCount: number;
|
|
405
|
+
/** Custom traits set by the integrator via `setTraits` / `identify`. */
|
|
406
|
+
traits: Record<string, string | number | boolean>;
|
|
407
|
+
}
|
|
408
|
+
declare function evaluate(node: TriggerConditionNode, ctx: VisitorContext): boolean;
|
|
409
|
+
/** Walk `triggers` in priority order (low number = high priority) and return
|
|
410
|
+
* the first one that matches `ctx` and isn't already in `firedSet`. The
|
|
411
|
+
* caller decides what `firedSet` means — once_ever uses long-lived storage,
|
|
412
|
+
* once_per_session uses the in-memory or sessionStorage set, every_time
|
|
413
|
+
* always misses the set so it can re-fire. */
|
|
414
|
+
declare function pickFire(triggers: TriggerDefinition[], ctx: VisitorContext, firedSet: ReadonlySet<string>): TriggerDefinition | null;
|
|
415
|
+
|
|
416
|
+
interface TriggersRuntimeHandle {
|
|
417
|
+
/** Stop all watchers and remove listeners. */
|
|
418
|
+
stop(): void;
|
|
419
|
+
/** Force a re-evaluation (used after the integrator calls setTraits). */
|
|
420
|
+
reevaluate(): void;
|
|
421
|
+
/** Update visitor traits and re-evaluate. */
|
|
422
|
+
setTraits(traits: Record<string, string | number | boolean>): void;
|
|
423
|
+
/** Mark a trigger as fired (used after a direct launcher click acted on
|
|
424
|
+
* a trigger or when the runtime fired one itself). */
|
|
425
|
+
markFired(triggerId: string, frequency: TriggerFrequency): void;
|
|
426
|
+
}
|
|
427
|
+
interface StartTriggersRuntimeOptions {
|
|
428
|
+
chatbotId: string;
|
|
429
|
+
triggers: TriggerDefinition[];
|
|
430
|
+
/** Returns true when the runtime is allowed to fire a trigger. The client
|
|
431
|
+
* uses this to gate on consent — only direct launcher clicks fire until
|
|
432
|
+
* the integrator has called `setConsent({ analytics: true })`. */
|
|
433
|
+
isAllowedToFire(): boolean;
|
|
434
|
+
/** Called when a trigger is selected to fire. */
|
|
435
|
+
onFire(trigger: TriggerDefinition): void;
|
|
436
|
+
/** Optional initial traits seed. */
|
|
437
|
+
initialTraits?: Record<string, string | number | boolean>;
|
|
438
|
+
}
|
|
439
|
+
declare function startTriggersRuntime(options: StartTriggersRuntimeOptions): TriggersRuntimeHandle;
|
|
440
|
+
|
|
441
|
+
export { type ActionConfirmationBlock, type ChatMessage, type ChatState, type ConsentSettings, CustomerHeroChat, type CustomerHeroChatConfig, DEFAULTS, type IdentifyPayload, type IdentityData, type MessageBlock, type MessageRating, type MessageSource, type MessageStatus, type PreChatField, type PreChatFieldKind, type PreChatFormConfig, type PreChatSubmission, type QuickRepliesBlock, type ResolvedConfig, SUPPORTED_LOCALES, ScreenshotCancelled, ScreenshotUnavailable, type StringOverrides, type SupportedLocale, type TranslateFn, type TranslationKey, type Translations, type TriggerAction, type TriggerConditionLeaf, type TriggerConditionNode, type TriggerDefinition, type TriggerFrequency, type TriggersRuntimeHandle, type VisitorContext, canCaptureScreenshot, captureScreenshot, createTranslator, detectLocale, evaluate, isRtlLocale, pickFire, resolveLocale, startTriggersRuntime };
|