@contentful/optimization-core 0.1.0-alpha → 0.1.0-alpha11

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.
Files changed (149) hide show
  1. package/README.md +329 -93
  2. package/dist/160.mjs +3 -0
  3. package/dist/260.mjs +14 -0
  4. package/dist/260.mjs.map +1 -0
  5. package/dist/499.mjs +4 -0
  6. package/dist/632.mjs +5 -0
  7. package/dist/632.mjs.map +1 -0
  8. package/dist/942.mjs +2 -0
  9. package/dist/api-client.cjs +60 -0
  10. package/dist/api-client.cjs.map +1 -0
  11. package/dist/api-client.d.cts +4 -0
  12. package/dist/api-client.d.mts +4 -0
  13. package/dist/api-client.d.ts +4 -0
  14. package/dist/api-client.mjs +2 -0
  15. package/dist/api-schemas.cjs +63 -0
  16. package/dist/api-schemas.cjs.map +1 -0
  17. package/dist/api-schemas.d.cts +4 -0
  18. package/dist/api-schemas.d.mts +4 -0
  19. package/dist/api-schemas.d.ts +4 -0
  20. package/dist/api-schemas.mjs +2 -0
  21. package/dist/constants.cjs +78 -0
  22. package/dist/constants.cjs.map +1 -0
  23. package/dist/constants.d.cts +88 -0
  24. package/dist/constants.d.mts +88 -0
  25. package/dist/constants.d.ts +88 -0
  26. package/dist/constants.mjs +1 -0
  27. package/dist/index.cjs +1509 -1715
  28. package/dist/index.cjs.map +1 -1
  29. package/dist/index.d.cts +2523 -0
  30. package/dist/index.d.mts +2523 -0
  31. package/dist/index.d.ts +2523 -15
  32. package/dist/index.mjs +1215 -1362
  33. package/dist/index.mjs.map +1 -1
  34. package/dist/logger.cjs +67 -0
  35. package/dist/logger.cjs.map +1 -0
  36. package/dist/logger.d.cts +8 -0
  37. package/dist/logger.d.mts +8 -0
  38. package/dist/logger.d.ts +8 -0
  39. package/dist/logger.mjs +2 -0
  40. package/dist/symbols.cjs +42 -0
  41. package/dist/symbols.cjs.map +1 -0
  42. package/dist/symbols.d.cts +10 -0
  43. package/dist/symbols.d.mts +10 -0
  44. package/dist/symbols.d.ts +10 -0
  45. package/dist/symbols.mjs +1 -0
  46. package/package.json +78 -12
  47. package/dist/Consent.d.ts +0 -44
  48. package/dist/Consent.d.ts.map +0 -1
  49. package/dist/Consent.js +0 -2
  50. package/dist/Consent.js.map +0 -1
  51. package/dist/CoreBase.d.ts +0 -161
  52. package/dist/CoreBase.d.ts.map +0 -1
  53. package/dist/CoreBase.js +0 -151
  54. package/dist/CoreBase.js.map +0 -1
  55. package/dist/CoreStateful.d.ts +0 -142
  56. package/dist/CoreStateful.d.ts.map +0 -1
  57. package/dist/CoreStateful.js +0 -137
  58. package/dist/CoreStateful.js.map +0 -1
  59. package/dist/CoreStateless.d.ts +0 -53
  60. package/dist/CoreStateless.d.ts.map +0 -1
  61. package/dist/CoreStateless.js +0 -43
  62. package/dist/CoreStateless.js.map +0 -1
  63. package/dist/ProductBase.d.ts +0 -83
  64. package/dist/ProductBase.d.ts.map +0 -1
  65. package/dist/ProductBase.js +0 -50
  66. package/dist/ProductBase.js.map +0 -1
  67. package/dist/analytics/AnalyticsBase.d.ts +0 -35
  68. package/dist/analytics/AnalyticsBase.d.ts.map +0 -1
  69. package/dist/analytics/AnalyticsBase.js +0 -13
  70. package/dist/analytics/AnalyticsBase.js.map +0 -1
  71. package/dist/analytics/AnalyticsStateful.d.ts +0 -138
  72. package/dist/analytics/AnalyticsStateful.d.ts.map +0 -1
  73. package/dist/analytics/AnalyticsStateful.js +0 -179
  74. package/dist/analytics/AnalyticsStateful.js.map +0 -1
  75. package/dist/analytics/AnalyticsStateless.d.ts +0 -48
  76. package/dist/analytics/AnalyticsStateless.d.ts.map +0 -1
  77. package/dist/analytics/AnalyticsStateless.js +0 -61
  78. package/dist/analytics/AnalyticsStateless.js.map +0 -1
  79. package/dist/analytics/index.d.ts +0 -5
  80. package/dist/analytics/index.d.ts.map +0 -1
  81. package/dist/analytics/index.js +0 -5
  82. package/dist/analytics/index.js.map +0 -1
  83. package/dist/global-constants.d.ts +0 -18
  84. package/dist/global-constants.d.ts.map +0 -1
  85. package/dist/global-constants.js +0 -18
  86. package/dist/global-constants.js.map +0 -1
  87. package/dist/index.d.ts.map +0 -1
  88. package/dist/index.js +0 -15
  89. package/dist/index.js.map +0 -1
  90. package/dist/lib/decorators/guardedBy.d.ts +0 -113
  91. package/dist/lib/decorators/guardedBy.d.ts.map +0 -1
  92. package/dist/lib/decorators/guardedBy.js +0 -143
  93. package/dist/lib/decorators/guardedBy.js.map +0 -1
  94. package/dist/lib/decorators/index.d.ts +0 -2
  95. package/dist/lib/decorators/index.d.ts.map +0 -1
  96. package/dist/lib/decorators/index.js +0 -2
  97. package/dist/lib/decorators/index.js.map +0 -1
  98. package/dist/lib/interceptor/InterceptorManager.d.ts +0 -127
  99. package/dist/lib/interceptor/InterceptorManager.d.ts.map +0 -1
  100. package/dist/lib/interceptor/InterceptorManager.js +0 -125
  101. package/dist/lib/interceptor/InterceptorManager.js.map +0 -1
  102. package/dist/lib/interceptor/index.d.ts +0 -2
  103. package/dist/lib/interceptor/index.d.ts.map +0 -1
  104. package/dist/lib/interceptor/index.js +0 -2
  105. package/dist/lib/interceptor/index.js.map +0 -1
  106. package/dist/lib/value-presence/ValuePresence.d.ts +0 -123
  107. package/dist/lib/value-presence/ValuePresence.d.ts.map +0 -1
  108. package/dist/lib/value-presence/ValuePresence.js +0 -141
  109. package/dist/lib/value-presence/ValuePresence.js.map +0 -1
  110. package/dist/lib/value-presence/index.d.ts +0 -2
  111. package/dist/lib/value-presence/index.d.ts.map +0 -1
  112. package/dist/lib/value-presence/index.js +0 -2
  113. package/dist/lib/value-presence/index.js.map +0 -1
  114. package/dist/personalization/PersonalizationBase.d.ts +0 -184
  115. package/dist/personalization/PersonalizationBase.d.ts.map +0 -1
  116. package/dist/personalization/PersonalizationBase.js +0 -76
  117. package/dist/personalization/PersonalizationBase.js.map +0 -1
  118. package/dist/personalization/PersonalizationStateful.d.ts +0 -226
  119. package/dist/personalization/PersonalizationStateful.d.ts.map +0 -1
  120. package/dist/personalization/PersonalizationStateful.js +0 -297
  121. package/dist/personalization/PersonalizationStateful.js.map +0 -1
  122. package/dist/personalization/PersonalizationStateless.d.ts +0 -74
  123. package/dist/personalization/PersonalizationStateless.d.ts.map +0 -1
  124. package/dist/personalization/PersonalizationStateless.js +0 -98
  125. package/dist/personalization/PersonalizationStateless.js.map +0 -1
  126. package/dist/personalization/index.d.ts +0 -6
  127. package/dist/personalization/index.d.ts.map +0 -1
  128. package/dist/personalization/index.js +0 -6
  129. package/dist/personalization/index.js.map +0 -1
  130. package/dist/personalization/resolvers/FlagsResolver.d.ts +0 -35
  131. package/dist/personalization/resolvers/FlagsResolver.d.ts.map +0 -1
  132. package/dist/personalization/resolvers/FlagsResolver.js +0 -47
  133. package/dist/personalization/resolvers/FlagsResolver.js.map +0 -1
  134. package/dist/personalization/resolvers/MergeTagValueResolver.d.ts +0 -74
  135. package/dist/personalization/resolvers/MergeTagValueResolver.d.ts.map +0 -1
  136. package/dist/personalization/resolvers/MergeTagValueResolver.js +0 -109
  137. package/dist/personalization/resolvers/MergeTagValueResolver.js.map +0 -1
  138. package/dist/personalization/resolvers/PersonalizedEntryResolver.d.ts +0 -142
  139. package/dist/personalization/resolvers/PersonalizedEntryResolver.d.ts.map +0 -1
  140. package/dist/personalization/resolvers/PersonalizedEntryResolver.js +0 -196
  141. package/dist/personalization/resolvers/PersonalizedEntryResolver.js.map +0 -1
  142. package/dist/personalization/resolvers/index.d.ts +0 -7
  143. package/dist/personalization/resolvers/index.d.ts.map +0 -1
  144. package/dist/personalization/resolvers/index.js +0 -7
  145. package/dist/personalization/resolvers/index.js.map +0 -1
  146. package/dist/signals.d.ts +0 -35
  147. package/dist/signals.d.ts.map +0 -1
  148. package/dist/signals.js +0 -30
  149. package/dist/signals.js.map +0 -1
package/README.md CHANGED
@@ -1,23 +1,23 @@
1
1
  <p align="center">
2
2
  <a href="https://www.contentful.com/developers/docs/personalization/">
3
- <img alt="Contentful Logo" title="Contentful" src="../../contentful-icon.png" width="150">
3
+ <img alt="Contentful Logo" title="Contentful" src="https://raw.githubusercontent.com/contentful/optimization/v0.1.0-alpha11/contentful-icon.png" width="150">
4
4
  </a>
5
5
  </p>
6
6
 
7
- <h1 align="center">Contentful Personalization & Analytics</h1>
7
+ <h1 align="center">Contentful Optimization Core SDK</h1>
8
8
 
9
9
  <h3 align="center">Optimization Core SDK</h3>
10
10
 
11
11
  <div align="center">
12
12
 
13
- [Readme](./README.md) · [Reference](https://contentful.github.io/optimization) ·
14
- [Contributing](/CONTRIBUTING.md)
13
+ [Guides](https://contentful.github.io/optimization/documents/Guides.html) ·
14
+ [Reference](https://contentful.github.io/optimization) · [Contributing](https://github.com/contentful/optimization/blob/v0.1.0-alpha11/CONTRIBUTING.md)
15
15
 
16
16
  </div>
17
17
 
18
18
  > [!WARNING]
19
19
  >
20
- > The Optimization SDK Suite is currently ALPHA! Breaking changes may be published at any time.
20
+ > The Optimization SDK Suite is pre-release (alpha). Breaking changes may be published at any time.
21
21
 
22
22
  The Optimization Core SDK encapsulates all platform-agnostic functionality and business logic. All
23
23
  other SDKs descend from the Core SDK.
@@ -31,25 +31,31 @@ other SDKs descend from the Core SDK.
31
31
  - [Working with Stateful Core](#working-with-stateful-core)
32
32
  - [Configuration](#configuration)
33
33
  - [Top-level Configuration Options](#top-level-configuration-options)
34
- - [Analytics Options](#analytics-options)
34
+ - [API Options](#api-options)
35
35
  - [Event Builder Options](#event-builder-options)
36
36
  - [Fetch Options](#fetch-options)
37
- - [Personalization Options](#personalization-options)
37
+ - [Queue Policy Options](#queue-policy-options)
38
38
  - [Core Methods](#core-methods)
39
- - [Personalization Data Resolution Methods](#personalization-data-resolution-methods)
40
- - [`getCustomFlag`](#getcustomflag)
41
- - [`personalizeEntry`](#personalizeentry)
39
+ - [Optimization Data Resolution Methods](#optimization-data-resolution-methods)
40
+ - [`getFlag`](#getflag)
41
+ - [`resolveOptimizedEntry`](#resolveoptimizedentry)
42
42
  - [`getMergeTagValue`](#getmergetagvalue)
43
- - [Personalization and Analytics Event Methods](#personalization-and-analytics-event-methods)
43
+ - [Event Methods](#event-methods)
44
44
  - [`identify`](#identify)
45
45
  - [`page`](#page)
46
+ - [`screen`](#screen)
46
47
  - [`track`](#track)
47
- - [`trackComponentView`](#trackcomponentview)
48
+ - [`trackView`](#trackview)
49
+ - [`trackClick`](#trackclick)
50
+ - [`trackHover`](#trackhover)
48
51
  - [`trackFlagView`](#trackflagview)
49
52
  - [Stateful-only Core Methods](#stateful-only-core-methods)
50
53
  - [`consent`](#consent)
51
54
  - [`reset`](#reset)
52
- - [Stateful-only Core Properties](#stateful-only-core-properties)
55
+ - [`flush`](#flush)
56
+ - [`destroy`](#destroy)
57
+ - [`registerPreviewPanel` (preview tooling only)](#registerpreviewpanel-preview-tooling-only)
58
+ - [Core States (`CoreStateful` only)](#core-states-corestateful-only)
53
59
  - [Interceptors](#interceptors)
54
60
  - [Life-cycle Interceptors](#life-cycle-interceptors)
55
61
 
@@ -76,9 +82,9 @@ import { CoreStateless } from '@contentful/optimization-core'
76
82
  Configure and initialize the Core SDK:
77
83
 
78
84
  ```ts
79
- const optimization = new CoreStateful({ clientId: 'abc123' })
80
- // or
81
- const optimization = new CoreStateless({ clientId: 'abc123' })
85
+ const statefulOptimization = new CoreStateful({ clientId: 'abc123' })
86
+ const statelessOptimization = new CoreStateless({ clientId: 'abc123' })
87
+ const requestOptimization = statelessOptimization.forRequest()
82
88
  ```
83
89
 
84
90
  ## Working with Stateless Core
@@ -91,6 +97,9 @@ In stateless environments, Core will not maintain any internal state, which incl
91
97
  These concerns should be handled by consumers to fit their specific architectural and design
92
98
  specifications.
93
99
 
100
+ Request-emitting methods in `CoreStateless` are bound per request via
101
+ `optimization.forRequest(...)`.
102
+
94
103
  ## Working with Stateful Core
95
104
 
96
105
  The `CoreStateful` class is intended to be used as the basis for SDKs that would run in stateful
@@ -100,49 +109,119 @@ In stateful environments, Core maintains state internally for consent, an event
100
109
  profile-related data that is commonly obtained from requests to the Experience API. These states are
101
110
  exposed externally as read-only observables.
102
111
 
112
+ > [!IMPORTANT]
113
+ >
114
+ > `CoreStateful` uses module-global state by design. Initialize exactly one stateful instance per
115
+ > JavaScript runtime and reuse it.
116
+
103
117
  ## Configuration
104
118
 
105
119
  ### Top-level Configuration Options
106
120
 
107
- | Option | Required? | Default | Description |
108
- | ----------------- | --------- | ----------------------------- | --------------------------------------------------------------------- |
109
- | `analytics` | No | See "Analytics Options" | Configuration specific to the Analytics/Insights API |
110
- | `clientId` | Yes | N/A | The Ninetailed API Key which can be found in the Ninetailed Admin app |
111
- | `environment` | No | `'main'` | The Ninetailed environment configured in the Ninetailed Admin app |
112
- | `eventBuilder` | No | See "Event Builder Options" | Event builder configuration (channel/library metadata, etc.) |
113
- | `fetchOptions` | No | See "Fetch Options" | Configuration for Fetch timeout and retry functionality |
114
- | `logLevel` | No | `'error'` | Minimum log level for the default console sin |
115
- | `personalization` | No | See "Personalization Options" | Configuration specific to the Personalization/Experience API |
121
+ | Option | Required? | Default | Description |
122
+ | -------------- | --------- | --------------------------- | ----------------------------------------------------------------------- |
123
+ | `api` | No | See "API Options" | Unified configuration for the Experience API and Insights API endpoints |
124
+ | `clientId` | Yes | N/A | Shared API key for Experience API and Insights API requests |
125
+ | `environment` | No | `'main'` | The environment identifier |
126
+ | `eventBuilder` | No | See "Event Builder Options" | Event builder configuration (channel/library metadata, etc.) |
127
+ | `fetchOptions` | No | See "Fetch Options" | Configuration for Fetch timeout and retry functionality |
128
+ | `logLevel` | No | `'error'` | Minimum log level for the default console sink |
116
129
 
117
130
  The following configuration options apply only in stateful environments:
118
131
 
119
- | Option | Required? | Default | Description |
120
- | -------------------------- | --------- | ---------------------- | ----------------------------------------------------------------- |
121
- | `allowedEventTypes` | No | `['identify', 'page']` | Allow-listed event types permitted when consent is not set |
122
- | `defaults` | No | `undefined` | Set of default state values applied on initialization |
123
- | `getAnonymousId` | No | `undefined` | Function used to obtain an anonymous user identifier |
124
- | `preventedComponentEvents` | No | `undefined` | Initial duplication prevention configuration for component events |
132
+ | Option | Required? | Default | Description |
133
+ | ------------------- | --------- | -------------------------------- | ---------------------------------------------------------- |
134
+ | `allowedEventTypes` | No | `['identify', 'page', 'screen']` | Allow-listed event types permitted when consent is not set |
135
+ | `defaults` | No | `undefined` | Set of default state values applied on initialization |
136
+ | `getAnonymousId` | No | `undefined` | Function used to obtain an anonymous user identifier |
137
+ | `onEventBlocked` | No | `undefined` | Callback invoked when an event call is blocked by guards |
138
+ | `queuePolicy` | No | See "Queue Policy Options" | Shared queue and retry configuration for stateful delivery |
125
139
 
126
140
  Configuration method signatures:
127
141
 
128
142
  - `getAnonymousId`: `() => string | undefined`
143
+ - `onEventBlocked`: `(event: BlockedEvent) => void`
129
144
 
130
- ### Analytics Options
145
+ ### API Options
131
146
 
132
- | Option | Required? | Default | Description |
133
- | --------- | --------- | ------------------------------------------ | ----------------------------- |
134
- | `baseUrl` | No | `'https://ingest.insights.ninetailed.co/'` | Base URL for the Insights API |
147
+ | Option | Required? | Default | Description |
148
+ | ------------------- | --------- | ------------------------------------------ | ------------------------------------------------------------ |
149
+ | `experienceBaseUrl` | No | `'https://experience.ninetailed.co/'` | Base URL for the Experience API |
150
+ | `insightsBaseUrl` | No | `'https://ingest.insights.ninetailed.co/'` | Base URL for the Insights API |
151
+ | `enabledFeatures` | No | `['ip-enrichment', 'location']` | Enabled features the Experience API may use for each request |
135
152
 
136
- The following configuration options apply only in stateful environments:
153
+ The following configuration option applies only in stateful environments:
137
154
 
138
- | Option | Required? | Default | Description |
139
- | --------------- | --------- | ----------- | ------------------------------------------------------------------------ |
140
- | `beaconHandler` | No | `undefined` | Handler used to enqueue events via the Beacon API or a similar mechanism |
155
+ | Option | Required? | Default | Description |
156
+ | --------------- | --------- | ----------- | ------------------------------------------------------------------------------ |
157
+ | `beaconHandler` | No | `undefined` | Handler used to enqueue Insights API events via the Beacon API or equivalent |
158
+ | `ip` | No | `undefined` | IP address override used by the Experience API for location analysis |
159
+ | `locale` | No | `'en-US'` | Locale used to translate `location.city` and `location.country` |
160
+ | `plainText` | No | `false` | Sends performance-critical Experience API endpoints in plain text |
161
+ | `preflight` | No | `false` | Instructs the Experience API to aggregate a new profile state but not store it |
141
162
 
142
163
  Configuration method signatures:
143
164
 
144
165
  - `beaconHandler`: `(url: string | URL, data: BatchInsightsEventArray) => boolean`
145
166
 
167
+ In stateless environments, bind `ip`, `locale`, `plainText`, and `preflight` per request with
168
+ `optimization.forRequest(...)` instead of constructor config.
169
+
170
+ ### Queue Policy Options
171
+
172
+ `queuePolicy` is available only in `CoreStateful` and combines shared flush retry settings with
173
+ Experience API offline buffering controls.
174
+
175
+ Configuration shape:
176
+
177
+ ```ts
178
+ {
179
+ flush?: {
180
+ baseBackoffMs?: number,
181
+ maxBackoffMs?: number,
182
+ jitterRatio?: number,
183
+ maxConsecutiveFailures?: number,
184
+ circuitOpenMs?: number,
185
+ onFlushFailure?: (context: QueueFlushFailureContext) => void,
186
+ onCircuitOpen?: (context: QueueFlushFailureContext) => void,
187
+ onFlushRecovered?: (context: QueueFlushRecoveredContext) => void
188
+ },
189
+ offlineMaxEvents?: number,
190
+ onOfflineDrop?: (context: ExperienceQueueDropContext) => void
191
+ }
192
+ ```
193
+
194
+ Supporting callback payloads:
195
+
196
+ ```ts
197
+ type ExperienceQueueDropContext = {
198
+ droppedCount: number
199
+ droppedEvents: ExperienceEventArray
200
+ maxEvents: number
201
+ queuedEvents: number
202
+ }
203
+
204
+ type QueueFlushFailureContext = {
205
+ consecutiveFailures: number
206
+ queuedBatches: number
207
+ queuedEvents: number
208
+ retryDelayMs: number
209
+ }
210
+
211
+ type QueueFlushRecoveredContext = {
212
+ consecutiveFailures: number
213
+ }
214
+ ```
215
+
216
+ Notes:
217
+
218
+ - `flush` applies the same retry/backoff/circuit policy to both Insights API flushing and Experience
219
+ API offline replay.
220
+ - Invalid numeric values fall back to defaults.
221
+ - `jitterRatio` is clamped to `[0, 1]`.
222
+ - `maxBackoffMs` is normalized to be at least `baseBackoffMs`.
223
+ - Failed flush attempts include both `false` responses and thrown send errors.
224
+
146
225
  ### Event Builder Options
147
226
 
148
227
  Event builder options should only be supplied when building an SDK on top of Core or any of its
@@ -189,7 +268,7 @@ Configuration method signatures:
189
268
  ### Fetch Options
190
269
 
191
270
  Fetch options allow for configuration of a Fetch API-compatible fetch method and the retry/timeout
192
- logic integrated into the Optimization API Client. Specify the `fetchMethod` when the host
271
+ logic integrated into the SDK's bundled API clients. Specify the `fetchMethod` when the host
193
272
  application environment does not offer a `fetch` method that is compatible with the standard Fetch
194
273
  API in its global scope.
195
274
 
@@ -207,16 +286,12 @@ Configuration method signatures:
207
286
  - `fetchMethod`: `(url: string | URL, init: RequestInit) => Promise<Response>`
208
287
  - `onFailedAttempt` and `onRequestTimeout`: `(options: FetchMethodCallbackOptions) => void`
209
288
 
210
- ### Personalization Options
211
-
212
- | Option | Required? | Default | Description |
213
- | ----------------- | --------- | ------------------------------------- | ------------------------------------------------------------------- |
214
- | `baseUrl` | No | `'https://experience.ninetailed.co/'` | Base URL for the Experience API |
215
- | `enabledFeatures` | No | `['ip-enrichment', 'location']` | Enabled features which the API may use for each request |
216
- | `ip` | No | `undefined` | IP address to override the API behavior for IP analysis |
217
- | `locale` | No | `'en-US'` (in API) | Locale used to translate `location.city` and `location.country` |
218
- | `plainText` | No | `false` | Sends performance-critical endpoints in plain text |
219
- | `preflight` | No | `false` | Instructs the API to aggregate a new profile state but not store it |
289
+ > [!NOTE]
290
+ >
291
+ > Core inherits the API Client retry contract: default retries intentionally apply only to HTTP
292
+ > `503` responses (`Service Unavailable`). This is deliberate and aligned with current Experience
293
+ > API and Insights API expectations; do not broaden retry status handling without an explicit API
294
+ > contract change.
220
295
 
221
296
  ## Core Methods
222
297
 
@@ -226,9 +301,9 @@ implementations.
226
301
 
227
302
  Arguments marked with an asterisk (\*) are always required.
228
303
 
229
- ### Personalization Data Resolution Methods
304
+ ### Optimization Data Resolution Methods
230
305
 
231
- #### `getCustomFlag`
306
+ #### `getFlag`
232
307
 
233
308
  Get the specified Custom Flag's value from the provided changes array, or from the current internal
234
309
  state in stateful implementations.
@@ -242,15 +317,23 @@ Returns:
242
317
 
243
318
  - The resolved value for the specified Custom Flag, or `undefined` if it cannot be found.
244
319
 
320
+ Behavior notes:
321
+
322
+ - In `CoreStateful`, calling `getFlag(...)` automatically emits a flag view event via
323
+ `trackFlagView`.
324
+ - In `CoreStateless`, `getFlag(...)` does not auto-emit a flag view event.
325
+ - If full map resolution is needed for advanced use cases, use
326
+ `optimization.flagsResolver.resolve(changes)`.
327
+
245
328
  > [!NOTE]
246
329
  >
247
330
  > If the `changes` argument is omitted in stateless implementations, the method will return
248
331
  > `undefined`.
249
332
 
250
- #### `personalizeEntry`
333
+ #### `resolveOptimizedEntry`
251
334
 
252
- Resolve a baseline Contentful entry to a personalized variant using the provided selected
253
- personalizations, or from the current internal state in stateful implementations.
335
+ Resolve a baseline Contentful entry to an optimized variant using the provided selected
336
+ optimizations, or from the current internal state in stateful implementations.
254
337
 
255
338
  Type arguments:
256
339
 
@@ -260,18 +343,18 @@ Type arguments:
260
343
 
261
344
  Arguments:
262
345
 
263
- - `entry`\*: The entry to personalize
264
- - `personalizations`: Selected personalizations
346
+ - `entry`\*: The baseline entry to resolve
347
+ - `selectedOptimizations`: Selected optimizations
265
348
 
266
349
  Returns:
267
350
 
268
- - The resolved personalized entry variant, or the supplied baseline entry if baseline is the
269
- selected variant or a variant cannot be found.
351
+ - The resolved optimized entry variant, or the supplied baseline entry if baseline is the selected
352
+ variant or a variant cannot be found.
270
353
 
271
354
  > [!NOTE]
272
355
  >
273
- > If the `personalizations` argument is omitted in stateless implementations, the method will return
274
- > the baseline entry.
356
+ > If the `selectedOptimizations` argument is omitted in stateless implementations, the method will
357
+ > return the baseline entry.
275
358
 
276
359
  #### `getMergeTagValue`
277
360
 
@@ -289,14 +372,37 @@ Arguments:
289
372
  > If the `profile` argument is omitted in stateless implementations, the method will return the
290
373
  > merge tag's fallback value.
291
374
 
292
- ### Personalization and Analytics Event Methods
375
+ ### Event Methods
293
376
 
294
- Each method except `trackFlagView` may return an `OptimizationData` object containing:
377
+ In `CoreStateful`, call these methods on the root instance. In `CoreStateless`, call them on the
378
+ request scope returned by `optimization.forRequest(...)`:
379
+
380
+ ```ts
381
+ const requestOptimization = optimization.forRequest({
382
+ locale: 'de-DE',
383
+ })
384
+ ```
385
+
386
+ Only the following methods may return an `OptimizationData` object:
387
+
388
+ - `identify`
389
+ - `page`
390
+ - `screen`
391
+ - `track`
392
+ - `trackView` (when `payload.sticky` is `true`)
393
+
394
+ `trackClick`, `trackHover`, and `trackFlagView` return no data. When returned, `OptimizationData`
395
+ contains:
295
396
 
296
397
  - `changes`: Currently used for Custom Flags
297
- - `personalizations`: Selected personalizations for the profile
398
+ - `selectedOptimizations`: Selected optimizations for the profile
298
399
  - `profile`: Profile associated with the evaluated events
299
400
 
401
+ In stateless runtimes, Insights-backed methods require a profile for delivery. Non-sticky
402
+ `trackView`, `trackClick`, `trackHover`, and `trackFlagView` require `payload.profile.id`. Sticky
403
+ `trackView` may omit `profile`, because the returned Experience profile is reused for the paired
404
+ Insights event.
405
+
300
406
  #### `identify`
301
407
 
302
408
  Identify the current profile/visitor to associate traits with a profile.
@@ -308,46 +414,82 @@ Arguments:
308
414
 
309
415
  #### `page`
310
416
 
311
- Record a personalization page view.
417
+ Record an Experience API page view.
312
418
 
313
419
  Arguments:
314
420
 
315
421
  - `payload`\*: Page view event builder arguments object, including an optional `profile` property
316
422
  with a `PartialProfile` value that requires only an `id`
317
423
 
424
+ #### `screen`
425
+
426
+ Record an Experience API screen view.
427
+
428
+ Arguments:
429
+
430
+ - `payload`\*: Screen view event builder arguments object, including an optional `profile` property
431
+ with a `PartialProfile` value that requires only an `id`
432
+
318
433
  #### `track`
319
434
 
320
- Record a personalization custom track event.
435
+ Record an Experience API custom track event.
321
436
 
322
437
  Arguments:
323
438
 
324
439
  - `payload`\*: Track event builder arguments object, including an optional `profile` property with a
325
440
  `PartialProfile` value that requires only an `id`
326
441
 
327
- #### `trackComponentView`
442
+ #### `trackView`
328
443
 
329
- Record an analytics component view event. When the payload marks the component as "sticky", an
330
- additional personalization component view is recorded. This method only returns `OptimizationData`
331
- when the component is marked as "sticky".
444
+ Record an Insights API entry view event. When the payload marks the entry as "sticky", an additional
445
+ Experience API entry view is recorded. This method only returns `OptimizationData` when the entry is
446
+ marked as "sticky".
332
447
 
333
448
  Arguments:
334
449
 
335
- - `payload`\*: Component view event builder arguments object, including an optional `profile`
336
- property with a `PartialProfile` value that requires only an `id`
337
- - `duplicationScope`: Arbitrary string that may be used to scope component view duplication; used in
338
- Stateful implementations
450
+ - `payload`\*: Entry view event builder arguments object. When `payload.sticky` is `true`, `profile`
451
+ is optional and the returned Experience profile is reused for Insights delivery. Otherwise,
452
+ `profile` is required and must contain at least an `id`
453
+
454
+ #### `trackClick`
455
+
456
+ Record an Insights API entry click event.
457
+
458
+ Returns:
459
+
460
+ - `void`
461
+
462
+ Arguments:
463
+
464
+ - `payload`\*: Entry click event builder arguments object, including a required `profile` property
465
+ with a `PartialProfile` value that requires only an `id`
466
+
467
+ #### `trackHover`
468
+
469
+ Record an Insights API entry hover event.
470
+
471
+ Returns:
472
+
473
+ - `void`
474
+
475
+ Arguments:
476
+
477
+ - `payload`\*: Entry hover event builder arguments object, including a required `profile` property
478
+ with a `PartialProfile` value that requires only an `id`
339
479
 
340
480
  #### `trackFlagView`
341
481
 
342
- Track a feature flag view via analytics. This is functionally the same as a non-sticky component
482
+ Track a feature flag view via the Insights API. This is functionally the same as a non-sticky flag
343
483
  view event.
344
484
 
485
+ Returns:
486
+
487
+ - `void`
488
+
345
489
  Arguments:
346
490
 
347
- - `payload`\*: Component view event builder arguments object, including an optional `profile`
348
- property with a `PartialProfile` value that requires only an `id`
349
- - `duplicationScope`: Arbitrary string that may be used to scope component view duplication; used in
350
- Stateful implementations
491
+ - `payload`\*: Flag view event builder arguments object, including a required `profile` property
492
+ with a `PartialProfile` value that requires only an `id`
351
493
 
352
494
  ## Stateful-only Core Methods
353
495
 
@@ -357,30 +499,124 @@ Updates the user consent state.
357
499
 
358
500
  Arguments:
359
501
 
360
- - `accept`: A boolean value specifying whether the user has accepted (`true`) or denied (`false`). A
361
- value of `undefined` implies that the user has not yet explicitly chosen whether to consent.
502
+ - `accept`: A boolean value specifying whether the user has accepted (`true`) or denied (`false`)
362
503
 
363
504
  ### `reset`
364
505
 
365
506
  Resets all internal state _except_ consent. This method expects no arguments and returns no value.
366
507
 
367
- ## Stateful-only Core Properties
508
+ ### `flush`
509
+
510
+ Flushes queued Insights API and Experience API events. This method expects no arguments and returns
511
+ a `Promise<void>`.
512
+
513
+ ### `destroy`
514
+
515
+ Releases singleton ownership for stateful runtime usage. This is intended for explicit teardown
516
+ paths, such as tests or hot-reload workflows. This method expects no arguments and returns no value.
517
+
518
+ ### `registerPreviewPanel` (preview tooling only)
519
+
520
+ Registers a preview consumer object and exposes internal signal references used by first-party
521
+ preview tooling.
522
+
523
+ Arguments:
524
+
525
+ - `previewPanel`: Required object that receives symbol-keyed signal bridge values
526
+
527
+ Returns:
528
+
529
+ - `void`
530
+
531
+ Bridge symbols:
532
+
533
+ - `PREVIEW_PANEL_SIGNALS_SYMBOL`: key used to expose internal `signals`
534
+ - `PREVIEW_PANEL_SIGNAL_FNS_SYMBOL`: key used to expose internal `signalFns`
535
+
536
+ Example:
368
537
 
369
- - `states`: Returns an object mapping of observables for all internal states
370
- - `consent`: The current state of user consent
371
- - `eventStream`: The latest event to be queued
372
- - `flags`: All current resolved Custom Flags
373
- - `profile`: The current user profile
374
- - `personalizations`: The current collection of selected personalizations
538
+ ```ts
539
+ import {
540
+ PREVIEW_PANEL_SIGNAL_FNS_SYMBOL,
541
+ PREVIEW_PANEL_SIGNALS_SYMBOL,
542
+ type PreviewPanelSignalObject,
543
+ } from '@contentful/optimization-core'
544
+
545
+ const previewBridge: PreviewPanelSignalObject = {}
546
+ optimization.registerPreviewPanel(previewBridge)
547
+
548
+ const signals = previewBridge[PREVIEW_PANEL_SIGNALS_SYMBOL]
549
+ const signalFns = previewBridge[PREVIEW_PANEL_SIGNAL_FNS_SYMBOL]
550
+ ```
551
+
552
+ > [!IMPORTANT]
553
+ >
554
+ > This method intentionally exposes mutable internal signals for preview tooling. The Web and React
555
+ > Native preview panels are tightly coupled by design and rely on this bridge (plus state
556
+ > interceptors) to apply immediate local overrides without network round-trips. This coupling is
557
+ > deliberate and necessary for preview functionality.
558
+
559
+ ## Core States (`CoreStateful` only)
560
+
561
+ `states` is available on `CoreStateful` and exposes signal-backed observables for runtime state.
562
+
563
+ Available state streams:
564
+
565
+ - `consent`: Current consent state (`boolean | undefined`)
566
+ - `blockedEventStream`: Latest blocked-call metadata (`BlockedEvent | undefined`)
567
+ - `eventStream`: Latest emitted Insights API or Experience API event
568
+ (`InsightsEvent | ExperienceEvent | undefined`)
569
+ - `flag(name)`: Key-scoped flag observable (`Observable<Json>`)
570
+ - `canOptimize`: Whether optimization selections are available (`boolean`;
571
+ `selectedOptimizations !== undefined`)
572
+ - `profile`: Current profile (`Profile | undefined`)
573
+ - `selectedOptimizations`: Current selected optimizations (`SelectedOptimizationArray | undefined`)
574
+ - `previewPanelAttached`: Preview panel attachment state (`boolean`)
575
+ - `previewPanelOpen`: Preview panel open state (`boolean`)
576
+
577
+ Each observable provides:
578
+
579
+ - `current`: Deep-cloned snapshot of the latest value
580
+ - `subscribe(next)`: Immediately emits `current`, then emits future updates
581
+ - `subscribeOnce(next)`: Emits the first non-nullish value, then auto-unsubscribes
375
582
 
376
- Each state except `consent` and `eventStream` is updated internally whenever a response from the
377
- Experience API contains a new or updated respective state.
583
+ `current` and callback payloads are deep-cloned snapshots, so local mutations do not affect Core's
584
+ internal signal state.
585
+
586
+ Update behavior:
587
+
588
+ - `blockedEventStream` updates whenever a call is blocked by consent guards.
589
+ - `eventStream` updates when a valid event is accepted for send/queue.
590
+ - `flag(name)` updates when the resolved value for that key changes.
591
+ - `canOptimize` updates whenever `selectedOptimizations` becomes defined or `undefined`.
592
+ - `consent` updates from defaults and `optimization.consent(...)`.
593
+ - `previewPanelAttached` and `previewPanelOpen` are controlled by preview tooling and are preserved
594
+ across `reset()`.
595
+
596
+ Example: read the latest snapshot synchronously:
597
+
598
+ ```ts
599
+ const profile = optimization.states.profile.current
600
+ if (profile) console.log(`Current profile: ${profile.id}`)
601
+ ```
602
+
603
+ Example: subscribe and clean up:
604
+
605
+ ```ts
606
+ const sub = optimization.states.profile.subscribe((profile) => {
607
+ if (!profile) return
608
+ console.log(`Profile ${profile.id} updated`)
609
+ })
610
+
611
+ // later (component unmount / teardown)
612
+ sub.unsubscribe()
613
+ ```
378
614
 
379
- Example `states` observable usage:
615
+ Example: wait for first available profile:
380
616
 
381
617
  ```ts
382
- optimization.states.profile.subscribe((profile) => {
383
- console.log(`Profile ${profile.id} updated!`)
618
+ optimization.states.profile.subscribeOnce((profile) => {
619
+ console.log(`Profile ${profile.id} loaded`)
384
620
  })
385
621
  ```
386
622
 
package/dist/160.mjs ADDED
@@ -0,0 +1,3 @@
1
+ import * as __rspack_external__contentful_optimization_api_client_api_schemas_4192893e from "@contentful/optimization-api-client/api-schemas";
2
+ var PartialProfile = __rspack_external__contentful_optimization_api_client_api_schemas_4192893e.PartialProfile;
3
+ export { PartialProfile, __rspack_external__contentful_optimization_api_client_api_schemas_4192893e };
package/dist/260.mjs ADDED
@@ -0,0 +1,14 @@
1
+ const OPTIMIZATION_CORE_SDK_VERSION = "0.1.0-alpha11";
2
+ const OPTIMIZATION_CORE_SDK_NAME = "@contentful/optimization-core";
3
+ const ANONYMOUS_ID_COOKIE = 'ctfl-opt-aid';
4
+ const ANONYMOUS_ID_KEY = '__ctfl_opt_anonymous_id__';
5
+ const CONSENT_KEY = '__ctfl_opt_consent__';
6
+ const CHANGES_CACHE_KEY = '__ctfl_opt_changes__';
7
+ const DEBUG_FLAG_KEY = '__ctfl_opt_debug__';
8
+ const PROFILE_CACHE_KEY = '__ctfl_opt_profile__';
9
+ const SELECTED_OPTIMIZATIONS_CACHE_KEY = '__ctfl_opt_selected-optimizations__';
10
+ const ANONYMOUS_ID_COOKIE_LEGACY = 'ntaid';
11
+ const ANONYMOUS_ID_KEY_LEGACY = '__nt_anonymous_id__';
12
+ export { ANONYMOUS_ID_COOKIE, ANONYMOUS_ID_COOKIE_LEGACY, ANONYMOUS_ID_KEY, ANONYMOUS_ID_KEY_LEGACY, CHANGES_CACHE_KEY, CONSENT_KEY, DEBUG_FLAG_KEY, OPTIMIZATION_CORE_SDK_NAME, OPTIMIZATION_CORE_SDK_VERSION, PROFILE_CACHE_KEY, SELECTED_OPTIMIZATIONS_CACHE_KEY };
13
+
14
+ //# sourceMappingURL=260.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"260.mjs","sources":["../src/constants.ts"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/naming-convention -- Replaced at build-time\ndeclare const __OPTIMIZATION_VERSION__: string | undefined\n// eslint-disable-next-line @typescript-eslint/naming-convention -- Replaced at build-time\ndeclare const __OPTIMIZATION_PACKAGE_NAME__: string | undefined\n\n/**\n * The current version of the Optimization Core SDK, injected at build time.\n *\n * @public\n */\nexport const OPTIMIZATION_CORE_SDK_VERSION =\n typeof __OPTIMIZATION_VERSION__ === 'string' ? __OPTIMIZATION_VERSION__ : '0.0.0'\n/**\n * The package name of the Optimization Core SDK, injected at build time.\n *\n * @public\n */\nexport const OPTIMIZATION_CORE_SDK_NAME =\n typeof __OPTIMIZATION_PACKAGE_NAME__ === 'string'\n ? __OPTIMIZATION_PACKAGE_NAME__\n : '@contentful/optimization-core'\n\n/**\n * Anonymous-ID cookie name used by the Optimization Core.\n *\n * @public\n * @remarks\n * This constant represents the cookie key used by the Optimization Framework\n * to persist an anonymous identifier for tracking optimization and insights\n * events when no explicit profile is known.\n *\n * @example\n * ```ts\n * import { ANONYMOUS_ID_COOKIE } from '@contentful/optimization-core/constants'\n * const profileId = request.cookies[ANONYMOUS_ID_COOKIE]\n * ```\n */\nexport const ANONYMOUS_ID_COOKIE = 'ctfl-opt-aid'\n\n/**\n * Storage key for the anonymous identifier.\n *\n * @internal\n */\nexport const ANONYMOUS_ID_KEY = '__ctfl_opt_anonymous_id__'\n\n/**\n * Storage key for the persisted consent status.\n *\n * @internal\n */\nexport const CONSENT_KEY = '__ctfl_opt_consent__'\n\n/**\n * Storage key for cached Custom Flags.\n *\n * @internal\n */\nexport const CHANGES_CACHE_KEY = '__ctfl_opt_changes__'\n\n/**\n * Storage key for the debug flag toggle.\n *\n * @internal\n */\nexport const DEBUG_FLAG_KEY = '__ctfl_opt_debug__'\n\n/**\n * Storage key for cached profile data.\n *\n * @internal\n */\nexport const PROFILE_CACHE_KEY = '__ctfl_opt_profile__'\n\n/**\n * Storage key for cached selected optimizations.\n *\n * @internal\n */\nexport const SELECTED_OPTIMIZATIONS_CACHE_KEY = '__ctfl_opt_selected-optimizations__'\n\n/**\n * Legacy anoynmous ID cookie key for migration from experience.js\n *\n * @internal\n */\nexport const ANONYMOUS_ID_COOKIE_LEGACY = 'ntaid'\n\n/**\n * Legacy anoynmous ID storage key for migration from experience.js\n *\n * @internal\n */\nexport const ANONYMOUS_ID_KEY_LEGACY = '__nt_anonymous_id__'\n"],"names":["OPTIMIZATION_CORE_SDK_VERSION","__OPTIMIZATION_VERSION__","OPTIMIZATION_CORE_SDK_NAME","__OPTIMIZATION_PACKAGE_NAME__","ANONYMOUS_ID_COOKIE","ANONYMOUS_ID_KEY","CONSENT_KEY","CHANGES_CACHE_KEY","DEBUG_FLAG_KEY","PROFILE_CACHE_KEY","SELECTED_OPTIMIZATIONS_CACHE_KEY","ANONYMOUS_ID_COOKIE_LEGACY","ANONYMOUS_ID_KEY_LEGACY"],"mappings":"AAUO,MAAMA,gCACoCC;AAM1C,MAAMC,6BAEPC;AAkBC,MAAMC,sBAAsB;AAO5B,MAAMC,mBAAmB;AAOzB,MAAMC,cAAc;AAOpB,MAAMC,oBAAoB;AAO1B,MAAMC,iBAAiB;AAOvB,MAAMC,oBAAoB;AAO1B,MAAMC,mCAAmC;AAOzC,MAAMC,6BAA6B;AAOnC,MAAMC,0BAA0B"}
package/dist/499.mjs ADDED
@@ -0,0 +1,4 @@
1
+ import * as __rspack_external__contentful_optimization_api_client_logger_f0d05f82 from "@contentful/optimization-api-client/logger";
2
+ var default_0 = __rspack_external__contentful_optimization_api_client_logger_f0d05f82["default"];
3
+ export default default_0;
4
+ export { __rspack_external__contentful_optimization_api_client_logger_f0d05f82 };
package/dist/632.mjs ADDED
@@ -0,0 +1,5 @@
1
+ const PREVIEW_PANEL_SIGNALS_SYMBOL = Symbol.for('ctfl.optimization.preview.signals');
2
+ const PREVIEW_PANEL_SIGNAL_FNS_SYMBOL = Symbol.for('ctfl.optimization.preview.signalFns');
3
+ export { PREVIEW_PANEL_SIGNALS_SYMBOL, PREVIEW_PANEL_SIGNAL_FNS_SYMBOL };
4
+
5
+ //# sourceMappingURL=632.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"632.mjs","sources":["../src/symbols.ts"],"sourcesContent":["/**\n * Well-known symbols used by the preview panel bridge.\n *\n * @public\n */\nexport const PREVIEW_PANEL_SIGNALS_SYMBOL = Symbol.for('ctfl.optimization.preview.signals')\nexport const PREVIEW_PANEL_SIGNAL_FNS_SYMBOL = Symbol.for('ctfl.optimization.preview.signalFns')\n"],"names":["PREVIEW_PANEL_SIGNALS_SYMBOL","Symbol","PREVIEW_PANEL_SIGNAL_FNS_SYMBOL"],"mappings":"AAKO,MAAMA,+BAA+BC,OAAO,GAAG,CAAC;AAChD,MAAMC,kCAAkCD,OAAO,GAAG,CAAC"}
package/dist/942.mjs ADDED
@@ -0,0 +1,2 @@
1
+ import * as __rspack_external__contentful_optimization_api_client_cba5a7ee from "@contentful/optimization-api-client";
2
+ export { __rspack_external__contentful_optimization_api_client_cba5a7ee };