@contentful/optimization-core

中文文档
2.2.1发布于 2026/11/06MITTypeScriptESM + CJS近 30 天下载 6292

Platform-agnostic core SDK for Contentful Optimization

原始使用文档
文档目录13 节
  1. Optimization Core SDK
  2. Getting started
  3. When to use this package
  4. Core variants
  5. Stateful Core
  6. Stateless Core
  7. Common configuration
  8. Campaign attribution
  9. Package surface
  10. Schema entry point
  11. Custom entry-source adapters
  12. Preview support
  13. Related

Contentful Logo

Contentful Personalization & Analytics

Optimization Core SDK

The Optimization Core SDK owns the platform-agnostic optimization state machine, event builders, queues, resolvers, and interceptors used by the application-facing SDKs. Web, React Web, Node, React Native, and native bridge layers build on this package.

We recommend starting application code with a platform SDK rather than Core directly. Use this README when building or maintaining SDK layers, and use Choosing the right SDK when deciding which application-facing package belongs in an integration. Generated reference documentation remains the source of truth for exported API signatures.

[!IMPORTANT]

Upgrading from v1? Follow the v1-to-v2 migration guide before changing package versions.

Table of Contents

Getting started

Install using an NPM-compatible package manager, pnpm for example:

pnpm install @contentful/optimization-core

Choose the stateful or stateless Core class based on the runtime layer you are building:

import { CoreStateful, CoreStateless } from '@contentful/optimization-core'

const statefulOptimization = new CoreStateful({
  spaceId: 'your-space-id',
})
const statelessOptimization = new CoreStateless({
  spaceId: 'your-space-id',
})

Stateful runtimes own durable in-process SDK state. Stateless runtimes bind request-scoped consent, profile state, event context, and Experience API options before calling event methods:

const requestOptimization = statelessOptimization.forRequest({
  consent: true,
  locale: 'en-US',
  eventContext: { locale: 'en-US' },
  experienceOptions: { preflight: false },
  profileId: 'f0837d7dc6344c36a3a0a06c4cde754b',
})

const { accepted, data } = await requestOptimization.page()

When to use this package

Use @contentful/optimization-core when you are building or maintaining an SDK layer that needs the shared optimization state machine, event builders, queueing, resolvers, or interceptors. Most application code uses a platform SDK such as Web, React Web, Node, or React Native instead of depending on Core directly.

Core variants

Stateful Core

CoreStateful is the basis for SDKs that run in stateful JavaScript runtimes such as browsers, mobile JavaScript containers, and native bridge runtimes. It maintains consent, profile, selected optimization, flag, event-stream, blocked-event, and preview-panel state as read-only observables.

reset() discards queued events and invalidates pending state updates. Withdrawing event consent completes that cleanup before subscribers run. destroy() attempts final queue delivery and releases internal subscriptions before another instance can initialize; application subscriptions remain caller-owned. See Core state management for lifecycle and observable behavior.

[!IMPORTANT]

CoreStateful uses module-global state by design. Initialize exactly one stateful instance per JavaScript runtime and reuse it.

Stateless Core

CoreStateless is the basis for SDKs that run in stateless environments such as Node servers and server-side functions. It does not store consent or profile state between requests. Consumers call forRequest() to bind consent, event context, and Experience options for one incoming request. Pass profileId for Experience continuity or a full Profile through profile for Insights. Experience responses update the request-local profile for subsequent calls.

Request clients also expose a readonly eventBuilder facade for constructing identify, page, screen, and track payloads with request context and locale defaults. Construction uses the shared builder's metadata and providers without applying request consent, running submission interceptors, or updating request state. Use direct request event methods for normal submission; low-level API calls with built events do not automatically apply that processing. The root SDK's eventBuilder is unbound. See the Node request-scoped events example.

Common configuration

Shared Core configuration:

OptionRequired?DefaultDescription
spaceIdYesN/AContentful Space identifier for Experience and Insights API requests
environmentNo'master'Contentful space environment identifier for Experience and Insights APIs
apiNoSee API options belowExperience API and Insights API endpoint options
contentfulNoundefinedApp-owned contentful.js client, default query, and cache
eventBuilderNoSDK-layer defaultsEvent metadata overrides for platform SDK authors
fetchOptionsNoSDK defaultsFetch timeout and retry behavior
logLevelNo'error'Minimum log level for the default console sink

Consent and event configuration:

OptionRequired?DefaultDescription
allowedEventTypesNo[]Event types allowed before consent is explicitly set
onEventBlockedNoundefinedCallback invoked when consent or guard logic blocks an event

Core itself fails closed before consent. Platform SDKs set runtime-specific defaults for the event types that make sense in that runtime, such as browser identify/page, server identify/page, and mobile identify/screen.

Stateful-only configuration:

OptionRequired?DefaultDescription
defaultsNoundefinedInitial state, commonly including consent, persistence consent, or profile values
getAnonymousIdNoundefinedFunction used to provide an anonymous ID from application-owned identity state
queuePolicyNoSDK defaultsFlush retry behavior and offline queue bounds

Persistence consent controls durable profile-continuity storage for SDKs with runtime storage: profile, anonymous ID, changes, and selected optimization caches. Event consent, stored consent decisions, and debug state are tracked separately.

Common api options:

OptionApplies toDefaultDescription
experienceBaseUrlAll'https://experience.ninetailed.co/'Base URL for the Experience API
insightsBaseUrlAll'https://ingest.insights.ninetailed.co/'Base URL for the Insights API
enabledFeaturesAll['ip-enrichment', 'location']Experience API features for each request
locationAllAPI fallbackDefault request location for single-profile Experience mutations
ipStatefulundefinedIP address override for Experience API analysis
plainTextStatefultrue for single-profile mutationsSends single-profile Experience mutations as text
preflightStatefulfalseAggregates a profile state without storing it

Both Core constructors accept api.location; platform SDKs inherit that configuration. Stateless request clients override it through forRequest({ experienceOptions: { location } }):

const optimization = new CoreStateless({
  spaceId: 'your-space-id',
  api: { location: { countryCode: 'DE' } },
})
const requestOptimization = optimization.forRequest({
  consent: true,
  experienceOptions: { location: {} },
})
await requestOptimization.page()

The request location replaces the entire constructor default, including an explicit {}. Event context.location remains separate and takes precedence over matching request fields at the API. An empty request location supplies an empty default instead of API geolocation; it does not clear existing profile location. This is request evaluation input, not a permanent profile lock. For backend precedence and profile continuity, see Location inputs and profile updates.

When plainText is omitted, single-profile Experience mutation/event requests use text/plain. Pass plainText: false to send JSON. Experience batch profile updates still default to JSON.

In stateless environments, pass ip, locale, plainText, and preflight as experienceOptions when creating the request-bound client instead of constructor config. Pass request-specific Insights API options, such as a last-chance beacon sender, as insightsOptions.

Core-backed stateful SDKs can accept an initial top-level locale and runtime setLocale(locale) calls. They expose that SDK Experience API and default event locale through the live locale getter and states.locale observable. Stateless server SDKs should pass the request-scoped SDK locale as forRequest({ locale }); advanced callers can still pass experienceOptions.locale when no request locale is supplied.

Applications own Contentful CDA locale selection and pass that locale directly to their Contentful client. For the full locale model, see Locale handling in the Optimization SDK Suite.

Common fetchOptions are fetchMethod, requestTimeout, retries, intervalTimeout, onFailedAttempt, and onRequestTimeout. Default retries intentionally apply only to HTTP 503 responses.

For every option, callback payload, and exported type, use the generated Core SDK reference.

Campaign attribution

Event builders use explicit campaign data when supplied. Otherwise, they infer context.campaign from utm_campaign, utm_source, utm_medium, utm_term, and utm_content parameters in page.url. They do not inspect page.referrer.

For a page event, properties.url supplies the inferred campaign when it contains at least one supported UTM parameter. Otherwise, the builder uses the resolved context.page.url. That resolved URL comes from an explicit page.url, or from getPageProperties() when event input does not override it. If neither eligible URL parses with a supported UTM parameter, the inferred campaign is empty.

Package surface

Core exposes reusable primitives for SDK layers:

SurfacePurpose
CoreStatefulStateful optimization runtime for browser, mobile, and bridge SDKs
CoreStatelessStateless optimization runtime for server SDKs
Event methodsidentify, page, screen, track, trackView, trackClick, etc.
Resolution and fetch helpersresolveOptimizedEntry, fetchContentfulEntry, fetchContentfulEntries, fetchOptimizedEntry, prefetchManagedEntries, getMergeTagValue, and getFlag
Selection handoff helpersFramework-neutral selection state, cache keys, cache-safety warnings, bulk entry resolution, and createHandoffFromSelections
Current-state trackingAcceptedCurrentStateTracker for SDK-owned page or screen adapters
statesStateful observable state streams
InterceptorsFirst-party hooks for event and state lifecycle customization
Queue policy and fetch helpersShared retry, flush, timeout, and offline buffering behavior
Signal and observable utilitiesLightweight reactive primitives used internally by stateful SDK layers
api-schemas entry pointCDA schemas owned by Core, plus Experience API and Insights API schema pass-throughs

Schema entry point

@contentful/optimization-core/api-schemas owns the Contentful CDA schemas, inferred types, and helpers used by Core. It also passes through the Experience API and Insights API validation surface from @contentful/optimization-api-client/api-schemas, so SDK layers can retain a single aggregate schema import when that is useful:

import { OptimizationConfig, ExperienceResponse } from '@contentful/optimization-core/api-schemas'

For direct Experience API or Insights API work, import validation contracts from @contentful/optimization-api-client/api-schemas to use their owning package. Do not add imports from the deprecated @contentful/optimization-api-schemas compatibility package.

When a contentful.js client is available, prefer SDK-managed fetching. Configure contentful: { client, defaultQuery?, cache? }, then identify each entry by ID or by content type and slug:

await sdk.fetchOptimizedEntry({
  contentType: 'page',
  slug: 'home',
  slugField: 'slug',
  entryQuery: { locale: 'en-US' },
})

slugField defaults to slug. Managed calls merge defaultQuery, entryQuery, an SDK or request locale fallback, and include: 10. Slug lookup then enforces content_type, fields.<slugField>, and limit: 2, so those selectors override conflicting query values. It throws these errors when the result isn't unique:

Contentful entry not found for content type "<contentType>" where "fields.<slugField>" equals "<slug>".
Multiple Contentful entries found for content type "<contentType>" where "fields.<slugField>" equals "<slug>".

ID lookups retain batching for same-query uncached entries and split large batches into 100-ID chunks. Results preserve descriptor order and duplicates. Managed fetching caches entries per SDK instance by default; set contentful.cache: false to disable the cache or call clearContentfulEntryCache() to clear it. Slug prefetch handoffs nest the normalized descriptor under managedEntry and retain the fetched entry's sys.id in entryId. resolveOptimizedEntry() remains the manual path for entries the app already fetched. Stateful Core uses current selections when omitted, request-bound stateless clients use the latest accepted selections and request locale fallback, and root stateless callers pass explicit selections.

Resolver types accept one skeleton or a union of every possible baseline and variant skeleton. See Entry optimization and variant resolution for heterogeneous entry typing and narrowing.

Framework SDKs use Core selection handoff helpers when server, static, or edge rendering already knows the selected optimizations. createHandoffFromSelections() records that explicit selection state and cache metadata without choosing browser hydration behavior. Cacheable public permutations can use createPublicPermutationCacheMetadata() for a deterministic key and optional caller-owned invalidation tags. resolveEntriesForSelections() resolves a batch of baseline entries in input order for server-rendered markup, and createSelectionFingerprint(), createOptimizationCacheKey(), getOptimizationCacheSafetyWarnings(), and assertOptimizationCacheSafety() support customer-owned cache keys and diagnostics.

Do not pass all-locale CDA responses from withAllLocales or locale=*; optimization fields such as fields.nt_experiences and fields.nt_variants must be direct single-locale field values. See Entry optimization and variant resolution for the entry contract and Locale handling in the Optimization SDK Suite for the broader locale model.

Custom entry-source adapters

@contentful/optimization-core/entry-source is an advanced subpath for custom JavaScript runtime or framework adapters that cannot use an official Web, React Web, React Native, Node, or native SDK surface. It is not part of the root Core API posture and is not the preferred path for application integrations.

Import OptimizedEntrySourceController when an adapter accepts a direct baselineEntry, a managed entry ID, or a managed content-type/slug source. The controller owns source lifecycle and query keying, SDK readiness/loading/error snapshots, stale request protection, and disconnect() cleanup. After a slug fetch, snapshots and downstream tracking use the fetched entry's sys.id. createOptimizedEntryLoadingEntry(entryId) creates a stable placeholder Contentful entry for ID loading states.

The entry-source controller does not own rendering, variant resolution, tracking, consent, Experience API calls, or Contentful client creation. After a snapshot contains baselineEntry, the adapter still calls resolveOptimizedEntry(), renders the result, and wires any runtime-specific tracking.

The generated reference owns method arguments, return types, callback payload shapes, and inherited members. Keep this README focused on package role and maintainer orientation.

Preview support

Preview-panel helpers live under the internal preview-support entry. They are used by first-party preview surfaces to register preview state bridges, apply optimization overrides, and map Contentful entries for local authoring workflows.

Application code must not use preview support directly unless it is building a first-party preview surface.

版本与发布记录

@contentful/optimization-core 共发布 28 个版本,首次发布于 2026/02/03;过去 12 个月发布了 28 个版本。

版本发布日期距今
2.2.1latest2026/11/064 天前
2.2.02026/11/046 天前
2.1.12026/10/2220 天前
2.1.02026/10/1922 天前
2.0.22026/10/1625 天前
2.0.12026/09/231 个月前

其他发布通道:alpha → 0.1.0-alpha。

关于 @contentful/optimization-core 的常见问题

@contentful/optimization-core 是什么?

Platform-agnostic core SDK for Contentful Optimization

如何安装 @contentful/optimization-core?

在项目目录运行 npm install @contentful/optimization-core,或使用 pnpm add / yarn add / bun add。

@contentful/optimization-core 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@contentful/optimization-core 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@contentful/optimization-core 可以商用吗?

@contentful/optimization-core 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@contentful/optimization-core 的下载量有多少?

根据 npm 官方下载统计,@contentful/optimization-core 在 2026/10/11 – 2026/11/09 这 30 天内被下载 6,292 次,日均约 210 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@contentful/optimization-core 还在维护吗?

最新版本 2.2.1 发布于 2026/11/06(4 天前);至今共发布 28 个版本,其中过去 12 个月发布了 28 个;首次发布于 2026/02/03。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。