This SDK implements functionality specific to the Web environment, based on the Optimization Core Library. This SDK is part of the Contentful Optimization SDK Suite.
Install using an NPM-compatible package manager, pnpm for example:
pnpm install @contentful/optimization-web
Import the Optimization class; both CJS and ESM module systems are supported, ESM preferred:
import Optimization from '@contentful/optimization-web'
Configure and initialize the Optimization Node SDK:
const optimization = new Optimization({ clientId: 'abc123' })
| Option | Required? | Default | Description |
|---|---|---|---|
allowedEventTypes |
No | ['identify', 'page'] |
Allow-listed event types permitted when consent is not set |
analytics |
No | See "Analytics Options" | Configuration specific to the Analytics/Insights API |
app |
No | undefined |
The application definition used to attribute events to a specific consumer app |
autoTrackEntryViews |
No | false |
Opt-in automated tracking of entry/component views |
clientId |
Yes | N/A | The Ninetailed API Key which can be found in the Ninetailed Admin app |
defaults |
No | undefined |
Set of default state values applied on initialization |
environment |
No | 'main' |
The Ninetailed environment configured in the Ninetailed Admin app |
eventBuilder |
No | See "Event Builder Options" | Event builder configuration (channel/library metadata, etc.) |
fetchOptions |
No | See "Fetch Options" | Configuration for Fetch timeout and retry functionality |
getAnonymousId |
No | undefined |
Function used to obtain an anonymous user identifier |
logLevel |
No | 'error' |
Minimum log level for the default console sin |
personalization |
No | See "Personalization Options" | Configuration specific to the Personalization/Experience API |
preventedComponentEvents |
No | undefined |
Initial duplication prevention configuration for component events |
Configuration method signatures:
getAnonymousId: () => string | undefined| Option | Required? | Default | Description |
|---|---|---|---|
baseUrl |
No | 'https://ingest.insights.ninetailed.co/' |
Base URL for the Insights API |
beaconHandler |
No | Built-in beacon API integration | Handler used to enqueue events via the Beacon API or a similar mechanism |
Configuration method signatures:
beaconHandler: (url: string | URL, data: BatchInsightsEventArray) => booleanEvent builder options should only be supplied when building an SDK on top of Core or any of its descendent SDKs.
| Option | Required? | Default | Description |
|---|---|---|---|
app |
No | undefined |
The application definition used to attribute events to a specific consumer app |
channel |
No | 'web' |
The channel that identifies where events originate from (e.g. 'web', 'mobile') |
library |
No | { name: 'Optimization Web API', version: '0.0.0' } |
The client library metadata that is attached to all events |
getLocale |
No | Built-in locale resolution | Function used to resolve the locale for outgoing events |
getPageProperties |
No | Built-in page properties resolution | Function that returns the current page properties |
getUserAgent |
No | Built-in user agent resolution | Function used to obtain the current user agent string when applicable |
The channel option may contain one of the following values:
webmobileserverConfiguration method signatures:
getLocale: () => string | undefined
getPageProperties:
() => {
path: string,
query: Record<string, string>,
referrer: string,
search: string,
title?: string,
url: string
}
getUserAgent: () => string | undefined
Fetch options allow for configuration of a Fetch API-compatible fetch method and the retry/timeout
logic integrated into the Optimization API Client. Specify the fetchMethod when the host
application environment does not offer a fetch method that is compatible with the standard Fetch
API in its global scope.
| Option | Required? | Default | Description |
|---|---|---|---|
fetchMethod |
No | undefined |
Signature of a fetch method used by the API clients |
intervalTimeout |
No | 0 |
Delay (in milliseconds) between retry attempts |
onFailedAttempt |
No | undefined |
Callback invoked whenever a retry attempt fails |
onRequestTimeout |
No | undefined |
Callback invoked when a request exceeds the configured timeout |
requestTimeout |
No | 3000 |
Maximum time (in milliseconds) to wait for a response before aborting |
retries |
No | 1 |
Maximum number of retry attempts |
Configuration method signatures:
fetchMethod: (url: string | URL, init: RequestInit) => Promise<Response>onFailedAttempt and onRequestTimeout: (options: FetchMethodCallbackOptions) => void| Option | Required? | Default | Description |
|---|---|---|---|
baseUrl |
No | 'https://experience.ninetailed.co/' |
Base URL for the Experience API |
enabledFeatures |
No | ['ip-enrichment', 'location'] |
Enabled features which the API may use for each request |
ip |
No | undefined |
IP address to override the API behavior for IP analysis |
locale |
No | 'en-US' (in API) |
Locale used to translate location.city and location.country |
plainText |
No | false |
Sends performance-critical endpoints in plain text |
preflight |
No | false |
Instructs the API to aggregate a new profile state but not store it |
states: Returns an object mapping of observables for all internal statesThe following observables are exposed via the states property:
consent: The current state of user consenteventStream: The latest event to be queuedflags: All current resolved Custom Flagsprofile: The current user profilepersonalizations: The current collection of selected personalizationsEach state except consent and eventStream is updated internally whenever a response from the
Experience API contains a new or updated respective state.
Arguments marked with an asterisk (*) are always required.
consentUpdates the user consent state.
Arguments:
accept: A boolean value specifying whether the user has accepted (true) or denied (false). A
value of undefined implies that the user has not yet explicitly chosen whether to consent.resetResets all internal state except consent. This method expects no arguments and returns no value.
startAutoTrackingEntryViewsStarts the process of tracking entry views.
Arguments:
options: Options to be passed to the element view observer:
dwellTimeMs: Required time before emitting the view event; default 1,000msminVisibleRatio: Minimum intersection ratio considered "visible"; default 0.1 (10%)root: IntersectionObserver root; default null (viewport)rootMargin: IntersectionObserver rootMargin; default 0pxmaxRetries: Maximum callback retry attempts on failure; default 2retryBackoffMs: Initial back-off delay in milliseconds for retries; default 300msbackoffMultiplier: Exponential back-off multiplier; default 2This method is called internally when the autoTrackEntryViews configuration option is set to
true and consent is given; do not call this method directly unless autoTrackEntryViews is set
to false
stopAutoTrackingEntryViewsStops and cleans up the process of tracking entry views. This method expects no arguments and returns no value.
This method is called internally when the autoTrackEntryViews configuration option is set to
true and consent has not been given; do not call this method directly unless
autoTrackEntryViews is set to false
trackEntryViewForElementManually observes a given element for automatic entry/component tracking.
Arguments:
element: A DOM element that directly contains the entry content to be trackedoptions*: Per-element options used to refine observation
data: Entry-specific data to send to the IntersectionObserver callback; see "Entry View
Tracking"dwellTimeMs: Per-element override of the required time before emitting the view eventmaxRetries: Per-element override of the maximum callback retry attempts on failureretryBackoffMs: Per-element override of the initial back-off delay in milliseconds for retriesbackoffMultiplier: Per-element override of the exponential back-off multiplier[!INFO]
This method does not need to be called if the given element is auto-observable as an entry; see "Entry View Tracking"
untrackEntryViewForElementManually stops observing a given element for automatic entry/component tracking.
Arguments:
element: A DOM element that directly contains entry content that is already tracked[!INFO]
This method does not need to be called if the given element is auto-observable as an entry; see "Entry View Tracking"
getCustomFlagGet the specified Custom Flag's value from the provided changes array, or from the current internal state.
Arguments:
name*: The name/key of the Custom Flagchanges: Changes arrayReturns:
undefined if it cannot be found.personalizeEntryResolve a baseline Contentful entry to a personalized variant using the provided selected personalizations, or from the current internal state.
Type arguments:
S: Entry skeleton typeM: Chain modifiersL: Locale codeArguments:
entry*: The entry to personalizepersonalizations: Selected personalizationsReturns:
getMergeTagValueResolve a "Merge Tag" to a value based on the current (or provided) profile. A "Merge Tag" is a special Rich Text fragment supported by Contentful that specifies a profile data member to be injected into the Rich Text when rendered.
Arguments:
embeddedNodeEntryTarget*: The merge tag entry node to resolveprofile: The user profileEach method except trackFlagView may return an OptimizationData object containing:
changes: Currently used for Custom Flagspersonalizations: Selected personalizations for the profileprofile: Profile associated with the evaluated eventsidentifyIdentify the current profile/visitor to associate traits with a profile.
Arguments:
payload*: Identify event builder arguments object, including an optional profile property
with a PartialProfile value that requires only an idpageRecord a personalization page view.
Arguments:
payload*: Page view event builder arguments object, including an optional profile property
with a PartialProfile value that requires only an idtrackRecord a personalization custom track event.
Arguments:
payload*: Track event builder arguments object, including an optional profile property with a
PartialProfile value that requires only an idtrackComponentViewRecord an analytics component view event. When the payload marks the component as "sticky", an
additional personalization component view is recorded. This method only returns OptimizationData
when the component is marked as "sticky".
Arguments:
payload*: Component view event builder arguments object, including an optional profile
property with a PartialProfile value that requires only an idduplicationScope: Arbitrary string that may be used to scope component view duplicationtrackFlagViewTrack a feature flag view via analytics. This is functionally the same as a non-sticky component view event.
Arguments:
payload*: Component view event builder arguments object, including an optional profile
property with a PartialProfile value that requires only an idduplicationScope: Arbitrary string that may be used to scope component view duplicationTracking of entry/component views is based on the element that contains that entry's content. The Optimization Web SDK can automatically track observed entry elements for events such as "component views", and it can also automatically observe elements that are marked as entry-related elements.
To manually track entry views using custom tracking code, simply call trackComponentView with the
necessary arguments when appropriate.
Example:
optimization.trackComponentView({ entryId: 'abc-123', ... })
Entry/component views can be tracked automatically for observed entry-related elements by simply
setting the autoTrackEntryViews configuration option to true, or by calling the
startAutoTrackingEntryViews method if further setup is required depending on the consumer's SDK
integration solution.
To track an element as an entry-related element, call the trackEntryViewForElement method with the
element to be tracked, as well as the data option set with the following data members:
duplicationScope: Key to differentiate between entry views when the same entry may be tracked in
multiple locationsentryId*: The ID of the content entry to be tracked; should be the selected variant if the
entry is personalizedpersonalizationId: The ID of the personalization/experience entry associated with the content
entry; only required if the entry is personalizedsticky: A boolean value that marks that the current user should always see this variant;
ignored if the entry is not personalizedvariantIndex: The index of the selected variant; only required if the entry is personalizedExample:
optimization.trackEntryViewForElement(element, { data: { entryId: 'abc-123', ... } })
Elements that are associated to entries using the following data attributes will be automatically detected for observation and view tracking:
data-ctfl-duplication-scope: Key to differentiate between entry views when the same entry may be
tracked in multiple locationsdata-ctfl-entry-id*: The ID of the content entry to be tracked; should be the selected variant
if the entry is personalizeddata-ctfl-personalization-id: The ID of the personalization/experience entry associated with the
content entry; only required if the entry is personalizeddata-ctfl-sticky: A boolean value that marks that the current user should always see this
variant; ignored if the entry is not personalizeddata-ctfl-variant-index: The index of the selected variant; only required if the entry is
personalizedExample:
<div data-ctfl-entry-id="abc-123">Entry Content</div>
Interceptors may be used to read and/or modify data flowing through the Core SDK.
event: Intercepts an event's data before it is queued and/or emittedstate: Intercepts state data retrieved from an Experience API call before updating the SDK's
internal stateExample interceptor usage:
optimization.interceptors.event((event) => {
event.properties.timestamp = new Date().toISOString()
})
Interceptors are intended to enable low-level interoperability; to simply read and react to
Optimization SDK events, use the states observables.