The Optimization SDK Suite is pre-release (alpha). Breaking changes can be published at any time.
This SDK implements browser-specific optimization behavior on top of the Optimization Core SDK. Use it directly for non-React browser applications, framework adapters, and client-side runtimes that need consent state, anonymous ID persistence, automatic entry interaction tracking, and browser-side event delivery.
If you are integrating a browser application, start with Getting Started, then use Integrating the Optimization Web SDK in a web app for the step-by-step flow. This README keeps the package orientation and common setup options close at hand; generated reference documentation remains the source of truth for exported API signatures.
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 ContentfulOptimization from '@contentful/optimization-web'
Configure and initialize the Optimization Web SDK once per page runtime:
const optimization = new ContentfulOptimization({
clientId: 'your-client-id',
environment: 'main',
contentfulLocales: {
default: 'en-US',
},
})
Initialize the Web SDK once per page runtime. Reuse window.contentfulOptimization or your own
singleton container binding instead of creating additional instances.
The UMD build is available for HTML pages that do not use a bundler:
<script src="https://cdn.jsdelivr.net/npm/@contentful/optimization-web@latest/dist/contentful-optimization-web.umd.js"></script>
<script>
window.contentfulOptimization = new ContentfulOptimization({
clientId: 'your-client-id',
environment: 'main',
contentfulLocales: {
default: 'en-US',
},
})
</script>
Use @contentful/optimization-web for browser applications that need the stateful Web runtime
directly, including consent state, anonymous ID persistence, automatic entry interaction tracking,
and browser-side event delivery.
We recommend starting React applications with
@contentful/optimization-react-web, which wraps this SDK
with React providers, hooks, router adapters, and entry-rendering primitives.
The Web SDK communicates with the Experience API for profile and optimization selection, and with the Insights API for event ingestion.
| Option | Required? | Default | Description |
|---|---|---|---|
clientId |
Yes | N/A | Shared API key for Experience API and Insights API requests |
environment |
No | 'main' |
Contentful environment identifier |
api |
No | See API options below | Experience API and Insights API endpoint and request options |
app |
No | undefined |
Application metadata attached to outgoing event context |
contentfulLocales |
No | undefined |
Contentful locale codes used for SDK-assisted CDA locale resolution |
locale |
No | undefined unless contentfulLocales is set |
Initial app/content locale candidate used to resolve the Contentful locale |
defaults |
No | undefined |
Initial state, commonly including consent or profile values |
allowedEventTypes |
No | ['identify', 'page'] |
Event types allowed before consent is explicitly set |
autoTrackEntryInteraction |
No | { views: false, clicks: false, hovers: false } |
Opt-in automatic tracking for entry views, clicks, and hovers |
cookie |
No | { domain: undefined, expires: 365 } |
Anonymous ID cookie settings |
getAnonymousId |
No | undefined |
Function used to provide an anonymous ID from application-owned identity state |
queuePolicy |
No | SDK defaults | Flush retry behavior and offline queue bounds |
logLevel |
No | 'error' |
Minimum log level for the default console sink |
onEventBlocked |
No | undefined |
Callback invoked when consent or guard logic blocks an event |
Common api options:
| Option | Required? | Default | Description |
|---|---|---|---|
experienceBaseUrl |
No | 'https://experience.ninetailed.co/' |
Base URL for the Experience API |
insightsBaseUrl |
No | 'https://ingest.insights.ninetailed.co/' |
Base URL for the Insights API |
locale |
No | API default | Locale query parameter for localized Experience API responses |
enabledFeatures |
No | ['ip-enrichment', 'location'] |
Experience API features to apply to each request |
preflight |
No | false |
Aggregate a new profile state without storing it |
beaconHandler |
No | Built-in beacon integration | Custom handler for enqueueing Insights API batches when needed |
plainText |
No | false |
Sends performance-critical Experience API endpoints as plain text |
Common fetchOptions are fetchMethod, requestTimeout, retries, intervalTimeout,
onFailedAttempt, and onRequestTimeout. Default retries intentionally apply only to HTTP 503
responses.
Use contentfulLocales.default for single-locale apps. For apps that match browser locale input to
multiple Contentful locales, keep default as the fallback and list the supported Contentful locale
codes:
contentfulLocales: {
default: 'en-US',
supported: ['en-US', 'de-DE', 'fr-FR'],
}
Copy contentfulLocales.default and optional contentfulLocales.supported from Contentful locale
settings or the CMA locale list. The resolved optimization.locale, when present, is the configured
Contentful locale code to use for CDA fetches and default Experience API localization. api.locale
remains an explicit Experience API override. The recommended helper,
withOptimizationLocale(contentfulClient), reads the live SDK locale and injects it into
getEntry() and getEntries() calls when a caller does not provide one; data layers that need
direct control can pass optimization.locale explicitly instead. See
Locale handling in the Optimization SDK Suite
for the full locale model.
Use optimization.setLocale(nextLocale) when the application locale changes. The method validates
the explicit input, resolves it to a configured Contentful locale code when contentfulLocales is
present, updates optimization.locale and optimization.states.locale, and changes the default
Experience API locale unless api.locale is configured. It does not fetch content or refresh
profile state; call page(), identify(), or CDA methods again when the app needs localized data
for the new locale.
For every option, callback payload, and exported type, use the generated Web SDK reference.
Consent is application policy. The SDK stores the consent state and blocks non-allowed events until consent is accepted.
optimization.consent(true)
const data = await optimization.page({
properties: { path: window.location.pathname },
})
page(), identify(), screen(), track(), and sticky trackView() calls can return
optimization data containing profile, selectedOptimizations, and changes.
Fetch Contentful entries in your application layer, then use the SDK to resolve the selected variant:
const optimizationData = await optimization.page({ properties: { path: location.pathname } })
const resolvedEntry = optimization.resolveOptimizedEntry(
baselineEntry,
optimizationData?.selectedOptimizations,
)
Fetch entries with one CDA locale in the app layer. For localized apps, configure
contentfulLocales, then use optimization.withOptimizationLocale(contentfulClient) or pass
optimization.locale explicitly before calling getEntry() or getEntries(). Without
contentfulLocales or an explicit top-level locale, the wrapper omits the CDA locale and lets
Contentful use the space default. Do not pass all-locale CDA responses from withAllLocales or
locale=*; the resolver expects direct single-locale field values. See
Entry personalization and variant resolution
for the entry contract and
Locale handling in the Optimization SDK Suite
for runtime locale behavior.
Use getMergeTagValue() for Contentful Rich Text merge tags and getFlag() for Custom Flags. If a
merge tag references localized profile fields such as location.city or location.country, its
resolved value follows the localized profile data returned by the Experience API. The Web SDK is
stateful, so reading a flag also emits flag-view tracking.
Enable automatic tracking when entry elements follow the standard data-attribute pattern:
const optimization = new ContentfulOptimization({
clientId: 'your-client-id',
autoTrackEntryInteraction: { views: true, clicks: true, hovers: false },
})
Use manual element overrides when the DOM structure does not fit automatic observation:
optimization.tracking.enableElement('views', element, {
data: {
componentId: 'entry-id',
experienceId: 'experience-id',
variantIndex: 0,
},
})
For detection thresholds, data attributes, click and hover behavior, and manual overrides, use the Web SDK integration guide.
The stateful Web SDK exposes observable state for UI feedback and integration glue:
const unsubscribe = optimization.states.profile.subscribe((profile) => {
console.log(profile?.id)
})
Common state streams include consent, profile, selectedOptimizations, changes,
blockedEventStream, eventStream, and preview-panel state. Use the generated reference for the
complete states surface.
localStorage writes fail, the SDK continues with
in-memory state and retries persistence on subsequent writes.reset() clears internal state except consent. Use it when the active profile changes.flush() drains queued Insights API and Experience API events.destroy() releases listeners and singleton ownership for explicit teardown paths such as tests
or hot-reload workflows.OptimizedEntry layer built on this SDK
Contentful ContentfulOptimization Web SDK.
Remarks
Exposes Web-specific utilities such as ContentfulOptimization, beaconHandler, and
LocalStore. Core and transitive API exports are available from dedicated entrypoints:@contentful/optimization-web/core-sdk,@contentful/optimization-web/api-client, and@contentful/optimization-web/api-schemas.