@uniformdev/context 12.2.1-alpha.142 → 12.2.1-alpha.177

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,987 @@
1
+ import * as mitt from 'mitt';
2
+
3
+ declare type StorageCommand<TID extends string = string, TData = unknown> = {
4
+ type: TID;
5
+ data: TData;
6
+ };
7
+ /** Commands that can be issued to alter the storage of Uniform Context data */
8
+ declare type StorageCommands = ModifyScoreCommand | ModifySessionScoreCommand | SetConsentCommand | SetQuirkCommand | SetTestCommand | IdentifyCommand | SetControlGroupCommand;
9
+ /**
10
+ * Changes the visitor's permanent score for a given dimension
11
+ */
12
+ declare type ModifyScoreCommand = StorageCommand<'modscore', {
13
+ dimension: string;
14
+ delta: number;
15
+ }>;
16
+ /**
17
+ * Changes the visitor's session (time-based) score for a given dimension
18
+ */
19
+ declare type ModifySessionScoreCommand = StorageCommand<'modscoreS', {
20
+ dimension: string;
21
+ delta: number;
22
+ }>;
23
+ /**
24
+ * Changes the visitor's storage consent setting.
25
+ * Setting consent to false will trigger deletion of any stored data for the visitor.
26
+ * Scores are still collected in-memory when consent is false; just not persisted.
27
+ */
28
+ declare type SetConsentCommand = StorageCommand<'consent', boolean>;
29
+ /** Sets a permanent quirk key and value for the visitor */
30
+ declare type SetQuirkCommand = StorageCommand<'setquirk', {
31
+ key: string;
32
+ value: string;
33
+ }>;
34
+ /** Sets a specific variant as being this visitor's variant on an A/B test */
35
+ declare type SetTestCommand = StorageCommand<'settest', {
36
+ test: string;
37
+ variant: string;
38
+ }>;
39
+ /**
40
+ * Identifies the visitor as being a specific unique identifier.
41
+ * NOTE: this only has an effect when using an external cross-device transition storage system.
42
+ * NOTE: you cannot read the identified visitor ID back from the storage system once it is set.
43
+ */
44
+ declare type IdentifyCommand = StorageCommand<'identify', {
45
+ identity: string;
46
+ }>;
47
+ /**
48
+ * Sets whether the current visitor is in the personalization control group
49
+ * (Will not be exposed to personalization or gather classification data; WILL see A/B tests)
50
+ * In most cases this should not be sent as the membership is computed automatically for visitors;
51
+ * this command is intended mostly for diagnostics and testing purposes.
52
+ */
53
+ declare type SetControlGroupCommand = StorageCommand<'setcontrol', boolean>;
54
+
55
+ declare type Quirks = {
56
+ [key: string]: string;
57
+ };
58
+ declare type Tests = {
59
+ [key: string]: string;
60
+ };
61
+ declare type ScoreVector = {
62
+ [key: string]: number;
63
+ };
64
+ declare type EnrichmentData = {
65
+ /** Enrichment category name */
66
+ cat: string;
67
+ /** Enrichment key value */
68
+ key: string;
69
+ /** Strength value (amount of score added when viewing content) */
70
+ str: number;
71
+ };
72
+ declare type EventData = {
73
+ event: string;
74
+ payload?: any;
75
+ };
76
+ declare type VisitorData = {
77
+ /** Quirk key-value data */
78
+ quirks: Quirks;
79
+ /** A/B test variant selections */
80
+ tests: Tests;
81
+ /** Personalization score data for the current session (merge with all time for totals) */
82
+ sessionScores: ScoreVector;
83
+ /** Personalization score data for all time (merge with session for totals) */
84
+ scores: ScoreVector;
85
+ /**
86
+ * Whether consent has been given to store the visitor data
87
+ * If false or not set: visitor data is stored in memory and is lost if the browser refreshes
88
+ * If true: visitor data is stored in localStorage and any other transition storage if registered
89
+ */
90
+ consent?: boolean;
91
+ /**
92
+ * Whether the visitor has been assigned to the personalization control group -
93
+ * visitors who are not shown personalization. If this is true, all scores will be zeroed,
94
+ * and score updates will be ignored. This has no effect on quirks or tests.
95
+ *
96
+ * If this value is not set, a random roll will be performed to determine membership,
97
+ * based on the control group size.
98
+ */
99
+ controlGroup?: boolean;
100
+ };
101
+ declare const emptyVisitorData: () => VisitorData;
102
+ declare type ContextState = {
103
+ cookies: Record<string, string>;
104
+ url: URL;
105
+ quirks: Quirks;
106
+ enrichments: EnrichmentData[];
107
+ events: EventData[];
108
+ };
109
+ declare type ContextStateUpdate = {
110
+ state: Partial<ContextState>;
111
+ previousState: Partial<ContextState>;
112
+ visitor: VisitorData;
113
+ scores: ScoreVector;
114
+ };
115
+
116
+ declare type TransitionDataStoreOptions = {
117
+ initialData?: Partial<VisitorData>;
118
+ };
119
+ declare type ServerToClientTransitionState = Pick<Partial<VisitorData>, 'quirks' | 'tests'> & {
120
+ /**
121
+ * Server Score Vector - the resultant scores _on the server side_ after the server/edge render completes
122
+ * Note that the client side does not trust these scores; they are only used until it's done with initial
123
+ * recomputation.
124
+ */
125
+ ssv?: ScoreVector;
126
+ };
127
+ declare const SERVER_STATE_ID = "__UNIFORM_DATA__";
128
+ declare type TransitionDataStoreEvents = {
129
+ /**
130
+ * Fired when the data is updated asynchronously
131
+ * (i.e. a promise resolves with new data from a backend)
132
+ *
133
+ * NOT fired for synchronous updates (e.g. calling updateData()), unless this also results in an async update of the data afterwards.
134
+ * NOT fired if an asynchronous update does not result in any change compared to the last known data.
135
+ */
136
+ dataUpdatedAsync: Partial<VisitorData>;
137
+ };
138
+ declare abstract class TransitionDataStore {
139
+ #private;
140
+ constructor({ initialData }: TransitionDataStoreOptions);
141
+ get data(): Partial<VisitorData> | undefined;
142
+ /**
143
+ * Subscribe to events from the transition storage
144
+ */
145
+ readonly events: {
146
+ on: {
147
+ <Key extends "dataUpdatedAsync">(type: Key, handler: mitt.Handler<TransitionDataStoreEvents[Key]>): void;
148
+ (type: "*", handler: mitt.WildcardHandler<TransitionDataStoreEvents>): void;
149
+ };
150
+ off: {
151
+ <Key_1 extends "dataUpdatedAsync">(type: Key_1, handler?: mitt.Handler<TransitionDataStoreEvents[Key_1]> | undefined): void;
152
+ (type: "*", handler: mitt.WildcardHandler<TransitionDataStoreEvents>): void;
153
+ };
154
+ };
155
+ /**
156
+ * Updates data in the transition storage.
157
+ * @param commands Commands to execute against existing stored value (event based stores)
158
+ * @param computedValue Pre-computed new value against existing value (object based stores)
159
+ * @returns Resolved promise when the data has been updated
160
+ */
161
+ updateData(commands: StorageCommands[], computedValue: VisitorData): Promise<void>;
162
+ /**
163
+ * Deletes a visitor's stored data, forgetting them.
164
+ * @param fromAllDevices - false: logout from this device ID. true: forget all data about the visitor and their identity.
165
+ */
166
+ delete(fromAllDevices?: boolean): Promise<void>;
167
+ /**
168
+ * Deletes a visitor's stored data, forgetting them.
169
+ * Important: do not emit any async score update events from this function.
170
+ * @param fromAllDevices - false: logout from this device ID. true: forget all data about the visitor and their identity.
171
+ */
172
+ abstract handleDelete(fromAllDevices?: boolean): Promise<void>;
173
+ /**
174
+ * Updates visitor data in the transition store.
175
+ *
176
+ * NOTE: The updated data is optimistically stored in TransitionDataStore automatically,
177
+ * so unless the updated data is _changed_ by the backend data store, there is no need
178
+ * to emit async score changed events when the visitor data is done updating.
179
+ */
180
+ abstract handleUpdateData(commands: StorageCommands[], computedValue: VisitorData): Promise<void>;
181
+ protected signalAsyncDataUpdate(newScores: Partial<VisitorData>): void;
182
+ /**
183
+ * When we load on the client side after a server side rendering has occurred (server to client transition),
184
+ * we can have a page script (ID: __UNIFORM_DATA__) that contains the computed visitor data from the SSR/edge render.
185
+ * This data is injected into the first render to allow score syncing and the server to request commands be applied
186
+ * to the client side data store.
187
+ */
188
+ getClientTransitionState(): ServerToClientTransitionState | undefined;
189
+ }
190
+
191
+ declare type CookieAdapter = {
192
+ get: (name: string) => string | undefined;
193
+ set: (name: string, value: string) => void;
194
+ remove: (name: string) => void;
195
+ };
196
+ declare type DecayOptions = {
197
+ now: number;
198
+ lastUpd: number | undefined;
199
+ scores: ScoreVector;
200
+ sessionScores: ScoreVector;
201
+ };
202
+ /**
203
+ * Computes decay of visitor scores over time.
204
+ * NOTE: it is expected that this function mutates the incoming score vectors,
205
+ * if it needs to apply score decay. The data store ensures immutability already.
206
+ *
207
+ * @returns true if any decay was applied, false otherwise
208
+ */
209
+ declare type DecayFunction = (options: DecayOptions) => boolean;
210
+
211
+ /** Defines all error codes and their parameter(s) */
212
+ declare type LogMessages = {
213
+ /** Context constructed */
214
+ 1: MessageFunc;
215
+ /** Context received data update */
216
+ 2: MessageFunc<Partial<Omit<ContextState, 'url'> & {
217
+ url: string;
218
+ }>>;
219
+ /** Context emitted new score vector */
220
+ 3: MessageFunc<ScoreVector>;
221
+ /** Context emitted updated quirks */
222
+ 4: MessageFunc<Quirks>;
223
+ /** Storage received update commands */
224
+ 101: MessageFunc<StorageCommands[]>;
225
+ /** Storage data was updated */
226
+ 102: MessageFunc<VisitorData>;
227
+ /** Storage data was deleted bool: fromAllDevices */
228
+ 103: MessageFunc<boolean>;
229
+ /** Storage score was truncated to its cap */
230
+ 110: MessageFunc<{
231
+ dim: string;
232
+ score: number;
233
+ cap: number;
234
+ }>;
235
+ /** Storage visitor data expired and was cleared */
236
+ 120: MessageFunc;
237
+ /** Server to client transition score data was loaded */
238
+ 130: MessageFunc<ScoreVector>;
239
+ /** Test did not exist */
240
+ 401: MessageFunc<string>;
241
+ /** Previously shown test variant no longer in variant data */
242
+ 402: MessageFunc<{
243
+ test: string;
244
+ variant: string;
245
+ }>;
246
+ /** gtag was not present on the page to emit events to */
247
+ 700: MessageFunc;
248
+ /** Enabled gtag event signal redirection */
249
+ 701: MessageFunc;
250
+ };
251
+
252
+ declare type Severity = 'debug' | 'info' | 'warn' | 'error';
253
+ declare type OutputSeverity = Severity | 'none';
254
+ declare type MessageFunc<TArg = void> = (arg: TArg) => [string, string, ...any];
255
+ declare type LogMessage<TID extends keyof LogMessages = keyof LogMessages> = [
256
+ severity: Severity,
257
+ id: TID,
258
+ ...args: Parameters<LogMessages[TID]>
259
+ ];
260
+ declare type LogDrain = (message: LogMessage) => void;
261
+
262
+ declare type VisitorDataStoreOptions = {
263
+ /** Transition storage used to transfer server or edge side execution state to the client. Unused for client side only. */
264
+ transitionStore?: TransitionDataStore;
265
+ /** Duration of a 'visit' measured by this number of milliseconds without performing any updates */
266
+ visitLifespan?: number;
267
+ /** Personalization manifest data. If set, the data store will automatically apply score caps in the manifest data. */
268
+ manifest?: ManifestInstance;
269
+ /** Allows decaying of scores over time based on time between visits. Default: no decay */
270
+ decay?: DecayFunction;
271
+ /**
272
+ * Sets the default value of storage consent for new unknown visitors.
273
+ * If storage consent is not given, only in-memory data will be stored which is lost when the browser leaves the page.
274
+ * @default false - consent is not given for new visitors until they explicitly give it with an update command
275
+ */
276
+ defaultConsent?: boolean;
277
+ /**
278
+ * Function called when server-to-client transfer state is loaded and contains server-side computed scores.
279
+ * These scores are used as a temporary shim for the current scores on the client side, until score computation
280
+ * is completed the first time (which occurs when the current url is fed into the Context).
281
+ *
282
+ * 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),
283
+ * one render might be done with _no_ scores unless we dropped the server scores in temporarily, resulting in a flash of unpersonalized content.
284
+ */
285
+ onServerTransitionScoresReceived?: (ssv: ScoreVector) => void;
286
+ /** Called when a log message is emitted from the data store */
287
+ onLogMessage?: (message: LogMessage) => void;
288
+ };
289
+ declare type VisitorDataStoreEvents = {
290
+ /**
291
+ * Fired when the stored data is updated.
292
+ * This is fired for any update, whether from integrated or transition storage.
293
+ * The event is NOT fired if an update does not result in any score changes.
294
+ */
295
+ scoresUpdated: Pick<VisitorData, 'scores' | 'sessionScores'>;
296
+ /**
297
+ * Fired when stored quirks are updated.
298
+ * This is fired for any update, whether from integrated or transition storage.
299
+ * The event is NOT fired if an update does not result in any quirk changes.
300
+ */
301
+ quirksUpdated: Pick<VisitorData, 'quirks'>;
302
+ /**
303
+ * Fired when test variant selection is updated.
304
+ */
305
+ testsUpdated: Pick<VisitorData, 'tests'>;
306
+ /**
307
+ * Fired when storage consent is changed
308
+ */
309
+ consentUpdated: Pick<VisitorData, 'consent'>;
310
+ /**
311
+ * Fired when visitor control group membership is changed
312
+ */
313
+ controlGroupUpdated: Pick<VisitorData, 'controlGroup'>;
314
+ };
315
+ declare class VisitorDataStore {
316
+ #private;
317
+ constructor(options: VisitorDataStoreOptions);
318
+ /** Gets the current visitor data. This property is always up to date. */
319
+ get data(): VisitorData;
320
+ get decayEnabled(): boolean;
321
+ /**
322
+ * Subscribe to events from storage
323
+ */
324
+ readonly events: {
325
+ on: {
326
+ <Key extends keyof VisitorDataStoreEvents>(type: Key, handler: mitt.Handler<VisitorDataStoreEvents[Key]>): void;
327
+ (type: "*", handler: mitt.WildcardHandler<VisitorDataStoreEvents>): void;
328
+ };
329
+ off: {
330
+ <Key_1 extends keyof VisitorDataStoreEvents>(type: Key_1, handler?: mitt.Handler<VisitorDataStoreEvents[Key_1]> | undefined): void;
331
+ (type: "*", handler: mitt.WildcardHandler<VisitorDataStoreEvents>): void;
332
+ };
333
+ };
334
+ /** Push data update command(s) into the visitor data */
335
+ updateData(commands: StorageCommands[]): Promise<void>;
336
+ /**
337
+ * Deletes visitor data (forgetting them)
338
+ * In most cases you should use forget() on the Context instead of this function, which also clears the Context state.
339
+ * @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
340
+ */
341
+ delete(fromAllDevices: boolean): Promise<void>;
342
+ }
343
+
344
+ declare class ManifestInstance {
345
+ #private;
346
+ readonly data: ManifestV2;
347
+ constructor({ manifest, evaluator, }: {
348
+ manifest: ManifestV2;
349
+ evaluator?: GroupCriteriaEvaluator;
350
+ });
351
+ rollForControlGroup(): boolean;
352
+ getTest(name: string): TestDefinition | undefined;
353
+ computeSignals(update: ContextStateUpdate): StorageCommands[];
354
+ /**
355
+ * Computes aggregated scores based on other dimensions
356
+ */
357
+ computeAggregateDimensions(primitiveScores: ScoreVector): ScoreVector;
358
+ getDimensionByKey(scoreKey: string): EnrichmentCategory | Signal | undefined;
359
+ }
360
+
361
+ /**
362
+ * This file was auto-generated by openapi-typescript.
363
+ * Do not make direct changes to the file.
364
+ */
365
+ interface paths {
366
+ "/api/v2/manifest": {
367
+ /**
368
+ * Fetches the Intent Manifest for a given project.
369
+ * 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).
370
+ */
371
+ get: {
372
+ parameters: {
373
+ query: {
374
+ preview?: boolean;
375
+ projectId: string;
376
+ };
377
+ };
378
+ responses: {
379
+ /** OK */
380
+ 200: {
381
+ content: {
382
+ "application/json": components["schemas"]["ManifestV2"];
383
+ };
384
+ };
385
+ 400: external["swagger.yml"]["components"]["responses"]["BadRequestError"];
386
+ 401: external["swagger.yml"]["components"]["responses"]["UnauthorizedError"];
387
+ 403: external["swagger.yml"]["components"]["responses"]["ForbiddenError"];
388
+ /** No manifest has ever been published, and the API key does not have preview permissions */
389
+ 404: {
390
+ content: {
391
+ "text/plain": string;
392
+ };
393
+ };
394
+ 429: external["swagger.yml"]["components"]["responses"]["RateLimitError"];
395
+ 500: external["swagger.yml"]["components"]["responses"]["InternalServerError"];
396
+ };
397
+ };
398
+ };
399
+ }
400
+ interface components {
401
+ schemas: {
402
+ ManifestV2: {
403
+ project: {
404
+ pz?: components["schemas"]["PersonalizationManifest"];
405
+ /** @description A/B test settings */
406
+ test?: {
407
+ [key: string]: external["uniform-context-types.swagger.yml"]["components"]["schemas"]["Test"];
408
+ };
409
+ };
410
+ };
411
+ PersonalizationManifest: {
412
+ /** @description Map of all signals defined for personalization criteria */
413
+ sig?: {
414
+ [key: string]: external["uniform-context-types.swagger.yml"]["components"]["schemas"]["Signal"];
415
+ };
416
+ /** @description Map of all enrichment categories defined for personalization criteria */
417
+ enr?: {
418
+ [key: string]: external["uniform-context-types.swagger.yml"]["components"]["schemas"]["EnrichmentCategory"];
419
+ };
420
+ /** @description Map of all aggregate dimensions (intents or audiences) defined for personalization criteria */
421
+ agg?: {
422
+ [key: string]: external["uniform-context-types.swagger.yml"]["components"]["schemas"]["AggregateDimension"];
423
+ };
424
+ /** @description Percentage of visitors that will be used as a personalization control group (not shown any personalization) */
425
+ control?: number;
426
+ };
427
+ };
428
+ }
429
+ interface external {
430
+ "swagger.yml": {
431
+ paths: {};
432
+ components: {
433
+ schemas: {
434
+ Error: {
435
+ /** @description Error message(s) that occurred while processing the request */
436
+ errorMessage?: string[] | string;
437
+ };
438
+ };
439
+ responses: {
440
+ /** Request input validation failed */
441
+ BadRequestError: {
442
+ content: {
443
+ "application/json": external["swagger.yml"]["components"]["schemas"]["Error"];
444
+ };
445
+ };
446
+ /** API key or token was not valid */
447
+ UnauthorizedError: {
448
+ content: {
449
+ "application/json": external["swagger.yml"]["components"]["schemas"]["Error"];
450
+ };
451
+ };
452
+ /** Permission was denied */
453
+ ForbiddenError: {
454
+ content: {
455
+ "application/json": external["swagger.yml"]["components"]["schemas"]["Error"];
456
+ };
457
+ };
458
+ /** Too many requests in allowed time period */
459
+ RateLimitError: unknown;
460
+ /** Execution error occurred */
461
+ InternalServerError: unknown;
462
+ };
463
+ };
464
+ operations: {};
465
+ };
466
+ "uniform-context-types.swagger.yml": {
467
+ paths: {};
468
+ components: {
469
+ schemas: {
470
+ EnrichmentCategory: {
471
+ /** @description The maximum visitor score allowed for enrichment keys in this category */
472
+ cap: number;
473
+ };
474
+ PreviewSignal: external["uniform-context-types.swagger.yml"]["components"]["schemas"]["Signal"] & {
475
+ /** @description Friendly name of the signal */
476
+ name: string;
477
+ /** @description Description of the signal */
478
+ description?: string;
479
+ };
480
+ Signal: {
481
+ /** @description The signal strength per activation (each time its criteria are true, this score is added) */
482
+ str: number;
483
+ /** @description The maximum visitor score allowed for this signal */
484
+ cap: number;
485
+ /**
486
+ * @description How long the signal's score should persist
487
+ * 's' = current session (expires after a period of inactivity)
488
+ * 'p' = permanent (expires as far in the future as possible, may be limited by browser security settings)
489
+ * 't' = transient (score tracks the current state of the criteria every time scores are updated)
490
+ */
491
+ dur: "s" | "p" | "t";
492
+ crit: external["uniform-context-types.swagger.yml"]["components"]["schemas"]["RootSignalCriteriaGroup"];
493
+ };
494
+ RootSignalCriteriaGroup: {
495
+ /** @description Criteria type (Group of other criteria) */
496
+ type: "G";
497
+ /**
498
+ * @description The logical operator to apply to the criteria groups
499
+ * & = AND
500
+ * | = OR
501
+ *
502
+ * Default is `&` if unspecified.
503
+ *
504
+ * @default &
505
+ */
506
+ op?: "&" | "|";
507
+ /** @description The criteria clauses that make up this grouping of criteria */
508
+ clauses: (external["uniform-context-types.swagger.yml"]["components"]["schemas"]["SignalCriteriaGroup"] | external["uniform-context-types.swagger.yml"]["components"]["schemas"]["SignalCriteria"])[];
509
+ };
510
+ SignalCriteriaGroup: {
511
+ /** @description Criteria type (Group of other criteria) */
512
+ type: "G";
513
+ /**
514
+ * @description The logical operator to apply to the criteria groups
515
+ * & = AND
516
+ * | = OR
517
+ *
518
+ * Default is `&` if unspecified.
519
+ */
520
+ op?: "&" | "|";
521
+ /** @description The criteria clauses that make up this grouping of criteria */
522
+ clauses: (external["uniform-context-types.swagger.yml"]["components"]["schemas"]["SignalCriteriaGroup"] | external["uniform-context-types.swagger.yml"]["components"]["schemas"]["SignalCriteria"])[];
523
+ };
524
+ SignalCriteria: external["uniform-context-types.swagger.yml"]["components"]["schemas"]["CookieCriteria"] | external["uniform-context-types.swagger.yml"]["components"]["schemas"]["QueryStringCriteria"] | external["uniform-context-types.swagger.yml"]["components"]["schemas"]["QuirkCriteria"] | external["uniform-context-types.swagger.yml"]["components"]["schemas"]["EventCriteria"] | external["uniform-context-types.swagger.yml"]["components"]["schemas"]["CurrentPageCriteria"] | external["uniform-context-types.swagger.yml"]["components"]["schemas"]["PageViewCountCriteria"];
525
+ /** @description Matches a URL query string parameter value */
526
+ QueryStringCriteria: {
527
+ type: "QS";
528
+ /** @description The name of the query string parameter to match */
529
+ queryName: string;
530
+ /** @description The value to match the query string parameter against */
531
+ match: external["uniform-context-types.swagger.yml"]["components"]["schemas"]["StringMatch"];
532
+ };
533
+ /** @description Matches a web cookie value */
534
+ CookieCriteria: {
535
+ type: "CK";
536
+ /** @description The name of the cookie to match */
537
+ cookieName: string;
538
+ /** @description The value to match the cookie against */
539
+ match: external["uniform-context-types.swagger.yml"]["components"]["schemas"]["StringMatch"];
540
+ };
541
+ /** @description Matches a visitor quirk key and value */
542
+ QuirkCriteria: {
543
+ type: "QK";
544
+ /** @description The name of the quirk key to match */
545
+ key: string;
546
+ /** @description The quirk value to match against */
547
+ match: external["uniform-context-types.swagger.yml"]["components"]["schemas"]["StringMatch"];
548
+ };
549
+ /** @description Matches an analytics event name being fired */
550
+ EventCriteria: {
551
+ type: "EVT";
552
+ /** @description How to match the event name */
553
+ event: external["uniform-context-types.swagger.yml"]["components"]["schemas"]["StringMatch"];
554
+ };
555
+ /**
556
+ * @description Matches the current page's absolute path (i.e. /path/to/page.html)
557
+ * Does not include the query string or protocol and hostname (i.e. NOT https://foo.com/path/to/page.html?query=something)
558
+ */
559
+ CurrentPageCriteria: {
560
+ type: "PV";
561
+ /** @description The page/route path to match as a page that has been visited */
562
+ path: external["uniform-context-types.swagger.yml"]["components"]["schemas"]["StringMatch"];
563
+ };
564
+ PageViewCountCriteria: {
565
+ type: "PVC";
566
+ /** @description The expression to match the page view count against */
567
+ match: external["uniform-context-types.swagger.yml"]["components"]["schemas"]["NumberMatch"];
568
+ };
569
+ /** @description Describes a match expression on a string */
570
+ StringMatch: {
571
+ /** @description The right hand side of the match expression */
572
+ rhs: string;
573
+ /**
574
+ * @description The match operator
575
+ * '=' = exact match
576
+ * '~' = contains match
577
+ * '//' = regular expression match
578
+ *
579
+ * Any of the above can be prefixed with '!' to invert the match (i.e. != for 'not an exact match')
580
+ */
581
+ op: "=" | "~" | "//" | "!=" | "!~" | "!//";
582
+ /** @description The case sensitivity of the match. Defaults to false if unspecified. */
583
+ cs?: boolean;
584
+ } | {
585
+ /**
586
+ * @description The type of match to perform
587
+ * '*' = exists with any value
588
+ * '!*' = does not exist
589
+ */
590
+ op: "*" | "!*";
591
+ };
592
+ /** @description Describes a match expression on a number */
593
+ NumberMatch: {
594
+ /** @description The right hand side of the match expression */
595
+ rhs: number;
596
+ /**
597
+ * @description The type of match to perform
598
+ * '=' = exact match
599
+ * '!=' = not an exact match
600
+ * '<' = less than match expression
601
+ * '>' = greater than match expression
602
+ */
603
+ op: "=" | "<" | ">" | "!=";
604
+ };
605
+ /** @description Defines an aggregate dimension that is a grouping of other dimensions' scores; an intent or audience. */
606
+ AggregateDimension: {
607
+ /** @description Input dimensions to the aggregate dimension */
608
+ inputs: external["uniform-context-types.swagger.yml"]["components"]["schemas"]["AggregateDimensionInput"][];
609
+ };
610
+ /** @description Defines an input dimension to an aggregate dimension */
611
+ AggregateDimensionInput: {
612
+ /**
613
+ * @description Dimension name to reference as an input.
614
+ * For enrichment inputs, use CATEGORY_KEY as the dimension.
615
+ * Enrichments, signals, and other aggregate dimensions may be referenced.
616
+ *
617
+ * Note that creating a cycle of aggregate dimensions is allowed, however
618
+ * the final score will _ignore_ the cycled aggregate dimension in the result.
619
+ * This can be used to create mutually exclusive aggregates.
620
+ */
621
+ dim: string;
622
+ /**
623
+ * @description The sign of the input dimension controls how it affects the aggregate dimension's final score.
624
+ *
625
+ * '+' = add to the final score
626
+ * '-' = subtract from the final score
627
+ * 'c' = clear the final score (if the input dimension has any score at all, this aggreate will have no score regardless of other inputs)
628
+ *
629
+ * Default if unspecified: '+'
630
+ *
631
+ * @default +
632
+ */
633
+ sign?: "+" | "-" | "c";
634
+ };
635
+ Test: {
636
+ /** @description Winning variation ID - if set, the test will not run and this variation is shown to all visitors (the test is closed) */
637
+ wv?: string;
638
+ };
639
+ };
640
+ };
641
+ operations: {};
642
+ };
643
+ }
644
+
645
+ declare type SharedTypes = external['uniform-context-types.swagger.yml']['components']['schemas'];
646
+ declare type ManifestV2 = components['schemas']['ManifestV2'];
647
+ declare type PersonalizationManifest = components['schemas']['PersonalizationManifest'];
648
+ declare type Signal = SharedTypes['Signal'];
649
+ declare type SignalCriteriaGroup = SharedTypes['SignalCriteriaGroup'];
650
+ declare type SignalCriteria = SharedTypes['SignalCriteria'];
651
+ declare type EnrichmentCategory = SharedTypes['EnrichmentCategory'];
652
+ declare type StringMatch = SharedTypes['StringMatch'];
653
+ declare type NumberMatch = SharedTypes['NumberMatch'];
654
+ declare type TestDefinition = SharedTypes['Test'];
655
+ declare type AggregateDimension = SharedTypes['AggregateDimension'];
656
+ declare type AggregateDimensionInput = SharedTypes['AggregateDimensionInput'];
657
+
658
+ /**
659
+ * A type that evaluates a signal criteria type and
660
+ * decides if it matches the current Context state or not.
661
+ * @returns {boolean} - true for a match, false for no match
662
+ * */
663
+ declare type CriteriaEvaluator = (update: ContextStateUpdate, criteria: SignalCriteria, commands: StorageCommands[], signal: Signal, dimension: string) => boolean;
664
+
665
+ declare class GroupCriteriaEvaluator {
666
+ #private;
667
+ constructor(criteriaEvaluators: Record<string, CriteriaEvaluator>);
668
+ evaluate(update: ContextStateUpdate, crit: SignalCriteriaGroup, commands: StorageCommands[], signal: Signal, dimension: string): boolean;
669
+ }
670
+
671
+ /** Content that is tagged for adding enrichment score when triggered by behavior (i.e. being shown that content) */
672
+ declare type BehaviorTag = {
673
+ beh?: EnrichmentData[];
674
+ };
675
+ /** Defines the shape of a personalized content variant */
676
+ declare type PersonalizedVariant = {
677
+ /** A unique identifier for this variation */
678
+ id: string;
679
+ /** Match criteria for this variation */
680
+ pz?: VariantMatchCriteria;
681
+ };
682
+ /** The result of computing personalized content from variations */
683
+ declare type PersonalizedResult<TVariant> = {
684
+ /** Whether or not this result contains a personalized result */
685
+ personalized: boolean;
686
+ /** Matching variations */
687
+ variations: Array<TVariant>;
688
+ };
689
+ /** Defines the shape of a A/B test variant */
690
+ declare type TestVariant = {
691
+ /** The identifier for this variant. This value persisted to storage when a variant is selected. */
692
+ id: string;
693
+ /**
694
+ * A number between 0 and 100 representing what percentage of visitors will be selected for this variant.
695
+ * If not provided, this variant will be selected in equal proportion to other variants without an explicit distribution.
696
+ */
697
+ testDistribution?: number;
698
+ };
699
+ /** The result of computing an A/B test result */
700
+ declare type TestResult<TVariant> = {
701
+ /** The selected variation */
702
+ result: TVariant | undefined;
703
+ /**
704
+ * Whether the test variant was newly assigned to the visitor.
705
+ * True: variant was assigned to the visitor for the first time.
706
+ * False: variant was already assigned to the visitor and is being reused.
707
+ */
708
+ variantAssigned: boolean;
709
+ };
710
+ /** Defines the shape of arbitrarily tagged content where the tag can be for a test, behaviour, or personalization */
711
+ declare type TaggedContent = PersonalizedVariant & TestVariant & BehaviorTag & {
712
+ /** @deprecated no longer used */
713
+ intents?: IntentTagVector;
714
+ };
715
+ /**
716
+ * A vector keyed by intent ID which contains magnitude and configuration data for each intent ID that has been tagged
717
+ * @deprecated no longer used
718
+ */
719
+ declare type IntentTagVector = Record<string, IntentTagAxis>;
720
+ /**
721
+ * An individual intent tag magnitude value in an IntentTagVector
722
+ * @deprecated no longer used
723
+ */
724
+ interface IntentTagAxis {
725
+ /** If this is true, don't use this intent tag when calculating personalization. If false or unspecified, personalization is allowed. */
726
+ noPn?: boolean;
727
+ /** If this is true, don't use this intent tag when calculating behavior. If false or unspecified, behavior is allowed. */
728
+ noBeh?: boolean;
729
+ /**
730
+ * If this is true, ANY strength in the tagged intent will result in selecting this variant to personalize,
731
+ * regardless of other intents' strengths. If more than one tag is override,
732
+ * they are sorted normally.
733
+ */
734
+ override?: boolean;
735
+ /**
736
+ * Sets the minimum visitor score required to trigger this variation.
737
+ * If more than one intent tag matches, the one with the highest threshold will win.
738
+ */
739
+ threshold?: number;
740
+ /** Strength of the intent tag. If unspecified, IntentTagStrength.Normal should be inferred */
741
+ str?: number | string;
742
+ }
743
+
744
+ declare type PersonalizeOptions<TVariant> = {
745
+ /** Name of placement (sent to analytics) */
746
+ name: string;
747
+ /** Possible variants to place */
748
+ variations: Iterable<TVariant>;
749
+ /** Maximum number of variants to place (default: 1) */
750
+ take?: number;
751
+ };
752
+ declare function personalizeVariations<TVariant extends PersonalizedVariant>({ context, variations, take, }: PersonalizeOptions<TVariant> & {
753
+ context: Context;
754
+ }): PersonalizedResult<TVariant>;
755
+
756
+ declare type VariantMatchCriteria = {
757
+ /**
758
+ * Operation for match criteria
759
+ *
760
+ * @defaultValue `&`
761
+ */
762
+ op?: '&' | '|';
763
+ crit: DimensionMatch[];
764
+ };
765
+ declare type DimensionMatch = {
766
+ /**
767
+ * Left hand side of the match expression (name of dimension in score vector)
768
+ * NOTE: if the dimension is not present in the score vector, it will be treated as if it has a value of 0
769
+ */
770
+ l: string;
771
+ /**
772
+ * Operator of the match expression
773
+ * Whole-vector (RHS only) operators - these do not require a `r` or `rDim` set:
774
+ * +: `l` is the strongest dimension in the score vector
775
+ * -: `l` is the weakest dimension in the score vector. This does not match if the dimension has no score at all.
776
+ *
777
+ * Comparison operators:
778
+ * >: `l` is greater than the right hand side expression
779
+ * >= : `l` is greater than or equal to the right hand side expression
780
+ * <: `l` is less than the right hand side expression
781
+ * <= : `l` is less than or equal to the right hand side expression
782
+ * =: `l` is equal to the right hand side expression
783
+ * !=: `l` is not equal to the right hand side expression
784
+ */
785
+ op: '+' | '-' | '>' | '>=' | '<' | '<=' | '=' | '!=';
786
+ /**
787
+ * Right hand side of the match expression (not required for op = + or - which have no right side)
788
+ * This value is treated as a constant value, if it is present. If it's a string, it is parsed to an integer.
789
+ * To reference another score dimension as the RHS, use the `rDim` property instead.
790
+ * `r` and `rDim` are mutually exclusive; if both are specified, then `rDim` wins.
791
+ */
792
+ r?: number | string;
793
+ /**
794
+ * Right hand side of the match expression (not required for op = + or - which have no right side)
795
+ * This value is treated as a reference to another score dimension, if it is present in the score vector.
796
+ * If the referenced dimension is NOT present in the score vector, the match will always be false.
797
+ * To reference a constant value instead as the RHS, use the `r` property instead.
798
+ * `r` and `rDim` are mutually exclusive; if both are specified, then `rDim` wins.
799
+ */
800
+ rDim?: string;
801
+ };
802
+
803
+ declare type TestOptions<TVariant extends TestVariant> = {
804
+ /** The name of the test that is being run, must be included in the manifest. */
805
+ name: string;
806
+ /** Variations that are being tested. */
807
+ variations: TVariant[];
808
+ };
809
+ declare const testVariations: <TVariant extends TestVariant>({ name, context, variations, }: TestOptions<TVariant> & {
810
+ context: Context;
811
+ }) => TestResult<TVariant>;
812
+
813
+ /**
814
+ * Defines a plugin for Uniform Context.
815
+ * The plugin should attach event handlers in its creation function.
816
+ * @returns A function that detaches any event handlers when called
817
+ */
818
+ declare type ContextPlugin = {
819
+ logDrain?: LogDrain;
820
+ init?: (context: Context) => () => void;
821
+ };
822
+ declare type ContextOptions = {
823
+ /** The Context Manifest to load (from the Context API) */
824
+ manifest: ManifestV2;
825
+ /**
826
+ * Context plugins to load at initialize time.
827
+ * Plugins that hook to the log event should be added here so that they can catch init-time log message events.
828
+ *
829
+ * Note that the Context passed to the plugin is not yet fully initialized, and is intended for event handler attachment
830
+ * only - don't call scores, update, etc on it. If you need to call these methods immediately, attach your plugin after initialisation.
831
+ */
832
+ plugins?: Array<ContextPlugin>;
833
+ } & Omit<VisitorDataStoreOptions, 'manifest' | 'onServerTransitionScoresReceived'>;
834
+ /** Emitted when a personalization runs */
835
+ declare type PersonalizationEvent = {
836
+ /** Name of the personalized placement */
837
+ name: string;
838
+ /** Selected variant ID(s) */
839
+ variantIds: string[];
840
+ /** Whether the user was part of the control group (and did not receive any personalization) */
841
+ control: boolean | undefined;
842
+ /**
843
+ * Whether the personalized placement has changed since the last time the placement was evaluated.
844
+ * 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).
845
+ * False: the variant(s) selected were the same as a previous evaluation of this placement.
846
+ */
847
+ changed: boolean;
848
+ };
849
+ /** Emitted event when an A/B test runs */
850
+ declare type TestEvent = {
851
+ /** Name (public ID) of the A/B test */
852
+ name: string;
853
+ /** ID of the variant that was selected */
854
+ variantId: string | undefined;
855
+ /**
856
+ * Whether the test variant was newly assigned to the visitor.
857
+ * True: variant was assigned to the visitor for the first time.
858
+ * False: variant was already assigned to the visitor and is being reused.
859
+ */
860
+ variantAssigned: boolean;
861
+ };
862
+ declare type ContextEvents = {
863
+ /**
864
+ * Fired when the scores are updated.
865
+ * The event is NOT fired if an update does not result in any score changes.
866
+ * The result is merged between session and permanent data.
867
+ */
868
+ scoresUpdated: Readonly<ScoreVector>;
869
+ /**
870
+ * Fired when quirk data changes. Not fired if no changes to quirks are made
871
+ * (e.g. setting it to the same value it already has)
872
+ */
873
+ quirksUpdated: Quirks;
874
+ /**
875
+ * Fired when a log message is emitted from Context
876
+ * Note that event handlers attached to this event will not catch events
877
+ * logged during initialisation of the Context unless they are attached as plugins to the constructor.
878
+ */
879
+ log: LogMessage;
880
+ /** Test variant has been selected */
881
+ testResult: TestEvent;
882
+ /** Personalization variants have been selected */
883
+ personalizationResult: PersonalizationEvent;
884
+ };
885
+ declare class Context implements Context {
886
+ #private;
887
+ readonly manifest: ManifestInstance;
888
+ constructor(options: ContextOptions);
889
+ get scores(): Readonly<ScoreVector>;
890
+ /**
891
+ * Subscribe to events
892
+ */
893
+ readonly events: {
894
+ on: {
895
+ <Key extends keyof ContextEvents>(type: Key, handler: mitt.Handler<ContextEvents[Key]>): void;
896
+ (type: "*", handler: mitt.WildcardHandler<ContextEvents>): void;
897
+ };
898
+ off: {
899
+ <Key_1 extends keyof ContextEvents>(type: Key_1, handler?: mitt.Handler<ContextEvents[Key_1]> | undefined): void;
900
+ (type: "*", handler: mitt.WildcardHandler<ContextEvents>): void;
901
+ };
902
+ };
903
+ readonly storage: VisitorDataStore;
904
+ update(newData: Partial<ContextState>): Promise<void>;
905
+ getTestVariantId(testName: string): string | null | undefined;
906
+ setTestVariantId(testName: string, variantId: string): void;
907
+ /**
908
+ * Writes a message to the Context log sink.
909
+ * Used by Uniform internal SDK; not intended for public use.
910
+ */
911
+ log(...message: LogMessage): void;
912
+ /** 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) */
913
+ test<TVariant extends TestVariant>(options: TestOptions<TVariant>): TestResult<TVariant>;
914
+ /** Executes a personalized placement with a given set of variants */
915
+ personalize<TVariant extends PersonalizedVariant>(options: PersonalizeOptions<TVariant>): PersonalizedResult<TVariant>;
916
+ /**
917
+ * Forgets the visitor's data and resets the Context to its initial state.
918
+ * @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
919
+ */
920
+ forget(fromAllDevices: boolean): Promise<void>;
921
+ }
922
+
923
+ /**
924
+ * The version of the DevTools UI to load when in Chromium extension context.
925
+ * 1: Uniform Optimize.
926
+ * 2: Uniform Context.
927
+ */
928
+ declare type DevToolsUiVersion = 1 | 2;
929
+ /**
930
+ * The data state provided to the devtools for rendering.
931
+ */
932
+ declare type DevToolsState = {
933
+ /** Current computed visitor scores (includes aggregates) */
934
+ scores: Readonly<ScoreVector>;
935
+ /** Current visitor data (includes quirks, raw scores, tests, consent, etc) */
936
+ data: Readonly<VisitorData>;
937
+ /** Personalization events that have fired since devtools started */
938
+ personalizations: Array<PersonalizationEvent>;
939
+ /** Test events that have fired since devtools started */
940
+ tests: Array<TestEvent>;
941
+ /** The Context manifest */
942
+ manifest: ManifestV2;
943
+ };
944
+ /** Mutations the DevTools can take on the data it receives */
945
+ declare type DevToolsActions = {
946
+ /** Standard updates; maps to Context.update() */
947
+ update: (newData: Partial<ContextState>) => Promise<void>;
948
+ /** Raw updates to the storage subsystem. Maps to Context.storage.updateData() */
949
+ rawUpdate: (commands: StorageCommands[]) => Promise<void>;
950
+ /** Forget the current visitor and clear data on this device */
951
+ forget: () => Promise<void>;
952
+ };
953
+ declare type DevToolsEvent<Type extends string = string, TEventData = unknown> = {
954
+ /** The integration ID that is required */
955
+ type: Type;
956
+ } & TEventData;
957
+ declare type DevToolsEvents = DevToolsLogEvent | DevToolsDataEvent | DevToolsHelloEvent | DevToolsUpdateEvent | DevToolsRawCommandsEvent | DevToolsForgetEvent;
958
+ /** A log message emitted as an event to the browser extension */
959
+ declare type DevToolsLogEvent = DevToolsEvent<'uniform:context:log', {
960
+ message: LogMessage;
961
+ }>;
962
+ /** Emitted when data is updated in Context to the devtools */
963
+ declare type DevToolsDataEvent = DevToolsEvent<'uniform:context:data', {
964
+ data: DevToolsState;
965
+ }>;
966
+ /** A hello message emitted as an event from the browser extension to test if the page contains Context */
967
+ declare type DevToolsHelloEvent = DevToolsEvent<'uniform:context:hello', {
968
+ uiVersion: DevToolsUiVersion;
969
+ }>;
970
+ /** Devtools requests a normal update cycle (regular data update, re-eval signals, etc) */
971
+ declare type DevToolsUpdateEvent = DevToolsEvent<'uniform-in:context:update', {
972
+ newData: Partial<ContextState>;
973
+ }>;
974
+ /** Devtools requests a raw update cycle (explicitly set scores of dimensions in durations, etc) */
975
+ declare type DevToolsRawCommandsEvent = DevToolsEvent<'uniform-in:context:commands', {
976
+ commands: StorageCommands[];
977
+ }>;
978
+ /** A request to forget me from the DevTools */
979
+ declare type DevToolsForgetEvent = DevToolsEvent<'uniform-in:context:forget', unknown>;
980
+ declare global {
981
+ interface Window {
982
+ /** Window var set by enableContextDevTools() to enable embedded devtools to receive Context instance and attach events to it. */
983
+ __UNIFORM_DEVTOOLS_CONTEXT_INSTANCE__?: Context;
984
+ }
985
+ }
986
+
987
+ export { Severity as $, AggregateDimension as A, VisitorDataStoreOptions as B, CookieAdapter as C, DecayFunction as D, EnrichmentCategory as E, VisitorDataStoreEvents as F, GroupCriteriaEvaluator as G, VisitorDataStore as H, IdentifyCommand as I, ServerToClientTransitionState as J, SERVER_STATE_ID as K, LogDrain as L, ManifestInstance as M, NumberMatch as N, OutputSeverity as O, PersonalizationManifest as P, Quirks as Q, TransitionDataStoreEvents as R, StorageCommands as S, TransitionDataStore as T, ContextOptions as U, VisitorData as V, PersonalizationEvent as W, TestEvent as X, ContextEvents as Y, Context as Z, LogMessages as _, TransitionDataStoreOptions as a, MessageFunc as a0, LogMessage as a1, testVariations as a2, TestOptions as a3, PersonalizeOptions as a4, personalizeVariations as a5, DimensionMatch as a6, BehaviorTag as a7, PersonalizedVariant as a8, PersonalizedResult as a9, TestVariant as aa, TestResult as ab, TaggedContent as ac, DevToolsUiVersion as ad, DevToolsState as ae, DevToolsActions as af, DevToolsEvent as ag, DevToolsEvents as ah, DevToolsLogEvent as ai, DevToolsDataEvent as aj, DevToolsHelloEvent as ak, DevToolsUpdateEvent as al, DevToolsRawCommandsEvent as am, DevToolsForgetEvent as an, paths as ao, ContextPlugin as b, CriteriaEvaluator as c, StringMatch as d, ScoreVector as e, VariantMatchCriteria as f, ManifestV2 as g, Signal as h, SignalCriteriaGroup as i, SignalCriteria as j, TestDefinition as k, AggregateDimensionInput as l, Tests as m, EnrichmentData as n, EventData as o, emptyVisitorData as p, ContextState as q, ContextStateUpdate as r, StorageCommand as s, ModifyScoreCommand as t, ModifySessionScoreCommand as u, SetConsentCommand as v, SetQuirkCommand as w, SetTestCommand as x, SetControlGroupCommand as y, DecayOptions as z };