@contentful/optimization-web 0.1.0-alpha
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +491 -0
- package/dist/AutoEntryViewTracking.d.ts +88 -0
- package/dist/AutoEntryViewTracking.d.ts.map +1 -0
- package/dist/Optimization.d.ts +146 -0
- package/dist/Optimization.d.ts.map +1 -0
- package/dist/analyzer.html +4 -0
- package/dist/builders/EventBuilder.d.ts +42 -0
- package/dist/builders/EventBuilder.d.ts.map +1 -0
- package/dist/builders/index.d.ts +2 -0
- package/dist/builders/index.d.ts.map +1 -0
- package/dist/contentful-optimization-web.umd.cjs +2 -0
- package/dist/contentful-optimization-web.umd.cjs.map +1 -0
- package/dist/global-constants.d.ts +37 -0
- package/dist/global-constants.d.ts.map +1 -0
- package/dist/handlers/beaconHandler.d.ts +24 -0
- package/dist/handlers/beaconHandler.d.ts.map +1 -0
- package/dist/handlers/createOnlineChangeListener.d.ts +34 -0
- package/dist/handlers/createOnlineChangeListener.d.ts.map +1 -0
- package/dist/handlers/createVisibilityChangeListener.d.ts +40 -0
- package/dist/handlers/createVisibilityChangeListener.d.ts.map +1 -0
- package/dist/handlers/index.d.ts +4 -0
- package/dist/handlers/index.d.ts.map +1 -0
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6244 -0
- package/dist/index.js.map +1 -0
- package/dist/observers/ElementExistenceObserver.d.ts +195 -0
- package/dist/observers/ElementExistenceObserver.d.ts.map +1 -0
- package/dist/observers/ElementView.d.ts +178 -0
- package/dist/observers/ElementView.d.ts.map +1 -0
- package/dist/observers/ElementViewObserver.d.ts +164 -0
- package/dist/observers/ElementViewObserver.d.ts.map +1 -0
- package/dist/observers/index.d.ts +6 -0
- package/dist/observers/index.d.ts.map +1 -0
- package/dist/storage/LocalStore.d.ts +111 -0
- package/dist/storage/LocalStore.d.ts.map +1 -0
- package/dist/storage/index.d.ts +3 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/test/helpers.d.ts +41 -0
- package/dist/test/helpers.d.ts.map +1 -0
- package/dist/visualizer.html +4687 -0
- package/package.json +28 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (C) 2026 Contentful Inc.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,491 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<a href="https://www.contentful.com/developers/docs/personalization/">
|
|
3
|
+
<img alt="Contentful Logo" title="Contentful" src="../../../contentful-icon.png" width="150">
|
|
4
|
+
</a>
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
<h1 align="center">Contentful Personalization & Analytics</h1>
|
|
8
|
+
|
|
9
|
+
<h3 align="center">Optimization Web SDK</h3>
|
|
10
|
+
|
|
11
|
+
<div align="center">
|
|
12
|
+
|
|
13
|
+
[Readme](./README.md) · [Reference](https://contentful.github.io/optimization) ·
|
|
14
|
+
[Contributing](/CONTRIBUTING.md)
|
|
15
|
+
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
> [!WARNING]
|
|
19
|
+
>
|
|
20
|
+
> The Optimization SDK Suite is currently ALPHA! Breaking changes may be published at any time.
|
|
21
|
+
|
|
22
|
+
This SDK implements functionality specific to the Web environment, based on the
|
|
23
|
+
[Optimization Core Library](/universal/core/README.md). This SDK is part of the
|
|
24
|
+
[Contentful Optimization SDK Suite](/README.md).
|
|
25
|
+
|
|
26
|
+
<details>
|
|
27
|
+
<summary>Table of Contents</summary>
|
|
28
|
+
<!-- mtoc-start -->
|
|
29
|
+
|
|
30
|
+
- [Getting Started](#getting-started)
|
|
31
|
+
- [Reference Implementations](#reference-implementations)
|
|
32
|
+
- [Configuration](#configuration)
|
|
33
|
+
- [Top-level Configuration Options](#top-level-configuration-options)
|
|
34
|
+
- [Analytics Options](#analytics-options)
|
|
35
|
+
- [Event Builder Options](#event-builder-options)
|
|
36
|
+
- [Fetch Options](#fetch-options)
|
|
37
|
+
- [Personalization Options](#personalization-options)
|
|
38
|
+
- [Optimization Properties](#optimization-properties)
|
|
39
|
+
- [Optimization Methods](#optimization-methods)
|
|
40
|
+
- [Top-level Methods](#top-level-methods)
|
|
41
|
+
- [`consent`](#consent)
|
|
42
|
+
- [`reset`](#reset)
|
|
43
|
+
- [`startAutoTrackingEntryViews`](#startautotrackingentryviews)
|
|
44
|
+
- [`stopAutoTrackingEntryViews`](#stopautotrackingentryviews)
|
|
45
|
+
- [`trackEntryViewForElement`](#trackentryviewforelement)
|
|
46
|
+
- [`untrackEntryViewForElement`](#untrackentryviewforelement)
|
|
47
|
+
- [Personalization Data Resolution Methods](#personalization-data-resolution-methods)
|
|
48
|
+
- [`getCustomFlag`](#getcustomflag)
|
|
49
|
+
- [`personalizeEntry`](#personalizeentry)
|
|
50
|
+
- [`getMergeTagValue`](#getmergetagvalue)
|
|
51
|
+
- [Personalization and Analytics Event Methods](#personalization-and-analytics-event-methods)
|
|
52
|
+
- [`identify`](#identify)
|
|
53
|
+
- [`page`](#page)
|
|
54
|
+
- [`track`](#track)
|
|
55
|
+
- [`trackComponentView`](#trackcomponentview)
|
|
56
|
+
- [`trackFlagView`](#trackflagview)
|
|
57
|
+
- [Entry View Tracking](#entry-view-tracking)
|
|
58
|
+
- [Manual Entry View Tracking](#manual-entry-view-tracking)
|
|
59
|
+
- [Automatic Entry View Tracking](#automatic-entry-view-tracking)
|
|
60
|
+
- [Manual Entry Element Observation](#manual-entry-element-observation)
|
|
61
|
+
- [Automatic Entry Element Observation](#automatic-entry-element-observation)
|
|
62
|
+
- [Interceptors](#interceptors)
|
|
63
|
+
- [Life-cycle Interceptors](#life-cycle-interceptors)
|
|
64
|
+
|
|
65
|
+
<!-- mtoc-end -->
|
|
66
|
+
</details>
|
|
67
|
+
|
|
68
|
+
## Getting Started
|
|
69
|
+
|
|
70
|
+
Install using an NPM-compatible package manager, pnpm for example:
|
|
71
|
+
|
|
72
|
+
```sh
|
|
73
|
+
pnpm install @contentful/optimization-web
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Import the Optimization class; both CJS and ESM module systems are supported, ESM preferred:
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
import Optimization from '@contentful/optimization-web'
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Configure and initialize the Optimization Node SDK:
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
const optimization = new Optimization({ clientId: 'abc123' })
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Reference Implementations
|
|
89
|
+
|
|
90
|
+
- [Web Vanilla](/implementations/web-vanilla/README.md): Example static Web page that renders and
|
|
91
|
+
emits analytics events for personalized content using a vanilla JS drop-in build of the Web SDK
|
|
92
|
+
|
|
93
|
+
## Configuration
|
|
94
|
+
|
|
95
|
+
### Top-level Configuration Options
|
|
96
|
+
|
|
97
|
+
| Option | Required? | Default | Description |
|
|
98
|
+
| -------------------------- | --------- | ----------------------------- | ------------------------------------------------------------------------------ |
|
|
99
|
+
| `allowedEventTypes` | No | `['identify', 'page']` | Allow-listed event types permitted when consent is not set |
|
|
100
|
+
| `analytics` | No | See "Analytics Options" | Configuration specific to the Analytics/Insights API |
|
|
101
|
+
| `app` | No | `undefined` | The application definition used to attribute events to a specific consumer app |
|
|
102
|
+
| `autoTrackEntryViews` | No | `false` | Opt-in automated tracking of entry/component views |
|
|
103
|
+
| `clientId` | Yes | N/A | The Ninetailed API Key which can be found in the Ninetailed Admin app |
|
|
104
|
+
| `defaults` | No | `undefined` | Set of default state values applied on initialization |
|
|
105
|
+
| `environment` | No | `'main'` | The Ninetailed environment configured in the Ninetailed Admin app |
|
|
106
|
+
| `eventBuilder` | No | See "Event Builder Options" | Event builder configuration (channel/library metadata, etc.) |
|
|
107
|
+
| `fetchOptions` | No | See "Fetch Options" | Configuration for Fetch timeout and retry functionality |
|
|
108
|
+
| `getAnonymousId` | No | `undefined` | Function used to obtain an anonymous user identifier |
|
|
109
|
+
| `logLevel` | No | `'error'` | Minimum log level for the default console sin |
|
|
110
|
+
| `personalization` | No | See "Personalization Options" | Configuration specific to the Personalization/Experience API |
|
|
111
|
+
| `preventedComponentEvents` | No | `undefined` | Initial duplication prevention configuration for component events |
|
|
112
|
+
|
|
113
|
+
Configuration method signatures:
|
|
114
|
+
|
|
115
|
+
- `getAnonymousId`: `() => string | undefined`
|
|
116
|
+
|
|
117
|
+
### Analytics Options
|
|
118
|
+
|
|
119
|
+
| Option | Required? | Default | Description |
|
|
120
|
+
| --------------- | --------- | ------------------------------------------ | ------------------------------------------------------------------------ |
|
|
121
|
+
| `baseUrl` | No | `'https://ingest.insights.ninetailed.co/'` | Base URL for the Insights API |
|
|
122
|
+
| `beaconHandler` | No | Built-in beacon API integration | Handler used to enqueue events via the Beacon API or a similar mechanism |
|
|
123
|
+
|
|
124
|
+
Configuration method signatures:
|
|
125
|
+
|
|
126
|
+
- `beaconHandler`: `(url: string | URL, data: BatchInsightsEventArray) => boolean`
|
|
127
|
+
|
|
128
|
+
### Event Builder Options
|
|
129
|
+
|
|
130
|
+
Event builder options should only be supplied when building an SDK on top of Core or any of its
|
|
131
|
+
descendent SDKs.
|
|
132
|
+
|
|
133
|
+
| Option | Required? | Default | Description |
|
|
134
|
+
| ------------------- | --------- | ---------------------------------------------------- | ---------------------------------------------------------------------------------- |
|
|
135
|
+
| `app` | No | `undefined` | The application definition used to attribute events to a specific consumer app |
|
|
136
|
+
| `channel` | No | `'web'` | The channel that identifies where events originate from (e.g. `'web'`, `'mobile'`) |
|
|
137
|
+
| `library` | No | `{ name: 'Optimization Web API', version: '0.0.0' }` | The client library metadata that is attached to all events |
|
|
138
|
+
| `getLocale` | No | Built-in locale resolution | Function used to resolve the locale for outgoing events |
|
|
139
|
+
| `getPageProperties` | No | Built-in page properties resolution | Function that returns the current page properties |
|
|
140
|
+
| `getUserAgent` | No | Built-in user agent resolution | Function used to obtain the current user agent string when applicable |
|
|
141
|
+
|
|
142
|
+
The `channel` option may contain one of the following values:
|
|
143
|
+
|
|
144
|
+
- `web`
|
|
145
|
+
- `mobile`
|
|
146
|
+
- `server`
|
|
147
|
+
|
|
148
|
+
Configuration method signatures:
|
|
149
|
+
|
|
150
|
+
- `getLocale`: `() => string | undefined`
|
|
151
|
+
- `getPageProperties`:
|
|
152
|
+
|
|
153
|
+
```ts
|
|
154
|
+
() => {
|
|
155
|
+
path: string,
|
|
156
|
+
query: Record<string, string>,
|
|
157
|
+
referrer: string,
|
|
158
|
+
search: string,
|
|
159
|
+
title?: string,
|
|
160
|
+
url: string
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
- `getUserAgent`: `() => string | undefined`
|
|
165
|
+
|
|
166
|
+
### Fetch Options
|
|
167
|
+
|
|
168
|
+
Fetch options allow for configuration of a Fetch API-compatible fetch method and the retry/timeout
|
|
169
|
+
logic integrated into the Optimization API Client. Specify the `fetchMethod` when the host
|
|
170
|
+
application environment does not offer a `fetch` method that is compatible with the standard Fetch
|
|
171
|
+
API in its global scope.
|
|
172
|
+
|
|
173
|
+
| Option | Required? | Default | Description |
|
|
174
|
+
| ------------------ | --------- | ----------- | --------------------------------------------------------------------- |
|
|
175
|
+
| `fetchMethod` | No | `undefined` | Signature of a fetch method used by the API clients |
|
|
176
|
+
| `intervalTimeout` | No | `0` | Delay (in milliseconds) between retry attempts |
|
|
177
|
+
| `onFailedAttempt` | No | `undefined` | Callback invoked whenever a retry attempt fails |
|
|
178
|
+
| `onRequestTimeout` | No | `undefined` | Callback invoked when a request exceeds the configured timeout |
|
|
179
|
+
| `requestTimeout` | No | `3000` | Maximum time (in milliseconds) to wait for a response before aborting |
|
|
180
|
+
| `retries` | No | `1` | Maximum number of retry attempts |
|
|
181
|
+
|
|
182
|
+
Configuration method signatures:
|
|
183
|
+
|
|
184
|
+
- `fetchMethod`: `(url: string | URL, init: RequestInit) => Promise<Response>`
|
|
185
|
+
- `onFailedAttempt` and `onRequestTimeout`: `(options: FetchMethodCallbackOptions) => void`
|
|
186
|
+
|
|
187
|
+
### Personalization Options
|
|
188
|
+
|
|
189
|
+
| Option | Required? | Default | Description |
|
|
190
|
+
| ----------------- | --------- | ------------------------------------- | ------------------------------------------------------------------- |
|
|
191
|
+
| `baseUrl` | No | `'https://experience.ninetailed.co/'` | Base URL for the Experience API |
|
|
192
|
+
| `enabledFeatures` | No | `['ip-enrichment', 'location']` | Enabled features which the API may use for each request |
|
|
193
|
+
| `ip` | No | `undefined` | IP address to override the API behavior for IP analysis |
|
|
194
|
+
| `locale` | No | `'en-US'` (in API) | Locale used to translate `location.city` and `location.country` |
|
|
195
|
+
| `plainText` | No | `false` | Sends performance-critical endpoints in plain text |
|
|
196
|
+
| `preflight` | No | `false` | Instructs the API to aggregate a new profile state but not store it |
|
|
197
|
+
|
|
198
|
+
## Optimization Properties
|
|
199
|
+
|
|
200
|
+
- `states`: Returns an object mapping of observables for all internal states
|
|
201
|
+
|
|
202
|
+
The following observables are exposed via the `states` property:
|
|
203
|
+
|
|
204
|
+
- `consent`: The current state of user consent
|
|
205
|
+
- `eventStream`: The latest event to be queued
|
|
206
|
+
- `flags`: All current resolved Custom Flags
|
|
207
|
+
- `profile`: The current user profile
|
|
208
|
+
- `personalizations`: The current collection of selected personalizations
|
|
209
|
+
|
|
210
|
+
Each state except `consent` and `eventStream` is updated internally whenever a response from the
|
|
211
|
+
Experience API contains a new or updated respective state.
|
|
212
|
+
|
|
213
|
+
## Optimization Methods
|
|
214
|
+
|
|
215
|
+
Arguments marked with an asterisk (\*) are always required.
|
|
216
|
+
|
|
217
|
+
### Top-level Methods
|
|
218
|
+
|
|
219
|
+
#### `consent`
|
|
220
|
+
|
|
221
|
+
Updates the user consent state.
|
|
222
|
+
|
|
223
|
+
Arguments:
|
|
224
|
+
|
|
225
|
+
- `accept`: A boolean value specifying whether the user has accepted (`true`) or denied (`false`). A
|
|
226
|
+
value of `undefined` implies that the user has not yet explicitly chosen whether to consent.
|
|
227
|
+
|
|
228
|
+
#### `reset`
|
|
229
|
+
|
|
230
|
+
Resets all internal state _except_ consent. This method expects no arguments and returns no value.
|
|
231
|
+
|
|
232
|
+
#### `startAutoTrackingEntryViews`
|
|
233
|
+
|
|
234
|
+
Starts the process of tracking entry views.
|
|
235
|
+
|
|
236
|
+
Arguments:
|
|
237
|
+
|
|
238
|
+
- `options`: Options to be passed to the element view observer:
|
|
239
|
+
- `dwellTimeMs`: Required time before emitting the view event; default 1,000ms
|
|
240
|
+
- `minVisibleRatio`: Minimum intersection ratio considered "visible"; default `0.1` (10%)
|
|
241
|
+
- `root`: `IntersectionObserver` `root`; default `null` (viewport)
|
|
242
|
+
- `rootMargin`: `IntersectionObserver` `rootMargin`; default `0px`
|
|
243
|
+
- `maxRetries`: Maximum callback retry attempts on failure; default 2
|
|
244
|
+
- `retryBackoffMs`: Initial back-off delay in milliseconds for retries; default 300ms
|
|
245
|
+
- `backoffMultiplier`: Exponential back-off multiplier; default 2
|
|
246
|
+
|
|
247
|
+
> [!WARNING]
|
|
248
|
+
>
|
|
249
|
+
> This method is called internally when the `autoTrackEntryViews` configuration option is set to
|
|
250
|
+
> `true` and consent is given; do not call this method directly unless `autoTrackEntryViews` is set
|
|
251
|
+
> to `false`
|
|
252
|
+
|
|
253
|
+
#### `stopAutoTrackingEntryViews`
|
|
254
|
+
|
|
255
|
+
Stops and cleans up the process of tracking entry views. This method expects no arguments and
|
|
256
|
+
returns no value.
|
|
257
|
+
|
|
258
|
+
> [!WARNING]
|
|
259
|
+
>
|
|
260
|
+
> This method is called internally when the `autoTrackEntryViews` configuration option is set to
|
|
261
|
+
> `true` and consent has not been given; do not call this method directly unless
|
|
262
|
+
> `autoTrackEntryViews` is set to `false`
|
|
263
|
+
|
|
264
|
+
#### `trackEntryViewForElement`
|
|
265
|
+
|
|
266
|
+
Manually observes a given element for automatic entry/component tracking.
|
|
267
|
+
|
|
268
|
+
Arguments:
|
|
269
|
+
|
|
270
|
+
- `element`: A DOM element that directly contains the entry content to be tracked
|
|
271
|
+
- `options`\*: Per-element options used to refine observation
|
|
272
|
+
- `data`: Entry-specific data to send to the `IntersectionObserver` callback; see "Entry View
|
|
273
|
+
Tracking"
|
|
274
|
+
- `dwellTimeMs`: Per-element override of the required time before emitting the view event
|
|
275
|
+
- `maxRetries`: Per-element override of the maximum callback retry attempts on failure
|
|
276
|
+
- `retryBackoffMs`: Per-element override of the initial back-off delay in milliseconds for retries
|
|
277
|
+
- `backoffMultiplier`: Per-element override of the exponential back-off multiplier
|
|
278
|
+
|
|
279
|
+
> [!INFO]
|
|
280
|
+
>
|
|
281
|
+
> This method does not need to be called if the given element is auto-observable as an entry; see
|
|
282
|
+
> "Entry View Tracking"
|
|
283
|
+
|
|
284
|
+
#### `untrackEntryViewForElement`
|
|
285
|
+
|
|
286
|
+
Manually stops observing a given element for automatic entry/component tracking.
|
|
287
|
+
|
|
288
|
+
Arguments:
|
|
289
|
+
|
|
290
|
+
- `element`: A DOM element that directly contains entry content that is already tracked
|
|
291
|
+
|
|
292
|
+
> [!INFO]
|
|
293
|
+
>
|
|
294
|
+
> This method does not need to be called if the given element is auto-observable as an entry; see
|
|
295
|
+
> "Entry View Tracking"
|
|
296
|
+
|
|
297
|
+
### Personalization Data Resolution Methods
|
|
298
|
+
|
|
299
|
+
#### `getCustomFlag`
|
|
300
|
+
|
|
301
|
+
Get the specified Custom Flag's value from the provided changes array, or from the current internal
|
|
302
|
+
state.
|
|
303
|
+
|
|
304
|
+
Arguments:
|
|
305
|
+
|
|
306
|
+
- `name`\*: The name/key of the Custom Flag
|
|
307
|
+
- `changes`: Changes array
|
|
308
|
+
|
|
309
|
+
Returns:
|
|
310
|
+
|
|
311
|
+
- The resolved value for the specified Custom Flag, or `undefined` if it cannot be found.
|
|
312
|
+
|
|
313
|
+
#### `personalizeEntry`
|
|
314
|
+
|
|
315
|
+
Resolve a baseline Contentful entry to a personalized variant using the provided selected
|
|
316
|
+
personalizations, or from the current internal state.
|
|
317
|
+
|
|
318
|
+
Type arguments:
|
|
319
|
+
|
|
320
|
+
- `S`: Entry skeleton type
|
|
321
|
+
- `M`: Chain modifiers
|
|
322
|
+
- `L`: Locale code
|
|
323
|
+
|
|
324
|
+
Arguments:
|
|
325
|
+
|
|
326
|
+
- `entry`\*: The entry to personalize
|
|
327
|
+
- `personalizations`: Selected personalizations
|
|
328
|
+
|
|
329
|
+
Returns:
|
|
330
|
+
|
|
331
|
+
- The resolved personalized entry variant, or the supplied baseline entry if baseline is the
|
|
332
|
+
selected variant or a variant cannot be found.
|
|
333
|
+
|
|
334
|
+
#### `getMergeTagValue`
|
|
335
|
+
|
|
336
|
+
Resolve a "Merge Tag" to a value based on the current (or provided) profile. A "Merge Tag" is a
|
|
337
|
+
special Rich Text fragment supported by Contentful that specifies a profile data member to be
|
|
338
|
+
injected into the Rich Text when rendered.
|
|
339
|
+
|
|
340
|
+
Arguments:
|
|
341
|
+
|
|
342
|
+
- `embeddedNodeEntryTarget`\*: The merge tag entry node to resolve
|
|
343
|
+
- `profile`: The user profile
|
|
344
|
+
|
|
345
|
+
### Personalization and Analytics Event Methods
|
|
346
|
+
|
|
347
|
+
Each method except `trackFlagView` may return an `OptimizationData` object containing:
|
|
348
|
+
|
|
349
|
+
- `changes`: Currently used for Custom Flags
|
|
350
|
+
- `personalizations`: Selected personalizations for the profile
|
|
351
|
+
- `profile`: Profile associated with the evaluated events
|
|
352
|
+
|
|
353
|
+
#### `identify`
|
|
354
|
+
|
|
355
|
+
Identify the current profile/visitor to associate traits with a profile.
|
|
356
|
+
|
|
357
|
+
Arguments:
|
|
358
|
+
|
|
359
|
+
- `payload`\*: Identify event builder arguments object, including an optional `profile` property
|
|
360
|
+
with a `PartialProfile` value that requires only an `id`
|
|
361
|
+
|
|
362
|
+
#### `page`
|
|
363
|
+
|
|
364
|
+
Record a personalization page view.
|
|
365
|
+
|
|
366
|
+
Arguments:
|
|
367
|
+
|
|
368
|
+
- `payload`\*: Page view event builder arguments object, including an optional `profile` property
|
|
369
|
+
with a `PartialProfile` value that requires only an `id`
|
|
370
|
+
|
|
371
|
+
#### `track`
|
|
372
|
+
|
|
373
|
+
Record a personalization custom track event.
|
|
374
|
+
|
|
375
|
+
Arguments:
|
|
376
|
+
|
|
377
|
+
- `payload`\*: Track event builder arguments object, including an optional `profile` property with a
|
|
378
|
+
`PartialProfile` value that requires only an `id`
|
|
379
|
+
|
|
380
|
+
#### `trackComponentView`
|
|
381
|
+
|
|
382
|
+
Record an analytics component view event. When the payload marks the component as "sticky", an
|
|
383
|
+
additional personalization component view is recorded. This method only returns `OptimizationData`
|
|
384
|
+
when the component is marked as "sticky".
|
|
385
|
+
|
|
386
|
+
Arguments:
|
|
387
|
+
|
|
388
|
+
- `payload`\*: Component view event builder arguments object, including an optional `profile`
|
|
389
|
+
property with a `PartialProfile` value that requires only an `id`
|
|
390
|
+
- `duplicationScope`: Arbitrary string that may be used to scope component view duplication
|
|
391
|
+
|
|
392
|
+
#### `trackFlagView`
|
|
393
|
+
|
|
394
|
+
Track a feature flag view via analytics. This is functionally the same as a non-sticky component
|
|
395
|
+
view event.
|
|
396
|
+
|
|
397
|
+
Arguments:
|
|
398
|
+
|
|
399
|
+
- `payload`\*: Component view event builder arguments object, including an optional `profile`
|
|
400
|
+
property with a `PartialProfile` value that requires only an `id`
|
|
401
|
+
- `duplicationScope`: Arbitrary string that may be used to scope component view duplication
|
|
402
|
+
|
|
403
|
+
## Entry View Tracking
|
|
404
|
+
|
|
405
|
+
Tracking of entry/component views is based on the element that contains that entry's content. The
|
|
406
|
+
Optimization Web SDK can automatically track observed entry elements for events such as "component
|
|
407
|
+
views", and it can also automatically observe elements that are marked as entry-related elements.
|
|
408
|
+
|
|
409
|
+
### Manual Entry View Tracking
|
|
410
|
+
|
|
411
|
+
To manually track entry views using custom tracking code, simply call `trackComponentView` with the
|
|
412
|
+
necessary arguments when appropriate.
|
|
413
|
+
|
|
414
|
+
Example:
|
|
415
|
+
|
|
416
|
+
```ts
|
|
417
|
+
optimization.trackComponentView({ entryId: 'abc-123', ... })
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
### Automatic Entry View Tracking
|
|
421
|
+
|
|
422
|
+
Entry/component views can be tracked automatically for observed entry-related elements by simply
|
|
423
|
+
setting the `autoTrackEntryViews` configuration option to `true`, or by calling the
|
|
424
|
+
`startAutoTrackingEntryViews` method if further setup is required depending on the consumer's SDK
|
|
425
|
+
integration solution.
|
|
426
|
+
|
|
427
|
+
### Manual Entry Element Observation
|
|
428
|
+
|
|
429
|
+
To track an element as an entry-related element, call the `trackEntryViewForElement` method with the
|
|
430
|
+
element to be tracked, as well as the `data` option set with the following data members:
|
|
431
|
+
|
|
432
|
+
- `duplicationScope`: Key to differentiate between entry views when the same entry may be tracked in
|
|
433
|
+
multiple locations
|
|
434
|
+
- `entryId`\*: The ID of the content entry to be tracked; should be the selected variant if the
|
|
435
|
+
entry is personalized
|
|
436
|
+
- `personalizationId`: The ID of the personalization/experience entry associated with the content
|
|
437
|
+
entry; only required if the entry is personalized
|
|
438
|
+
- `sticky`: A boolean value that marks that the current user should _always_ see this variant;
|
|
439
|
+
ignored if the entry is not personalized
|
|
440
|
+
- `variantIndex`: The index of the selected variant; only required if the entry is personalized
|
|
441
|
+
|
|
442
|
+
Example:
|
|
443
|
+
|
|
444
|
+
```ts
|
|
445
|
+
optimization.trackEntryViewForElement(element, { data: { entryId: 'abc-123', ... } })
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
### Automatic Entry Element Observation
|
|
449
|
+
|
|
450
|
+
Elements that are associated to entries using the following data attributes will be automatically
|
|
451
|
+
detected for observation and view tracking:
|
|
452
|
+
|
|
453
|
+
- `data-ctfl-duplication-scope`: Key to differentiate between entry views when the same entry may be
|
|
454
|
+
tracked in multiple locations
|
|
455
|
+
- `data-ctfl-entry-id`\*: The ID of the content entry to be tracked; should be the selected variant
|
|
456
|
+
if the entry is personalized
|
|
457
|
+
- `data-ctfl-personalization-id`: The ID of the personalization/experience entry associated with the
|
|
458
|
+
content entry; only required if the entry is personalized
|
|
459
|
+
- `data-ctfl-sticky`: A boolean value that marks that the current user should _always_ see this
|
|
460
|
+
variant; ignored if the entry is not personalized
|
|
461
|
+
- `data-ctfl-variant-index`: The index of the selected variant; only required if the entry is
|
|
462
|
+
personalized
|
|
463
|
+
|
|
464
|
+
Example:
|
|
465
|
+
|
|
466
|
+
```html
|
|
467
|
+
<div data-ctfl-entry-id="abc-123">Entry Content</div>
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
## Interceptors
|
|
471
|
+
|
|
472
|
+
Interceptors may be used to read and/or modify data flowing through the Core SDK.
|
|
473
|
+
|
|
474
|
+
### Life-cycle Interceptors
|
|
475
|
+
|
|
476
|
+
- `event`: Intercepts an event's data _before_ it is queued and/or emitted
|
|
477
|
+
- `state`: Intercepts state data retrieved from an Experience API call _before_ updating the SDK's
|
|
478
|
+
internal state
|
|
479
|
+
|
|
480
|
+
Example interceptor usage:
|
|
481
|
+
|
|
482
|
+
```ts
|
|
483
|
+
optimization.interceptors.event((event) => {
|
|
484
|
+
event.properties.timestamp = new Date().toISOString()
|
|
485
|
+
})
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
> [!WARNING]
|
|
489
|
+
>
|
|
490
|
+
> Interceptors are intended to enable low-level interoperability; to simply read and react to
|
|
491
|
+
> Optimization SDK events, use the `states` observables.
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { type CoreStateful } from '@contentful/optimization-core';
|
|
2
|
+
import type { ElementExistenceObserverOptions, ElementViewCallbackInfo, ElementViewObserver } from './observers';
|
|
3
|
+
/**
|
|
4
|
+
* Data attributes used by the Web SDK to identify and configure tracked entries.
|
|
5
|
+
*/
|
|
6
|
+
export type CtflDataset = DOMStringMap & {
|
|
7
|
+
/** Entry ID associated with the element. */
|
|
8
|
+
ctflEntryId: string;
|
|
9
|
+
/** Optional duplication scope key for de-duplication across views. */
|
|
10
|
+
ctflDuplicationScope?: string;
|
|
11
|
+
/** Optional personalization/experience ID associated with the entry. */
|
|
12
|
+
ctflPersonalizationId?: string;
|
|
13
|
+
/** Whether this component view should be treated as sticky. */
|
|
14
|
+
ctflSticky?: 'true' | 'false';
|
|
15
|
+
/** Optional variant index for personalized variants (non-negative integer). */
|
|
16
|
+
ctflVariantIndex?: string;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Element type representing a Contentful entry with required dataset attributes.
|
|
20
|
+
*
|
|
21
|
+
* @remarks
|
|
22
|
+
* This does not support legacy browsers that do not expose `dataset` on `SVGElement`.
|
|
23
|
+
*/
|
|
24
|
+
export type EntryElement = (HTMLElement | SVGElement) & {
|
|
25
|
+
dataset: CtflDataset;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Type guard that determines whether a given element is a tracked entry element.
|
|
29
|
+
*
|
|
30
|
+
* @param element - Candidate element.
|
|
31
|
+
* @returns `true` if the element exposes a valid `ctflEntryId` dataset property.
|
|
32
|
+
*/
|
|
33
|
+
export declare function isEntryElement(element?: Element): element is EntryElement;
|
|
34
|
+
/**
|
|
35
|
+
* Normalized entry data resolved either from `dataset` or explicit callback data.
|
|
36
|
+
*/
|
|
37
|
+
export interface EntryData {
|
|
38
|
+
/** Optional duplication scope used for de-duplication. */
|
|
39
|
+
duplicationScope?: string;
|
|
40
|
+
/** ID of the Contentful entry. */
|
|
41
|
+
entryId: string;
|
|
42
|
+
/** Optional personalization/experience ID. */
|
|
43
|
+
personalizationId?: string;
|
|
44
|
+
/** Whether the view is sticky. */
|
|
45
|
+
sticky?: boolean;
|
|
46
|
+
/** Optional variant index (non-negative integer). */
|
|
47
|
+
variantIndex?: number;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Type guard that determines whether an arbitrary value is {@link EntryData}.
|
|
51
|
+
*
|
|
52
|
+
* @param data - Unknown value to validate.
|
|
53
|
+
* @returns `true` if the object contains a non-empty entryId string.
|
|
54
|
+
*/
|
|
55
|
+
export declare function isEntryData(data?: unknown): data is EntryData;
|
|
56
|
+
/**
|
|
57
|
+
* Create a callback that wires ElementViewObserver events into `trackComponentView`
|
|
58
|
+
* on the {@link CoreStateful} instance.
|
|
59
|
+
*
|
|
60
|
+
* @param core - Stateful core instance used to send component view events.
|
|
61
|
+
* @returns A callback suitable for use with {@link ElementViewObserver}.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```ts
|
|
65
|
+
* const callback = createAutoTrackingEntryViewCallback(core)
|
|
66
|
+
* const observer = new ElementViewObserver(callback, { dwellTimeMs: 1000 })
|
|
67
|
+
* observer.observe(element, { data: { entryId: 'xyz' } })
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export declare const createAutoTrackingEntryViewCallback: (core: CoreStateful) => (element: Element, info: ElementViewCallbackInfo) => Promise<void>;
|
|
71
|
+
/**
|
|
72
|
+
* Create an {@link ElementExistenceObserverOptions} object that auto-observes
|
|
73
|
+
* and/or unobserves entry elements for a given {@link ElementViewObserver}.
|
|
74
|
+
*
|
|
75
|
+
* @param entryViewObserver - ElementViewObserver instance to manage.
|
|
76
|
+
* @param autoObserveEntryElements - When `true`, automatically start observing
|
|
77
|
+
* newly-added entry elements.
|
|
78
|
+
* @returns Options object suitable for constructing an ElementExistenceObserver.
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```ts
|
|
82
|
+
* const viewObserver = new ElementViewObserver(callback, { dwellTimeMs: 1000 })
|
|
83
|
+
* const existenceOpts = createAutoTrackingEntryExistenceCallback(viewObserver, true)
|
|
84
|
+
* const existenceObserver = new ElementExistenceObserver(existenceOpts)
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
export declare const createAutoTrackingEntryExistenceCallback: (entryViewObserver: ElementViewObserver, autoObserveEntryElements?: boolean) => ElementExistenceObserverOptions;
|
|
88
|
+
//# sourceMappingURL=AutoEntryViewTracking.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AutoEntryViewTracking.d.ts","sourceRoot":"","sources":["../src/AutoEntryViewTracking.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAsB,MAAM,+BAA+B,CAAA;AACrF,OAAO,KAAK,EACV,+BAA+B,EAC/B,uBAAuB,EACvB,mBAAmB,EACpB,MAAM,aAAa,CAAA;AAIpB;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG;IACvC,4CAA4C;IAC5C,WAAW,EAAE,MAAM,CAAA;IACnB,sEAAsE;IACtE,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B,wEAAwE;IACxE,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;IAC7B,+EAA+E;IAC/E,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B,CAAA;AAED;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,WAAW,GAAG,UAAU,CAAC,GAAG;IAAE,OAAO,EAAE,WAAW,CAAA;CAAE,CAAA;AAEhF;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,IAAI,YAAY,CAgBzE;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,0DAA0D;IAC1D,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,kCAAkC;IAClC,OAAO,EAAE,MAAM,CAAA;IACf,8CAA8C;IAC9C,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,kCAAkC;IAClC,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,qDAAqD;IACrD,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,IAAI,SAAS,CAI7D;AAwBD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,mCAAmC,GAC7C,MAAM,YAAY,MACZ,SAAS,OAAO,EAAE,MAAM,uBAAuB,KAAG,OAAO,CAAC,IAAI,CA8CpE,CAAA;AAgBH;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,wCAAwC,GACnD,mBAAmB,mBAAmB,EACtC,kCAAgC,KAC/B,+BAuBD,CAAA"}
|