@uniformdev/context 20.34.3-alpha.70 → 20.35.1-alpha.188

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.
@@ -0,0 +1,1403 @@
1
+ import * as mitt from 'mitt';
2
+ import { Emitter } from 'mitt';
3
+
4
+ type Quirks = {
5
+ [key: string]: string;
6
+ };
7
+ type Tests = {
8
+ [key: string]: string;
9
+ };
10
+ type ScoreVector = {
11
+ [key: string]: number;
12
+ };
13
+ type Goals = {
14
+ [key: string]: boolean;
15
+ };
16
+ type EnrichmentData = {
17
+ /** Enrichment category name */
18
+ cat: string;
19
+ /** Enrichment key value */
20
+ key: string;
21
+ /** Strength value (amount of score added when viewing content) */
22
+ str: number;
23
+ };
24
+ type PersonalizeControlVariant = {
25
+ index: number;
26
+ control: boolean;
27
+ };
28
+ type PersonalizeVariants = {
29
+ [key: string]: PersonalizeControlVariant[];
30
+ };
31
+ /** An event that has occurred (i.e. an analytics track) which may trigger an Event signal */
32
+ type EventData = {
33
+ /** The event name that has been fired */
34
+ event: string;
35
+ };
36
+ type VisitorData = {
37
+ /**
38
+ * Quirk key-value data.
39
+ * NOTE: Context.quirks is more commonly correct if you need to read quirks data.
40
+ */
41
+ quirks: Quirks;
42
+ /** A/B test variant selections */
43
+ tests: Tests;
44
+ /**
45
+ * Personalization score data for the current session (merge with all time for totals)
46
+ * NOTE: Context.scores is more commonly correct to read scores instead of this value.
47
+ */
48
+ sessionScores: ScoreVector;
49
+ /**
50
+ * Personalization score data for all time (merge with session for totals)
51
+ * NOTE: Context.scores is more commonly correct to read scores instead of this value.
52
+ */
53
+ scores: ScoreVector;
54
+ /**
55
+ * Goals that this user has triggered.
56
+ */
57
+ goals?: Goals;
58
+ /**
59
+ * Whether consent has been given to store the visitor data
60
+ * If false or not set: visitor data is stored in memory and is lost if the browser refreshes
61
+ * If true: visitor data is stored in localStorage and any other transition storage if registered
62
+ */
63
+ consent?: boolean;
64
+ /**
65
+ * Whether the visitor has been assigned to the personalization control group -
66
+ * visitors who are not shown personalization. If this is true, all scores will be zeroed,
67
+ * and score updates will be ignored. This has no effect on quirks or tests.
68
+ *
69
+ * If this value is not set, a random roll will be performed to determine membership,
70
+ * based on the control group size.
71
+ */
72
+ controlGroup?: boolean;
73
+ /**
74
+ * Records of personalized variants that have been shown to the visitor and their control group status
75
+ */
76
+ personalizeVariants?: PersonalizeVariants;
77
+ };
78
+ declare const emptyVisitorData: () => VisitorData;
79
+ /**
80
+ * Canvas-specific data that should be managed separately from regular context updates
81
+ */
82
+ type CompositionMetadata = {
83
+ /** The composition ID always required, otherwise whole metadata should not be set */
84
+ compositionId: string;
85
+ /** The matched route from router endpoint. Same as matched project map node pathname */
86
+ matchedRoute?: string;
87
+ /** Dynamic inputs for the route */
88
+ dynamicInputs?: Record<string, string>;
89
+ };
90
+ /**
91
+ * Expresses a 'patch' to the Uniform Context state
92
+ */
93
+ type ContextState = {
94
+ cookies: Record<string, string | undefined>;
95
+ url?: URL;
96
+ quirks: Quirks;
97
+ enrichments: EnrichmentData[];
98
+ events: EventData[];
99
+ /**
100
+ * Metadata about the composition that is being rendered right now.
101
+ * if you have multiple compositions on the page, please set this one manually.
102
+ */
103
+ compositionMetadata?: CompositionMetadata;
104
+ };
105
+ type ContextStateUpdate = {
106
+ /** The new effective state of the visitor after this state update is applied */
107
+ state: Partial<ContextState>;
108
+ /** The last state of the visitor before this state update */
109
+ previousState: Partial<ContextState>;
110
+ /** The visitor we are updating */
111
+ visitor: VisitorData;
112
+ /** The visitor's scores before this state update */
113
+ scores: ScoreVector;
114
+ };
115
+ type GoalStateUpdate = {
116
+ scores: ScoreVector | undefined;
117
+ quirks: Quirks | undefined;
118
+ };
119
+
120
+ type StorageCommand<TID extends string = string, TData = unknown> = {
121
+ type: TID;
122
+ data: TData;
123
+ };
124
+ /** Commands that can be issued to alter the storage of Uniform Context data */
125
+ type StorageCommands = ModifyScoreCommand | ModifySessionScoreCommand | SetConsentCommand | SetQuirkCommand | SetTestCommand | IdentifyCommand | SetControlGroupCommand | SetPersonalizeVariantControlCommand | SetGoalCommand;
126
+ /**
127
+ * Converts the goal specified.
128
+ */
129
+ type SetGoalCommand = StorageCommand<'setgoal', {
130
+ goal: string;
131
+ }>;
132
+ /**
133
+ * Changes the visitor's permanent score for a given dimension
134
+ */
135
+ type ModifyScoreCommand = StorageCommand<'modscore', {
136
+ dimension: string;
137
+ delta: number;
138
+ }>;
139
+ /**
140
+ * Changes the visitor's session (time-based) score for a given dimension
141
+ */
142
+ type ModifySessionScoreCommand = StorageCommand<'modscoreS', {
143
+ dimension: string;
144
+ delta: number;
145
+ }>;
146
+ /**
147
+ * Changes the visitor's storage consent setting.
148
+ * Setting consent to false will trigger deletion of any stored data for the visitor.
149
+ * Scores are still collected in-memory when consent is false; just not persisted.
150
+ */
151
+ type SetConsentCommand = StorageCommand<'consent', boolean>;
152
+ /** Sets a permanent quirk key and value for the visitor */
153
+ type SetQuirkCommand = StorageCommand<'setquirk', {
154
+ key: string;
155
+ value: string;
156
+ }>;
157
+ /** Sets a specific variant as being this visitor's variant on an A/B test */
158
+ type SetTestCommand = StorageCommand<'settest', {
159
+ test: string;
160
+ variant: string;
161
+ }>;
162
+ /**
163
+ * Identifies the visitor as being a specific unique identifier.
164
+ * NOTE: this only has an effect when using an external cross-device transition storage system.
165
+ * NOTE: you cannot read the identified visitor ID back from the storage system once it is set.
166
+ */
167
+ type IdentifyCommand = StorageCommand<'identify', {
168
+ identity: string;
169
+ }>;
170
+ /**
171
+ * Sets whether the current visitor is in the personalization control group
172
+ * (Will not be exposed to personalization or gather classification data; WILL see A/B tests)
173
+ * In most cases this should not be sent as the membership is computed automatically for visitors;
174
+ * this command is intended mostly for diagnostics and testing purposes.
175
+ */
176
+ type SetControlGroupCommand = StorageCommand<'setcontrol', boolean>;
177
+ type SetPersonalizeVariantControlCommand = StorageCommand<'setpersonalizecontrol', {
178
+ personlizationName: string;
179
+ index: number;
180
+ control: boolean;
181
+ }>;
182
+ declare const areCommandsEqual: (a: StorageCommands, b: StorageCommands) => boolean;
183
+
184
+ type TransitionDataStoreOptions = {
185
+ initialData?: Partial<VisitorData>;
186
+ };
187
+ type ServerToClientTransitionState = Pick<Partial<VisitorData>, 'quirks' | 'tests' | 'personalizeVariants'> & {
188
+ /**
189
+ * Server Score Vector - the resultant scores _on the server side_ after the server/edge render completes
190
+ * Note that the client side does not trust these scores; they are only used until it's done with initial
191
+ * recomputation.
192
+ */
193
+ ssv?: ScoreVector;
194
+ /**
195
+ * Storage commands that the server
196
+ */
197
+ commands?: StorageCommands[];
198
+ /**
199
+ * Composition metadata from the server side
200
+ */
201
+ compositionMetadata?: CompositionMetadata;
202
+ };
203
+ declare const SERVER_STATE_ID = "__UNIFORM_DATA__";
204
+ type TransitionDataStoreEvents = {
205
+ /**
206
+ * Fired when the data is updated asynchronously
207
+ * (i.e. a promise resolves with new data from a backend)
208
+ *
209
+ * NOT fired for synchronous updates (e.g. calling updateData()), unless this also results in an async update of the data afterwards.
210
+ * NOT fired if an asynchronous update does not result in any change compared to the last known data.
211
+ */
212
+ dataUpdatedAsync: Partial<VisitorData>;
213
+ };
214
+ declare abstract class TransitionDataStore {
215
+ #private;
216
+ constructor({ initialData }: TransitionDataStoreOptions);
217
+ get data(): Partial<VisitorData> | undefined;
218
+ get initialData(): Partial<VisitorData> | undefined;
219
+ /**
220
+ * Subscribe to events from the transition storage
221
+ */
222
+ readonly events: {
223
+ on: {
224
+ <Key extends "dataUpdatedAsync">(type: Key, handler: mitt.Handler<TransitionDataStoreEvents[Key]>): void;
225
+ (type: "*", handler: mitt.WildcardHandler<TransitionDataStoreEvents>): void;
226
+ };
227
+ off: {
228
+ <Key extends "dataUpdatedAsync">(type: Key, handler?: mitt.Handler<TransitionDataStoreEvents[Key]> | undefined): void;
229
+ (type: "*", handler: mitt.WildcardHandler<TransitionDataStoreEvents>): void;
230
+ };
231
+ };
232
+ /**
233
+ * Updates data in the transition storage.
234
+ * @param commands Commands to execute against existing stored value (event based stores)
235
+ * @param computedValue Pre-computed new value against existing value (object based stores)
236
+ * @returns Resolved promise when the data has been updated
237
+ */
238
+ updateData(commands: StorageCommands[], computedValue: VisitorData): Promise<void>;
239
+ /**
240
+ * Deletes a visitor's stored data, forgetting them.
241
+ * @param fromAllDevices - false: logout from this device ID. true: forget all data about the visitor and their identity.
242
+ */
243
+ delete(fromAllDevices?: boolean): Promise<void>;
244
+ /**
245
+ * Deletes a visitor's stored data, forgetting them.
246
+ * Important: do not emit any async score update events from this function.
247
+ * @param fromAllDevices - false: logout from this device ID. true: forget all data about the visitor and their identity.
248
+ */
249
+ abstract handleDelete(fromAllDevices?: boolean): Promise<void>;
250
+ /**
251
+ * Updates visitor data in the transition store.
252
+ *
253
+ * NOTE: The updated data is optimistically stored in TransitionDataStore automatically,
254
+ * so unless the updated data is _changed_ by the backend data store, there is no need
255
+ * to emit async score changed events when the visitor data is done updating.
256
+ */
257
+ abstract handleUpdateData(commands: StorageCommands[], computedValue: VisitorData): Promise<void>;
258
+ protected signalAsyncDataUpdate(newScores: Partial<VisitorData>): void;
259
+ /**
260
+ * When we load on the client side after a server side rendering has occurred (server to client transition),
261
+ * we can have a page script (ID: __UNIFORM_DATA__) that contains the computed visitor data from the SSR/edge render.
262
+ * This data is injected into the first render to allow score syncing and the server to request commands be applied
263
+ * to the client side data store.
264
+ */
265
+ getClientTransitionState(): ServerToClientTransitionState | undefined;
266
+ }
267
+
268
+ type DecayOptions = {
269
+ now: number;
270
+ lastUpd: number | undefined;
271
+ scores: ScoreVector;
272
+ sessionScores: ScoreVector;
273
+ onLogMessage?: (message: LogMessage) => void;
274
+ };
275
+ /**
276
+ * Computes decay of visitor scores over time.
277
+ * NOTE: it is expected that this function mutates the incoming score vectors,
278
+ * if it needs to apply score decay. The data store ensures immutability already.
279
+ *
280
+ * @returns true if any decay was applied, false otherwise
281
+ */
282
+ type DecayFunction = (options: DecayOptions) => boolean;
283
+
284
+ type VisitorDataStoreOptions = {
285
+ /** Transition storage used to transfer server or edge side execution state to the client. Unused for client side only. */
286
+ transitionStore?: TransitionDataStore;
287
+ /** Duration of a 'visit' measured by this number of milliseconds without performing any updates */
288
+ visitLifespan?: number;
289
+ /** Personalization manifest data. If set, the data store will automatically apply score caps in the manifest data. */
290
+ manifest?: ManifestInstance;
291
+ /** Allows decaying of scores over time based on time between visits. Default: no decay */
292
+ decay?: DecayFunction;
293
+ /**
294
+ * Sets the default value of storage consent for new unknown visitors.
295
+ * If storage consent is not given, only in-memory data will be stored which is lost when the browser leaves the page.
296
+ * @default false - consent is not given for new visitors until they explicitly give it with an update command
297
+ */
298
+ defaultConsent?: boolean;
299
+ /**
300
+ * Function called when server-to-client transfer state is loaded and contains server-side computed scores.
301
+ * These scores are used as a temporary shim for the current scores on the client side, until score computation
302
+ * is completed the first time (which occurs when the current url is fed into the Context).
303
+ *
304
+ * Because the feed of the URL may be marginally delayed (for example in React it's in an effect so it's a second render),
305
+ * one render might be done with _no_ scores unless we dropped the server scores in temporarily, resulting in a flash of unpersonalized content.
306
+ */
307
+ onServerTransitionReceived?: (state: ServerToClientTransitionState) => void;
308
+ /** Called when a log message is emitted from the data store */
309
+ onLogMessage?: (message: LogMessage) => void;
310
+ /**
311
+ * Optionally specify a prefix for all storage keys.
312
+ * Only required if using multiple Context instances on the same domain and need to separate them.
313
+ */
314
+ partitionKey?: string;
315
+ };
316
+ type VisitorDataStoreEvents = {
317
+ /**
318
+ * Fired when the stored data is updated.
319
+ * This is fired for any update, whether from integrated or transition storage.
320
+ * The event is NOT fired if an update does not result in any score changes.
321
+ */
322
+ scoresUpdated: Pick<VisitorData, 'scores' | 'sessionScores'>;
323
+ /**
324
+ * Fired when stored quirks are updated.
325
+ * This is fired for any update, whether from integrated or transition storage.
326
+ * The event is NOT fired if an update does not result in any quirk changes.
327
+ */
328
+ quirksUpdated: Pick<VisitorData, 'quirks'>;
329
+ /**
330
+ * Fired when test variant selection is updated.
331
+ */
332
+ testsUpdated: Pick<VisitorData, 'tests'>;
333
+ /**
334
+ * Fired when storage consent is changed
335
+ */
336
+ consentUpdated: Pick<VisitorData, 'consent'>;
337
+ /**
338
+ * Fired when visitor control group membership is changed
339
+ */
340
+ controlGroupUpdated: Pick<VisitorData, 'controlGroup'>;
341
+ /**
342
+ * Fired when a goal is converted
343
+ */
344
+ goalConverted: {
345
+ goalId: string;
346
+ };
347
+ /** Fired when storage update commands are done executing */
348
+ commandsExecuted: StorageCommands[];
349
+ };
350
+ declare class VisitorDataStore {
351
+ #private;
352
+ constructor(options: VisitorDataStoreOptions);
353
+ /** Gets the current visitor data. This property is always up to date. */
354
+ get data(): VisitorData;
355
+ get decayEnabled(): boolean;
356
+ get options(): VisitorDataStoreOptions;
357
+ /**
358
+ * Subscribe to events from storage
359
+ */
360
+ readonly events: {
361
+ on: {
362
+ <Key extends keyof VisitorDataStoreEvents>(type: Key, handler: mitt.Handler<VisitorDataStoreEvents[Key]>): void;
363
+ (type: "*", handler: mitt.WildcardHandler<VisitorDataStoreEvents>): void;
364
+ };
365
+ off: {
366
+ <Key extends keyof VisitorDataStoreEvents>(type: Key, handler?: mitt.Handler<VisitorDataStoreEvents[Key]> | undefined): void;
367
+ (type: "*", handler: mitt.WildcardHandler<VisitorDataStoreEvents>): void;
368
+ };
369
+ };
370
+ /** Push data update command(s) into the visitor data */
371
+ updateData(commands: StorageCommands[]): Promise<void>;
372
+ /**
373
+ * Deletes visitor data (forgetting them)
374
+ * In most cases you should use forget() on the Context instead of this function, which also clears the Context state.
375
+ * @param fromAllDevices for an identified user, whether to delete all their data (for the entire account) - true, or data for this device (sign out) - false
376
+ */
377
+ delete(fromAllDevices: boolean): Promise<void>;
378
+ }
379
+
380
+ declare class ManifestInstance {
381
+ #private;
382
+ readonly data: ManifestV2;
383
+ constructor({ manifest, evaluator, onLogMessage, }: {
384
+ manifest: ManifestV2;
385
+ evaluator?: GroupCriteriaEvaluator;
386
+ onLogMessage?: (message: LogMessage) => void;
387
+ });
388
+ rollForControlGroup(): boolean;
389
+ getTest(name: string): TestDefinition | undefined;
390
+ computeSignals(update: ContextStateUpdate): StorageCommands[];
391
+ computeGoals(data: GoalStateUpdate): StorageCommands[];
392
+ /**
393
+ * Computes aggregated scores based on other dimensions
394
+ */
395
+ computeAggregateDimensions(primitiveScores: ScoreVector): ScoreVector;
396
+ getDimensionByKey(scoreKey: string): EnrichmentCategory | Signal | undefined;
397
+ getAggregateDimensionByKey(scoreKey: string): AggregateDimension | undefined;
398
+ }
399
+
400
+ interface paths {
401
+ "/api/v2/manifest": {
402
+ parameters: {
403
+ query?: never;
404
+ header?: never;
405
+ path?: never;
406
+ cookie?: never;
407
+ };
408
+ /** @description Fetches the optimization Manifest for a given project.
409
+ * If no manifest has ever been published, and an API key is used that has preview manifest permissions then the current preview manifest will be returned (in delivery format).
410
+ * */
411
+ get: {
412
+ parameters: {
413
+ query: {
414
+ preview?: boolean;
415
+ projectId: string;
416
+ };
417
+ header?: never;
418
+ path?: never;
419
+ cookie?: never;
420
+ };
421
+ requestBody?: never;
422
+ responses: {
423
+ /** @description OK */
424
+ 200: {
425
+ headers: {
426
+ [name: string]: unknown;
427
+ };
428
+ content: {
429
+ "application/json": components["schemas"]["ManifestV2"];
430
+ };
431
+ };
432
+ 400: components["responses"]["BadRequestError"];
433
+ 401: components["responses"]["UnauthorizedError"];
434
+ 403: components["responses"]["ForbiddenError"];
435
+ /** @description No manifest has ever been published, and the API key does not have preview permissions */
436
+ 404: {
437
+ headers: {
438
+ [name: string]: unknown;
439
+ };
440
+ content: {
441
+ "text/plain": string;
442
+ };
443
+ };
444
+ 429: components["responses"]["RateLimitError"];
445
+ 500: components["responses"]["InternalServerError"];
446
+ };
447
+ };
448
+ put?: never;
449
+ post?: never;
450
+ delete?: never;
451
+ /** @description Handles preflight requests. This endpoint allows CORS. */
452
+ options: {
453
+ parameters: {
454
+ query?: never;
455
+ header?: never;
456
+ path?: never;
457
+ cookie?: never;
458
+ };
459
+ requestBody?: never;
460
+ responses: {
461
+ /** @description OK */
462
+ 204: {
463
+ headers: {
464
+ [name: string]: unknown;
465
+ };
466
+ content?: never;
467
+ };
468
+ };
469
+ };
470
+ head?: never;
471
+ patch?: never;
472
+ trace?: never;
473
+ };
474
+ }
475
+ interface components {
476
+ schemas: {
477
+ ManifestV2: {
478
+ project: {
479
+ /**
480
+ * Format: uuid
481
+ * @description is not present unless getting a preview manifest
482
+ */
483
+ id?: string;
484
+ /** @description is not present unless getting a preview manifest */
485
+ name?: string;
486
+ /** @description is not present unless getting a preview manifest */
487
+ ui_version?: number;
488
+ pz?: components["schemas"]["PersonalizationManifest"];
489
+ /** @description A/B test settings */
490
+ test?: {
491
+ [key: string]: components["schemas"]["Test"];
492
+ };
493
+ };
494
+ };
495
+ PersonalizationManifest: {
496
+ /** @description Map of all signals defined for personalization criteria */
497
+ sig?: {
498
+ [key: string]: components["schemas"]["Signal"];
499
+ };
500
+ /** @description Map of all enrichment categories defined for personalization criteria */
501
+ enr?: {
502
+ [key: string]: components["schemas"]["EnrichmentCategory"];
503
+ };
504
+ /** @description Map of all aggregate dimensions (intents or audiences) defined for personalization criteria */
505
+ agg?: {
506
+ [key: string]: components["schemas"]["AggregateDimension"];
507
+ };
508
+ /** @description Percentage of visitors that will be used as a personalization control group (not shown any personalization) */
509
+ control?: number;
510
+ };
511
+ SignalCriteriaGroup: {
512
+ /**
513
+ * @description Criteria type (Group of other criteria)
514
+ * @enum {string}
515
+ */
516
+ type: "G";
517
+ /**
518
+ * @description The logical operator to apply to the criteria groups
519
+ * & = AND
520
+ * | = OR
521
+ *
522
+ * Default is `&` if unspecified
523
+ *
524
+ * @enum {string}
525
+ */
526
+ op?: "&" | "|";
527
+ /** @description The criteria clauses that make up this grouping of criteria */
528
+ clauses: (components["schemas"]["SignalCriteriaGroup"] | components["schemas"]["SignalCriteria"])[];
529
+ };
530
+ /** @description Describes a match expression on a string */
531
+ StringMatch: {
532
+ /** @description The right-hand side of the match expression */
533
+ rhs: string;
534
+ /**
535
+ * @description The match operator
536
+ * '=' = exact match
537
+ * '~' = contains match
538
+ * '//' = regular expression match
539
+ *
540
+ * Any of the above can be prefixed with '!' to invert the match (i.e. != for 'not an exact match')
541
+ *
542
+ * @enum {string}
543
+ */
544
+ op: "=" | "~" | "//" | "!=" | "!~" | "!//";
545
+ /** @description The case sensitivity of the match. Defaults to false if unspecified */
546
+ cs?: boolean;
547
+ } | {
548
+ /**
549
+ * @description The type of match to perform
550
+ * '*' = exists with any value
551
+ * '!*' = does not exist
552
+ *
553
+ * @enum {string}
554
+ */
555
+ op: "*" | "!*";
556
+ };
557
+ /** @description Matches a web cookie value */
558
+ CookieCriteria: {
559
+ /** @enum {string} */
560
+ type: "CK";
561
+ /** @description The name of the cookie to match */
562
+ cookieName: string;
563
+ /** @description The value to match the cookie against */
564
+ match: components["schemas"]["StringMatch"];
565
+ };
566
+ /** @description Matches a URL query string parameter value */
567
+ QueryStringCriteria: {
568
+ /** @enum {string} */
569
+ type: "QS";
570
+ /** @description The name of the query string parameter to match */
571
+ queryName: string;
572
+ /** @description The value to match the query string parameter against */
573
+ match: components["schemas"]["StringMatch"];
574
+ };
575
+ /** @description Matches a visitor quirk key and value */
576
+ QuirkCriteria: {
577
+ /** @enum {string} */
578
+ type: "QK";
579
+ /** @description The name of the quirk key to match */
580
+ key: string;
581
+ /** @description The quirk value to match against */
582
+ match: components["schemas"]["StringMatch"];
583
+ };
584
+ /** @description Matches an analytics event name being fired */
585
+ EventCriteria: {
586
+ /** @enum {string} */
587
+ type: "EVT";
588
+ /** @description How to match the event name */
589
+ event: components["schemas"]["StringMatch"];
590
+ };
591
+ /** @description Matches the current page's absolute path (i.e. /path/to/page.html)
592
+ * Does not include the query string or protocol and hostname (i.e. NOT https://foo.com/path/to/page.html?query=something)
593
+ * */
594
+ CurrentPageCriteria: {
595
+ /** @enum {string} */
596
+ type: "PV";
597
+ /** @description The page/route path to match as a page that has been visited */
598
+ path: components["schemas"]["StringMatch"];
599
+ };
600
+ /** @description Describes a match expression on a number */
601
+ NumberMatch: {
602
+ /** @description The right-hand side of the match expression */
603
+ rhs: number;
604
+ /**
605
+ * @description The type of match to perform
606
+ * '=' = exact match
607
+ * '!=' = not an exact match
608
+ * '<' = less than match expression
609
+ * '>' = greater than match expression
610
+ *
611
+ * @enum {string}
612
+ */
613
+ op: "=" | "<" | ">" | "!=";
614
+ };
615
+ PageViewCountCriteria: {
616
+ /** @enum {string} */
617
+ type: "PVC";
618
+ /** @description The expression to match the page view count against */
619
+ match: components["schemas"]["NumberMatch"];
620
+ };
621
+ SignalCriteria: components["schemas"]["CookieCriteria"] | components["schemas"]["QueryStringCriteria"] | components["schemas"]["QuirkCriteria"] | components["schemas"]["EventCriteria"] | components["schemas"]["CurrentPageCriteria"] | components["schemas"]["PageViewCountCriteria"];
622
+ RootSignalCriteriaGroup: {
623
+ /**
624
+ * @description Criteria type (Group of other criteria)
625
+ * @enum {string}
626
+ */
627
+ type: "G";
628
+ /**
629
+ * @description The logical operator to apply to the criteria groups
630
+ * & = AND
631
+ * | = OR
632
+ *
633
+ * Default is `&` if unspecified
634
+ *
635
+ * @default &
636
+ * @enum {string}
637
+ */
638
+ op?: "&" | "|";
639
+ /** @description The criteria clauses that make up this grouping of criteria */
640
+ clauses: (components["schemas"]["SignalCriteriaGroup"] | components["schemas"]["SignalCriteria"])[];
641
+ };
642
+ Conversion: {
643
+ /**
644
+ * @description The frequency of the conversion event
645
+ * @enum {string}
646
+ */
647
+ freq: "O";
648
+ };
649
+ Signal: {
650
+ /** @description The signal strength per activation (each time its criteria are true, this score is added) */
651
+ str: number;
652
+ /** @description The maximum visitor score allowed for this signal */
653
+ cap: number;
654
+ /**
655
+ * @description How long the signal's score should persist
656
+ * 's' = current session (expires after a period of inactivity)
657
+ * 'p' = permanent (expires as far in the future as possible, may be limited by browser security settings)
658
+ * 't' = transient (score tracks the current state of the criteria every time scores are updated)
659
+ *
660
+ * @enum {string}
661
+ */
662
+ dur: "s" | "p" | "t";
663
+ crit: components["schemas"]["RootSignalCriteriaGroup"];
664
+ conversion?: components["schemas"]["Conversion"] | null;
665
+ };
666
+ EnrichmentCategory: {
667
+ /** @description The maximum visitor score allowed for enrichment keys in this category */
668
+ cap: number;
669
+ };
670
+ /** @description Defines an input dimension to an aggregate dimension */
671
+ AggregateDimensionInput: {
672
+ /** @description Dimension name to reference as an input.
673
+ * For enrichment inputs, use CATEGORY_KEY as the dimension.
674
+ * Enrichments, signals, and other aggregate dimensions may be referenced.
675
+ *
676
+ * Note that creating a cycle of aggregate dimensions is allowed, however
677
+ * the final score will _ignore_ the cycled aggregate dimension in the result.
678
+ * This can be used to create mutually exclusive aggregates
679
+ * */
680
+ dim: string;
681
+ /**
682
+ * @description The sign of the input dimension controls how it affects the aggregate dimension's final score.
683
+ *
684
+ * '+' = add to the final score
685
+ * '-' = subtract from the final score
686
+ * 'c' = clear the final score (if the input dimension has any score at all, this aggregate will have no score regardless of other inputs)
687
+ *
688
+ * Default if unspecified: '+'
689
+ *
690
+ * @default +
691
+ * @enum {string}
692
+ */
693
+ sign?: "+" | "-" | "c";
694
+ };
695
+ /** @description Defines an aggregate dimension that is a grouping of other dimensions' scores; an intent or audience */
696
+ AggregateDimension: {
697
+ /** @description Input dimensions to the aggregate dimension */
698
+ inputs: components["schemas"]["AggregateDimensionInput"][];
699
+ };
700
+ Test: {
701
+ /** @description Winning variation ID - if set, the test will not run and this variation is shown to all visitors (the test is closed) */
702
+ wv?: string;
703
+ };
704
+ Error: {
705
+ /** @description Error message(s) that occurred while processing the request */
706
+ errorMessage?: string[] | string;
707
+ };
708
+ };
709
+ responses: {
710
+ /** @description Request input validation failed */
711
+ BadRequestError: {
712
+ headers: {
713
+ [name: string]: unknown;
714
+ };
715
+ content: {
716
+ "application/json": components["schemas"]["Error"];
717
+ };
718
+ };
719
+ /** @description API key or token was not valid */
720
+ UnauthorizedError: {
721
+ headers: {
722
+ [name: string]: unknown;
723
+ };
724
+ content: {
725
+ "application/json": components["schemas"]["Error"];
726
+ };
727
+ };
728
+ /** @description Permission was denied */
729
+ ForbiddenError: {
730
+ headers: {
731
+ [name: string]: unknown;
732
+ };
733
+ content: {
734
+ "application/json": components["schemas"]["Error"];
735
+ };
736
+ };
737
+ /** @description Too many requests in allowed time period */
738
+ RateLimitError: {
739
+ headers: {
740
+ [name: string]: unknown;
741
+ };
742
+ content?: never;
743
+ };
744
+ /** @description Execution error occurred */
745
+ InternalServerError: {
746
+ headers: {
747
+ [name: string]: unknown;
748
+ };
749
+ content?: never;
750
+ };
751
+ };
752
+ parameters: never;
753
+ requestBodies: never;
754
+ headers: never;
755
+ pathItems: never;
756
+ }
757
+
758
+ type ManifestV2 = components['schemas']['ManifestV2'];
759
+ type PersonalizationManifest = components['schemas']['PersonalizationManifest'];
760
+ type Signal = components['schemas']['Signal'];
761
+ type SignalCriteriaGroup = components['schemas']['SignalCriteriaGroup'];
762
+ type SignalCriteria = components['schemas']['SignalCriteria'];
763
+ type EnrichmentCategory = components['schemas']['EnrichmentCategory'];
764
+ type StringMatch = components['schemas']['StringMatch'];
765
+ type NumberMatch = components['schemas']['NumberMatch'];
766
+ type TestDefinition = components['schemas']['Test'];
767
+ type AggregateDimension = components['schemas']['AggregateDimension'];
768
+ type AggregateDimensionInput = components['schemas']['AggregateDimensionInput'];
769
+
770
+ declare class GroupCriteriaEvaluator {
771
+ #private;
772
+ constructor(criteriaEvaluators: Record<string, CriteriaEvaluator>);
773
+ evaluate(update: ContextStateUpdate, crit: SignalCriteriaGroup, commands: StorageCommands[], signal: SignalData, onLogMessage?: (message: LogMessage) => void): CriteriaEvaluatorResult;
774
+ }
775
+
776
+ /**
777
+ * The result of evaluating a signal criteria.
778
+ */
779
+ type CriteriaEvaluatorResult = {
780
+ /** Whether the criteria evaluated to true or not */
781
+ result: boolean;
782
+ /**
783
+ * Whether the value of the criteria changed from the previous state
784
+ * If ALL criteria on a signal have NOT changed, the signal is skipped
785
+ * and its score is left alone.
786
+ */
787
+ changed: boolean;
788
+ };
789
+ type CriteriaEvaluatorParameters = {
790
+ /** The update being made to the Context state */
791
+ update: ContextStateUpdate;
792
+ /** Current criteria to evaluate the update against */
793
+ criteria: SignalCriteria;
794
+ /**
795
+ * The storage commands that will be executed by this update.
796
+ * If the evaluation requires custom commands, push them into this parameter.
797
+ * NOTE: needing to use this is very rare and should be avoided if possible.
798
+ */
799
+ commands: StorageCommands[];
800
+ /** The parent signal containing the criteria we are evaluating */
801
+ signal: SignalData;
802
+ /** Function to emit log notices to the Context log */
803
+ onLogMessage?: (message: LogMessage) => void;
804
+ };
805
+ type SignalData = Signal & {
806
+ id: string;
807
+ };
808
+ /**
809
+ * A type that evaluates a signal criteria type and
810
+ * decides if it matches the current Context state or not.
811
+ */
812
+ type CriteriaEvaluator = ((parameters: CriteriaEvaluatorParameters) => CriteriaEvaluatorResult) & {
813
+ /** If true the criteria will always execute even if a short-circuit would normally skip it */
814
+ alwaysExecute?: boolean;
815
+ };
816
+
817
+ /** Defines all error codes and their parameter(s) */
818
+ type LogMessages = {
819
+ /** Context constructed */
820
+ 1: MessageFunc;
821
+ /** Context received data update */
822
+ 2: MessageFunc<Partial<Omit<ContextState, 'url'> & {
823
+ url: string;
824
+ }>>;
825
+ /** Context emitted new score vector */
826
+ 3: MessageFunc<ScoreVector>;
827
+ /** Context emitted updated quirks */
828
+ 4: MessageFunc<Quirks>;
829
+ /** Tried to set enrichment category that did not exist */
830
+ 5: MessageFunc<EnrichmentData>;
831
+ /** Storage received update commands */
832
+ 101: MessageFunc<StorageCommands[]>;
833
+ /** Storage data was updated */
834
+ 102: MessageFunc<VisitorData>;
835
+ /** Storage data was deleted bool: fromAllDevices */
836
+ 103: MessageFunc<boolean>;
837
+ /** Visitor was assigned or removed from control group */
838
+ 104: MessageFunc<boolean>;
839
+ /** Storage score was truncated to its cap */
840
+ 110: MessageFunc<{
841
+ dim: string;
842
+ score: number;
843
+ cap: number;
844
+ }>;
845
+ /** Storage visitor data expired and was cleared */
846
+ 120: MessageFunc;
847
+ /** Server to client transition score data was loaded */
848
+ 130: MessageFunc<ServerToClientTransitionState>;
849
+ /** Server to client transition data was discarded */
850
+ 131: MessageFunc;
851
+ /** Decay function executed */
852
+ 140: MessageFunc<string>;
853
+ /** Signals evaluation beginning */
854
+ 200: MessageFunc;
855
+ /** Evaluation of a specific signal beginning */
856
+ 201: MessageFunc<SignalData>;
857
+ /** Evaluation of a group beginning */
858
+ 202: MessageFunc<SignalCriteriaGroup>;
859
+ 203: MessageFunc<{
860
+ criteria: SignalCriteria;
861
+ result: CriteriaEvaluatorResult;
862
+ explanation: string;
863
+ }>;
864
+ /** Result of evaluating a criteria group */
865
+ 204: MessageFunc<CriteriaEvaluatorResult>;
866
+ /** Personalization placement executing */
867
+ 300: MessageFunc<{
868
+ name: string;
869
+ take?: number;
870
+ }>;
871
+ /** Personalization placement testing variation */
872
+ 301: MessageFunc<{
873
+ id: string;
874
+ op?: string;
875
+ }>;
876
+ /** Processed a personalization criteria */
877
+ 302: MessageFunc<{
878
+ matched: boolean;
879
+ description: string;
880
+ }>;
881
+ /** Final result for a personalized variation */
882
+ 303: MessageFunc<boolean>;
883
+ /** Personalization algorithm not found */
884
+ 304: MessageFunc<{
885
+ algorithm: string;
886
+ }>;
887
+ /** A/B test placement executing */
888
+ 400: MessageFunc<string>;
889
+ /** A/B Test definition did not exist */
890
+ 401: MessageFunc<string>;
891
+ /** Previously shown test variant no longer in variant data */
892
+ 402: MessageFunc<{
893
+ missingVariant: string;
894
+ variants: string[];
895
+ }>;
896
+ /** Selected a new A/B test variation */
897
+ 403: MessageFunc<string>;
898
+ /** Displaying A/B test variation */
899
+ 404: MessageFunc<string>;
900
+ /** gtag was not present on the page to emit events to */
901
+ 700: MessageFunc;
902
+ /** Enabled gtag event signal redirection */
903
+ 701: MessageFunc;
904
+ };
905
+
906
+ type Severity = 'debug' | 'info' | 'warn' | 'error';
907
+ type MessageCategory = 'context' | 'storage' | 'testing' | 'personalization' | 'gtag' | 'signals';
908
+ type OutputSeverity = Severity | 'none';
909
+ type MessageFunc<TArg = void> = (arg: TArg) => [
910
+ /** Category of the message */
911
+ MessageCategory,
912
+ /** Log message text */
913
+ string,
914
+ /** Log message */
915
+ ...unknown[]
916
+ ];
917
+ type LogMessage = LogMessageSingle | LogMessageGroup;
918
+ type LogMessageSingle<TID extends keyof LogMessages = keyof LogMessages> = [
919
+ severity: Severity,
920
+ id: TID,
921
+ ...args: Parameters<LogMessages[TID]>
922
+ ];
923
+ type LogMessageGroup<TID extends keyof LogMessages = keyof LogMessages> = [severity: Severity, id: TID, group: 'GROUP', ...args: Parameters<LogMessages[TID]>] | [severity: Severity, id: TID, group: 'ENDGROUP'];
924
+ type LogDrain = (message: LogMessage) => void;
925
+
926
+ /** Data for a personalization variation using the top-down criteria selection algorithm */
927
+ interface VariantMatchCriteria extends VariationMatchMetadata {
928
+ /**
929
+ * Operation for match criteria
930
+ *
931
+ * @defaultValue `&`
932
+ */
933
+ op?: '&' | '|';
934
+ crit: Array<DimensionMatch | QuirkMatch>;
935
+ /**
936
+ * Control group percentage for the variant.
937
+ */
938
+ control?: number;
939
+ }
940
+ /** Data for a personalization variation using the TODO selection algorithm */
941
+ interface VariationMatchDimensionCriteria extends VariationMatchMetadata {
942
+ /** The dimension this content is relevant to */
943
+ dim: string | undefined;
944
+ }
945
+ /** Data that must exist on a personalization variation regardless of selection algorithm */
946
+ interface VariationMatchMetadata {
947
+ /**
948
+ * Name of the variation for analytics tracking.
949
+ * NOTE: name is optional for backwards compatibility, but it is HIGHLY recommended to specify a name
950
+ * as the default fallback is not helpfully named and is reliant on the order of the variations array.
951
+ */
952
+ name?: string;
953
+ }
954
+ type DimensionMatch = {
955
+ /**
956
+ * Left hand side of the match expression (name of dimension in score vector)
957
+ * NOTE: if the dimension is not present in the score vector, it will be treated as if it has a value of 0
958
+ */
959
+ l: string;
960
+ /**
961
+ * Operator of the match expression
962
+ * Whole-vector (RHS only) operators - these do not require a `r` or `rDim` set:
963
+ * +: `l` is the strongest dimension in the score vector across all categories
964
+ * ^: `l` is the strongest dimension in the specified category
965
+ * -: `l` is the weakest dimension in the score vector. This does not match if the dimension has no score at all.
966
+ *
967
+ * Comparison operators:
968
+ * >: `l` is greater than the right hand side expression
969
+ * >= : `l` is greater than or equal to the right hand side expression
970
+ * <: `l` is less than the right hand side expression
971
+ * <= : `l` is less than or equal to the right hand side expression
972
+ * =: `l` is equal to the right hand side expression
973
+ * !=: `l` is not equal to the right hand side expression
974
+ */
975
+ op: '+' | '-' | '>' | '>=' | '<' | '<=' | '=' | '!=' | '^';
976
+ /**
977
+ * Right hand side of the match expression (not required for op = + or - which have no right side)
978
+ * This value is treated as a constant value, if it is present. If it's a string, it is parsed to an integer.
979
+ * To reference another score dimension as the RHS, use the `rDim` property instead.
980
+ * `r` and `rDim` are mutually exclusive; if both are specified, then `rDim` wins.
981
+ */
982
+ r?: number | string;
983
+ /**
984
+ * Right hand side of the match expression (not required for op = + or - which have no right side)
985
+ * This value is treated as a reference to another score dimension, if it is present in the score vector.
986
+ * If the referenced dimension is NOT present in the score vector, the match will always be false.
987
+ * To reference a constant value instead as the RHS, use the `r` property instead.
988
+ * `r` and `rDim` are mutually exclusive; if both are specified, then `rDim` wins.
989
+ */
990
+ rDim?: string;
991
+ };
992
+ type QuirkMatch = {
993
+ /**
994
+ * Type of match expression; 'q' discriminates quirk matches from dimension matches
995
+ */
996
+ t: 'q';
997
+ /**
998
+ * Left hand side of the match expression (name of quirk)
999
+ * NOTE: if the quirk is not present
1000
+ */
1001
+ l: string;
1002
+ /**
1003
+ * Operator of the match expression
1004
+ * Comparison operators:
1005
+ * =: `l` is equal to the right hand side expression
1006
+ * !=: `l` is not equal to the right hand side expression
1007
+ */
1008
+ op: '=' | '!=';
1009
+ /**
1010
+ * Right hand side of the match expression
1011
+ * This value is treated as a constant value, if it is present. If it's a string, it is parsed to an integer.
1012
+ * To reference another score dimension as the RHS, use the `rDim` property instead.
1013
+ * `r` and `rDim` are mutually exclusive; if both are specified, then `rDim` wins.
1014
+ */
1015
+ r: string;
1016
+ /**
1017
+ * Only here to maintain object compatibility with DimensionMatch.
1018
+ * Completely ignored.
1019
+ * @deprecated this is not used with QuirkMatch.
1020
+ */
1021
+ rDim?: string;
1022
+ };
1023
+
1024
+ /** Content that is tagged for adding enrichment score when triggered by behavior (i.e. being shown that content) */
1025
+ type BehaviorTag = {
1026
+ beh?: EnrichmentData[];
1027
+ };
1028
+ /** Defines the shape of a personalized content variant */
1029
+ type PersonalizedVariant<TCriteria = VariantMatchCriteria> = {
1030
+ /** A unique identifier for this variation */
1031
+ id: string;
1032
+ /** Match criteria for this variation */
1033
+ pz?: TCriteria;
1034
+ };
1035
+ /** The result of computing personalized content from variations */
1036
+ type PersonalizedResult<TVariant> = {
1037
+ /** Whether or not this result contains a personalized result */
1038
+ personalized: boolean;
1039
+ /** Matching variations */
1040
+ variations: Array<TVariant & {
1041
+ /** Whether the visitor is part of this variation's local control group (also true if part of global control group) */
1042
+ control: boolean;
1043
+ }>;
1044
+ };
1045
+ /** Defines the shape of a A/B test variant */
1046
+ type TestVariant = {
1047
+ /** The identifier for this variant. This value persisted to storage when a variant is selected. */
1048
+ id: string;
1049
+ /**
1050
+ * A number between 0 and 100 representing what percentage of visitors will be selected for this variant.
1051
+ * If not provided, this variant will be selected in equal proportion to other variants without an explicit distribution.
1052
+ */
1053
+ testDistribution?: number;
1054
+ /** Whether this variant is a control variant.
1055
+ * Can be undefined for backward compatibility with older versions of the SDK which were not explicitly setting the control flag.
1056
+ */
1057
+ control?: boolean;
1058
+ };
1059
+ /** The result of computing an A/B test result */
1060
+ type TestResult<TVariant> = {
1061
+ /** The selected variation */
1062
+ result: TVariant | undefined;
1063
+ /**
1064
+ * Whether the test variant was newly assigned to the visitor.
1065
+ * True: variant was assigned to the visitor for the first time.
1066
+ * False: variant was already assigned to the visitor and is being reused.
1067
+ */
1068
+ variantAssigned: boolean;
1069
+ };
1070
+ interface PersonalizeOptions<TVariant> {
1071
+ /** Name of placement (sent to analytics) */
1072
+ name: string;
1073
+ /** Possible variations to place */
1074
+ variations: Iterable<TVariant>;
1075
+ /** Maximum number of variants to place (default: 1) */
1076
+ take?: number;
1077
+ /** Name of the personalization selection algorithm to use. Defaults to top-down criteria when not specified. */
1078
+ algorithm?: string;
1079
+ /** Composition metadata where the personalization is being rendered for analytics tracking */
1080
+ compositionMetadata?: CompositionMetadata;
1081
+ }
1082
+ interface PersonalizationSelectionAlgorithmOptions<TCriteria, TVariant extends PersonalizedVariant<TCriteria> = PersonalizedVariant<TCriteria>> {
1083
+ /** Name of placement (sent to analytics) */
1084
+ name: string;
1085
+ /** Possible variations to place */
1086
+ variations: Iterable<TVariant>;
1087
+ /** Maximum number of variants to place (default: 1) */
1088
+ take?: number;
1089
+ /** Callback for logging messages */
1090
+ onLogMessage?: (message: LogMessage) => void;
1091
+ /** Context instance */
1092
+ context: Context;
1093
+ }
1094
+
1095
+ type TestOptions<TVariant extends TestVariant> = {
1096
+ /** The name of the test that is being run, must be included in the manifest. */
1097
+ name: string;
1098
+ /** Variations that are being tested. */
1099
+ variations: TVariant[];
1100
+ /** Composition metadata where the personalization is being rendered for analytics tracking */
1101
+ compositionMetadata?: CompositionMetadata;
1102
+ };
1103
+ declare const testVariations: <TVariant extends TestVariant>({ name, context, variations, onLogMessage, }: TestOptions<TVariant> & {
1104
+ context: Context;
1105
+ onLogMessage?: (message: LogMessage) => void;
1106
+ }) => TestResult<TVariant>;
1107
+
1108
+ declare const CONTEXTUAL_EDITING_TEST_NAME = "contextual_editing_test";
1109
+ declare const CONTEXTUAL_EDITING_TEST_SELECTED_VARIANT_ID = "contextual_editing_test_selected_variant";
1110
+ type PersonalizationSelectionAlgorithm<TCriteria = unknown> = (options: PersonalizationSelectionAlgorithmOptions<TCriteria>) => PersonalizedResult<PersonalizedVariant<TCriteria>>;
1111
+ type PersonalizationSelectionAlgorithms<TCriteria = unknown> = Record<string, PersonalizationSelectionAlgorithm<TCriteria>>;
1112
+ /**
1113
+ * Defines a plugin for Uniform Context.
1114
+ * The plugin should attach event handlers in its creation function.
1115
+ * @returns A function that detaches any event handlers when called
1116
+ */
1117
+ type ContextPlugin = {
1118
+ /** Defines a log drain for the plugin, which all log messages are sent to */
1119
+ logDrain?: LogDrain;
1120
+ /** Initializes the plugin (attach event handlers here if needed) */
1121
+ init?: (context: Context) => () => void;
1122
+ /** Plugin-specific actions to perform when a user is forgotten */
1123
+ forget?: () => Promise<void> | void;
1124
+ /** Plugin-specific actions to perform when the visitor context is updated, second parameter is the recalculated scores after the update */
1125
+ update?: (newData: Partial<ContextState>, recalculatedScores: ScoreVector) => Promise<void> | void;
1126
+ /**
1127
+ * Allows the plugin to register named personalization selection algorithms
1128
+ *
1129
+ * Important: the `default` and `strongestMatch` algorithms are automatically registered.
1130
+ * We strongly advise against replacing these.
1131
+ */
1132
+ personalizationSelectionAlgorithms?: PersonalizationSelectionAlgorithms<any>;
1133
+ };
1134
+ interface ContextOptions extends Omit<VisitorDataStoreOptions, 'manifest' | 'onServerTransitionScoresReceived'> {
1135
+ /** The Context Manifest to load (from the Context API) */
1136
+ manifest: ManifestV2;
1137
+ /**
1138
+ * Context plugins to load at initialize time.
1139
+ * Plugins that hook to the log event should be added here so that they can catch init-time log message events.
1140
+ *
1141
+ * Note that the Context passed to the plugin is not yet fully initialized, and is intended for event handler attachment
1142
+ * only - don't call scores, update, etc on it. If you need to call these methods immediately, attach your plugin after initialisation.
1143
+ */
1144
+ plugins?: Array<ContextPlugin>;
1145
+ /**
1146
+ * Only show personalizations if the visitor has given consent.
1147
+ * `false (default)`: personalization can run in memory without visitor granting storage consent
1148
+ * `true`: personalization is not run at all unless storage consent is given
1149
+ */
1150
+ requireConsentForPersonalization?: boolean;
1151
+ }
1152
+ type PersonalizationEventVariantId = {
1153
+ /** The variant ID that was selected */
1154
+ id: string;
1155
+ /** Whether the visitor is part of this variant's local control group (also true if part of global control group) */
1156
+ control: boolean;
1157
+ };
1158
+ /** Emitted when a personalization runs */
1159
+ type PersonalizationEvent = {
1160
+ /** Name of the personalized placement */
1161
+ name: string;
1162
+ /** Selected variant ID(s) */
1163
+ variantIds: PersonalizationEventVariantId[];
1164
+ /** Whether the user was part of the control group (and did not receive any personalization) */
1165
+ control: boolean | undefined;
1166
+ /**
1167
+ * Whether the personalized placement has changed since the last time the placement was evaluated.
1168
+ * True: the placement was evaluated for the first time, or the variant(s) selected changed from last time (e.g. due to a score change that activated a new variant).
1169
+ * False: the variant(s) selected were the same as a previous evaluation of this placement.
1170
+ */
1171
+ changed: boolean;
1172
+ /**
1173
+ * Contains information about the composition that contains personalization wrapper component,
1174
+ * which triggered the personalization event.
1175
+ * Only references top level root composition after pattern resolutions.
1176
+ */
1177
+ compositionMetadata?: CompositionMetadata;
1178
+ };
1179
+ /** Emitted event when an A/B test runs */
1180
+ type TestEvent = {
1181
+ /** Name (public ID) of the A/B test */
1182
+ name: string;
1183
+ /** ID of the variant that was selected */
1184
+ variantId: string | undefined;
1185
+ /**
1186
+ * Whether the variant is part of the control group.
1187
+ */
1188
+ control: boolean;
1189
+ /**
1190
+ * Whether the test variant was newly assigned to the visitor.
1191
+ * True: variant was assigned to the visitor for the first time.
1192
+ * False: variant was already assigned to the visitor and is being reused.
1193
+ */
1194
+ variantAssigned: boolean;
1195
+ /**
1196
+ * Contains information about the composition that contains A/B test wrapper component,
1197
+ * which triggered the A/B test event.
1198
+ * Only references top level root composition after pattern resolutions.
1199
+ */
1200
+ compositionMetadata?: CompositionMetadata;
1201
+ };
1202
+ type ContextEvents = {
1203
+ /**
1204
+ * Fired when the scores are updated.
1205
+ * The event is NOT fired if an update does not result in any score changes.
1206
+ * The result is merged between session and permanent data.
1207
+ */
1208
+ scoresUpdated: Readonly<ScoreVector>;
1209
+ /**
1210
+ * Fired when quirk data changes. Not fired if no changes to quirks are made
1211
+ * (e.g. setting it to the same value it already has)
1212
+ */
1213
+ quirksUpdated: Quirks;
1214
+ /**
1215
+ * Fired when a log message is emitted from Context
1216
+ * Note that event handlers attached to this event will not catch events
1217
+ * logged during initialisation of the Context unless they are attached as plugins to the constructor.
1218
+ */
1219
+ log: LogMessage | LogMessageGroup;
1220
+ /** Test variant has been selected */
1221
+ testResult: TestEvent;
1222
+ /** Personalization variants have been selected */
1223
+ personalizationResult: PersonalizationEvent;
1224
+ /** Composition metadata has been set/updated, usually happens when new composition is being rendered during client-side navigation for example */
1225
+ canvasDataUpdated: CompositionMetadata;
1226
+ };
1227
+ interface ContextInstance {
1228
+ get scores(): Readonly<ScoreVector>;
1229
+ get quirks(): Readonly<Quirks>;
1230
+ update(newData: Partial<ContextState>): Promise<void>;
1231
+ getTestVariantId(testName: string): string | null | undefined;
1232
+ setTestVariantId(testName: string, variantId: string): void;
1233
+ log(...message: LogMessage): void;
1234
+ test<TVariant extends TestVariant>(options: TestOptions<TVariant>): TestResult<TVariant>;
1235
+ personalize<TVariant extends PersonalizedVariant<any>>(options: PersonalizeOptions<TVariant>): PersonalizedResult<TVariant>;
1236
+ forget(fromAllDevices: boolean): Promise<void>;
1237
+ getServerToClientTransitionState(): ServerToClientTransitionState;
1238
+ readonly manifest: ManifestInstance;
1239
+ events: {
1240
+ on: Emitter<ContextEvents>['on'];
1241
+ off: Emitter<ContextEvents>['off'];
1242
+ };
1243
+ /** @deprecated */
1244
+ internal_processTestEvent(event: TestEvent): void;
1245
+ /** @deprecated */
1246
+ internal_processPersonalizationEvent(event: PersonalizationEvent): void;
1247
+ /**
1248
+ * Gets the current canvas data
1249
+ */
1250
+ getCompositionMetadata(): Readonly<CompositionMetadata | undefined>;
1251
+ /**
1252
+ * Updates the canvas data and emits a canvasDataUpdated event
1253
+ */
1254
+ updateCompositionMetadata(newData: CompositionMetadata): Promise<void>;
1255
+ }
1256
+ declare class Context implements ContextInstance {
1257
+ #private;
1258
+ readonly manifest: ManifestInstance;
1259
+ constructor(options: ContextOptions);
1260
+ /** Gets the current visitor's dimension score vector. */
1261
+ get scores(): Readonly<ScoreVector>;
1262
+ /** Gets the current visitor's quirks values. */
1263
+ get quirks(): Readonly<Quirks>;
1264
+ get requireConsentForPersonalization(): boolean | undefined;
1265
+ /**
1266
+ * Subscribe to events
1267
+ */
1268
+ readonly events: {
1269
+ on: {
1270
+ <Key extends keyof ContextEvents>(type: Key, handler: mitt.Handler<ContextEvents[Key]>): void;
1271
+ (type: "*", handler: mitt.WildcardHandler<ContextEvents>): void;
1272
+ };
1273
+ off: {
1274
+ <Key extends keyof ContextEvents>(type: Key, handler?: mitt.Handler<ContextEvents[Key]> | undefined): void;
1275
+ (type: "*", handler: mitt.WildcardHandler<ContextEvents>): void;
1276
+ };
1277
+ };
1278
+ readonly storage: VisitorDataStore;
1279
+ /**
1280
+ * Updates the Context with new data of any sort, such as
1281
+ * new URLs, cookies, quirks, and enrichments.
1282
+ *
1283
+ * Only properties that are set in the data parameter will be updated,
1284
+ * for example if passing `url` but not `cookies`, the last known state of cookies will be preserved.
1285
+ *
1286
+ * Properties that do not result in a changed state,
1287
+ * i.e. pushing the same URL or cookies as before,
1288
+ * will NOT result in a recomputation of signal state.
1289
+ */
1290
+ update(newData: Partial<ContextState>): Promise<void>;
1291
+ processServerCommands({ serverCommands, commands, }: {
1292
+ serverCommands: StorageCommands[] | undefined;
1293
+ commands: StorageCommands[];
1294
+ }): Promise<void>;
1295
+ /** use test() instead */
1296
+ getTestVariantId(testName: string): string | null | undefined;
1297
+ /** use test() instead */
1298
+ setTestVariantId(testName: string, variantId: string): void;
1299
+ getPersonalizeVariantControl(name: string, index: number): boolean | undefined;
1300
+ /**
1301
+ * Writes a message to the Context log sink.
1302
+ * Used by Uniform internal SDK; not intended for public use.
1303
+ */
1304
+ log(...message: LogMessage): void;
1305
+ /** Executes an A/B test with a given set of variants, showing the visitor's assigned variant (or selecting one to assign, if none is set yet) */
1306
+ test<TVariant extends TestVariant>(options: TestOptions<TVariant>): TestResult<TVariant>;
1307
+ /** Executes a personalized placement with a given set of variants */
1308
+ personalize<TVariant extends PersonalizedVariant<any>>(options: PersonalizeOptions<TVariant>): PersonalizedResult<TVariant>;
1309
+ /**
1310
+ * Forgets the visitor's data and resets the Context to its initial state.
1311
+ * @param fromAllDevices for an identified user, whether to delete all their data (for the entire account) - true, or data for this device (sign out) - false
1312
+ */
1313
+ forget(fromAllDevices: boolean): Promise<void>;
1314
+ /**
1315
+ * Computes server to client transition state.
1316
+ *
1317
+ * Removes state from server-to-client if it came in initial state (cookies) to avoid double tracking on the client.
1318
+ */
1319
+ getServerToClientTransitionState(): ServerToClientTransitionState;
1320
+ /** @deprecated */
1321
+ internal_processTestEvent(event: TestEvent): void;
1322
+ /** @deprecated */
1323
+ internal_processPersonalizationEvent(event: PersonalizationEvent): void;
1324
+ /**
1325
+ * Gets the current canvas data
1326
+ */
1327
+ getCompositionMetadata(): Readonly<CompositionMetadata | undefined>;
1328
+ /**
1329
+ * Updates the canvas data and emits a canvasDataUpdated event
1330
+ */
1331
+ updateCompositionMetadata(newData: CompositionMetadata): Promise<void>;
1332
+ }
1333
+
1334
+ /**
1335
+ * The version of the DevTools UI to load when in Chromium extension context.
1336
+ * 1: Uniform Optimize.
1337
+ * 2: Uniform Context.
1338
+ */
1339
+ type DevToolsUiVersion = 1 | 2;
1340
+ /**
1341
+ * The data state provided to the devtools for rendering.
1342
+ */
1343
+ type DevToolsState = {
1344
+ /** Current computed visitor scores (includes aggregates) */
1345
+ scores: Readonly<ScoreVector>;
1346
+ /** Current visitor data (includes quirks, raw scores, tests, consent, etc) */
1347
+ data: Readonly<VisitorData>;
1348
+ /** Personalization events that have fired since devtools started */
1349
+ personalizations: Array<PersonalizationEvent>;
1350
+ /** Test events that have fired since devtools started */
1351
+ tests: Array<TestEvent>;
1352
+ /** The Context manifest */
1353
+ manifest: ManifestV2;
1354
+ };
1355
+ /** Mutations the DevTools can take on the data it receives */
1356
+ type DevToolsActions = {
1357
+ /** Standard updates; maps to Context.update() */
1358
+ update: (newData: Partial<ContextState>) => Promise<void>;
1359
+ /** Raw updates to the storage subsystem. Maps to Context.storage.updateData() */
1360
+ rawUpdate: (commands: StorageCommands[]) => Promise<void>;
1361
+ /** Forget the current visitor and clear data on this device */
1362
+ forget: () => Promise<void>;
1363
+ };
1364
+ type DevToolsEvent<Type extends string = string, TEventData = unknown> = {
1365
+ /** The integration ID that is required */
1366
+ type: Type;
1367
+ } & TEventData;
1368
+ type DevToolsEvents = DevToolsLogEvent | DevToolsDataEvent | DevToolsHelloEvent | DevToolsUpdateEvent | DevToolsRawCommandsEvent | DevToolsForgetEvent;
1369
+ /** A log message emitted as an event to the browser extension */
1370
+ type DevToolsLogEvent = DevToolsEvent<'uniform:context:log', {
1371
+ message: LogMessage;
1372
+ }>;
1373
+ /** Emitted when data is updated in Context to the devtools */
1374
+ type DevToolsDataEvent = DevToolsEvent<'uniform:context:data', {
1375
+ data: DevToolsState;
1376
+ }>;
1377
+ /** A hello message emitted as an event from the browser extension to test if the page contains Context */
1378
+ type DevToolsHelloEvent = DevToolsEvent<'uniform:context:hello', {
1379
+ uiVersion: DevToolsUiVersion;
1380
+ }>;
1381
+ /** Devtools requests a normal update cycle (regular data update, re-eval signals, etc) */
1382
+ type DevToolsUpdateEvent = DevToolsEvent<'uniform-in:context:update', {
1383
+ newData: Partial<ContextState>;
1384
+ }>;
1385
+ /** Devtools requests a raw update cycle (explicitly set scores of dimensions in durations, etc) */
1386
+ type DevToolsRawCommandsEvent = DevToolsEvent<'uniform-in:context:commands', {
1387
+ commands: StorageCommands[];
1388
+ }>;
1389
+ /** A request to forget me from the DevTools */
1390
+ type DevToolsForgetEvent = DevToolsEvent<'uniform-in:context:forget', unknown>;
1391
+ declare global {
1392
+ interface Window {
1393
+ /** Window var set by enableContextDevTools() to enable embedded devtools to receive Context instance and attach events to it. */
1394
+ __UNIFORM_DEVTOOLS_CONTEXT_INSTANCE__?: Context;
1395
+ /**
1396
+ * Window var set automatically that Uniform's contextual editing uses to respond to changes in the Context within its preview pane,
1397
+ * for example quirks being set from within the preview.
1398
+ */
1399
+ __UNIFORM_CONTEXTUAL_EDITING_CONTEXT__?: Context;
1400
+ }
1401
+ }
1402
+
1403
+ export { type ManifestV2 as $, type AggregateDimension as A, type DevToolsLogEvent as B, type ContextPlugin as C, type DecayFunction as D, type DevToolsDataEvent as E, type DevToolsHelloEvent as F, type DevToolsUpdateEvent as G, type DevToolsRawCommandsEvent as H, type DevToolsForgetEvent as I, type LogMessages as J, type Severity as K, type LogDrain as L, type MessageCategory as M, type MessageFunc as N, type OutputSeverity as O, type PersonalizedVariant as P, type Quirks as Q, type LogMessageSingle as R, type ScoreVector as S, TransitionDataStore as T, type LogMessageGroup as U, type VisitorData as V, ManifestInstance as W, GroupCriteriaEvaluator as X, type CriteriaEvaluatorResult as Y, type CriteriaEvaluatorParameters as Z, type SignalData as _, type StorageCommands as a, type PersonalizationManifest as a0, type Signal as a1, type SignalCriteriaGroup as a2, type SignalCriteria as a3, type EnrichmentCategory as a4, type NumberMatch as a5, type TestDefinition as a6, type AggregateDimensionInput as a7, type TestOptions as a8, testVariations as a9, type EnrichmentData as aA, type PersonalizeControlVariant as aB, type PersonalizeVariants as aC, type EventData as aD, emptyVisitorData as aE, type CompositionMetadata as aF, type ContextState as aG, type ContextStateUpdate as aH, type GoalStateUpdate as aI, type paths as aJ, type VariationMatchMetadata as aa, type DimensionMatch as ab, type QuirkMatch as ac, type BehaviorTag as ad, type TestVariant as ae, type TestResult as af, type StorageCommand as ag, type SetGoalCommand as ah, type ModifyScoreCommand as ai, type ModifySessionScoreCommand as aj, type SetConsentCommand as ak, type SetQuirkCommand as al, type SetTestCommand as am, type IdentifyCommand as an, type SetControlGroupCommand as ao, type SetPersonalizeVariantControlCommand as ap, areCommandsEqual as aq, type ServerToClientTransitionState as ar, SERVER_STATE_ID as as, type TransitionDataStoreEvents as at, type DecayOptions as au, type VisitorDataStoreOptions as av, type VisitorDataStoreEvents as aw, VisitorDataStore as ax, type Tests as ay, type Goals as az, type TransitionDataStoreOptions as b, type CriteriaEvaluator as c, type StringMatch as d, type VariantMatchCriteria as e, type LogMessage as f, type PersonalizeOptions as g, Context as h, type PersonalizedResult as i, type VariationMatchDimensionCriteria as j, type PersonalizationSelectionAlgorithmOptions as k, type DevToolsEvents as l, CONTEXTUAL_EDITING_TEST_NAME as m, CONTEXTUAL_EDITING_TEST_SELECTED_VARIANT_ID as n, type PersonalizationSelectionAlgorithm as o, type PersonalizationSelectionAlgorithms as p, type ContextOptions as q, type PersonalizationEventVariantId as r, type PersonalizationEvent as s, type TestEvent as t, type ContextEvents as u, type ContextInstance as v, type DevToolsUiVersion as w, type DevToolsState as x, type DevToolsActions as y, type DevToolsEvent as z };