Contentful Personalization & Analytics
    Preparing search index...

    Module @contentful/optimization-react-native - v0.0.0

    Contentful Optimization React Native SDK.

    Implements React Native-specific functionality on top of the ContentfulOptimization Core Library. Provides components for optimization, analytics tracking, and a preview panel for debugging selected optimizations during development.

    Contentful Logo

    Contentful Personalization & Analytics

    Optimization React Native SDK

    Guides · Reference · Contributing

    Warning

    The Optimization SDK Suite is pre-release (alpha). Breaking changes can be published at any time.

    The Optimization React Native SDK provides a stateful mobile runtime on top of the Optimization Core SDK. It adds React providers, hooks, OptimizedEntry, screen tracking, optional offline-aware event delivery, and in-app preview-panel support for React Native applications.

    If you are integrating a React Native application, start with Getting Started, then use Integrating the Optimization React Native SDK in a React Native 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.

    Table of Contents

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

    pnpm install @contentful/optimization-react-native @react-native-async-storage/async-storage
    

    For offline support, also install NetInfo:

    pnpm install @react-native-community/netinfo
    

    Wrap the app with OptimizationRoot near the top of the component tree:

    import { OptimizationRoot } from '@contentful/optimization-react-native'

    export default function App() {
    return (
    <OptimizationRoot
    clientId="your-client-id"
    environment="main"
    contentfulLocales={{
    default: 'en-US',
    }}
    >
    <YourApp />
    </OptimizationRoot>
    )
    }

    For non-component ownership paths, create the SDK instance explicitly and call methods directly:

    import { ContentfulOptimization } from '@contentful/optimization-react-native'

    const optimization = await ContentfulOptimization.create({
    clientId: 'your-client-id',
    environment: 'main',
    contentfulLocales: {
    default: 'en-US',
    },
    })

    Use @contentful/optimization-react-native for React Native applications that need mobile optimization, persisted state, screen tracking, entry interaction tracking, offline behavior, and preview-panel support. Native iOS and Android package work also exists in this monorepo for teams that need platform-native integration surfaces.

    OptimizationRoot accepts Core stateful configuration directly, plus React Native-specific props. Only clientId is required.

    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
    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; changing this prop updates the owned SDK locale
    defaults No undefined Initial state, commonly including consent or profile values
    allowedEventTypes No ['identify', 'screen'] Event types allowed before consent is explicitly set
    trackEntryInteraction No { views: true, taps: false } Default view and tap tracking for OptimizedEntry components
    liveUpdates No false Whether optimized entries react continuously to SDK state changes
    previewPanel No undefined Enables the in-app preview panel when provided with enabled: true
    onStatesReady No undefined Provider-managed app-level state subscription hook
    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 undefined Custom handler for enqueueing Insights API batches when needed

    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 device locale input to multiple Contentful locales, keep default as the fallback and list the supported Contentful locale codes:

    <OptimizationRoot
    clientId="your-client-id"
    contentfulLocales={{
    default: 'en-US',
    supported: ['en-US', 'de-DE', 'fr-FR'],
    }}
    >
    <YourApp />
    </OptimizationRoot>

    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, and withOptimizationLocale(contentfulClient) reads the live SDK locale and injects it into getEntry() and getEntries() calls when a caller does not provide one. See Locale handling in the Optimization SDK Suite for the full locale model.

    For provider-owned SDK instances, changing the locale prop calls sdk.setLocale() after initialization while the rest of the SDK config remains initialization-scoped. Locale updates do not fetch content or refresh profile state; trigger your app's normal screen(), identify(), or CDA fetch flow when localized data needs to change.

    For every prop, callback payload, and exported type, use the generated React Native SDK reference.

    OptimizationRoot owns async React Native SDK initialization. It renders no children while platform state setup is pending, runs any onStatesReady callback, and only then renders provider children. This matches the React Web provider contract, but React Native uses async effect scheduling because storage and platform setup cannot be completed before paint.

    OptimizedEntry resolves optimized Contentful entries and passes non-optimized entries through unchanged:

    import { OptimizedEntry } from '@contentful/optimization-react-native'

    function HeroEntry({ entry }) {
    return (
    <OptimizedEntry baselineEntry={entry}>
    {(resolvedEntry) => <Hero data={resolvedEntry.fields} />}
    </OptimizedEntry>
    )
    }

    Fetch Contentful entries in your app layer. For optimized entries, request linked entries deeply enough for the baseline and variants, commonly with include: 10.

    Use one CDA locale for entries passed to OptimizedEntry or useEntryResolver(). For localized apps, configure contentfulLocales, then use the recommended optimization.withOptimizationLocale(contentfulClient) helper or pass optimization.locale explicitly so entry fetches use the SDK-resolved locale. 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=*; these APIs expect 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 useEntryResolver() when a component needs manual entry resolution without the OptimizedEntry wrapper:

    import { useEntryResolver } from '@contentful/optimization-react-native'

    function HeroData({ entry }) {
    const { resolveEntry } = useEntryResolver()
    const resolvedEntry = resolveEntry(entry)

    return <Hero data={resolvedEntry.fields} />
    }

    Track entry interactions

    Entry tracking records views and taps for Contentful entries, not arbitrary UI components. Global defaults live on OptimizationRoot; individual OptimizedEntry components can override them:

    <OptimizationRoot clientId="your-client-id" trackEntryInteraction={{ views: true, taps: true }}>
    <OptimizedEntry baselineEntry={entry} trackViews={true} trackTaps={false}>
    {(resolvedEntry) => <Card entry={resolvedEntry} />}
    </OptimizedEntry>
    </OptimizationRoot>

    Wrap scrollable screens with OptimizationScrollProvider so view tracking uses actual scroll position instead of only screen dimensions.

    Use OptimizationNavigationContainer to emit screen events from React Navigation changes:

    <OptimizationNavigationContainer>
    {(navigationProps) => (
    <NavigationContainer {...navigationProps}>{/* navigators */}</NavigationContainer>
    )}
    </OptimizationNavigationContainer>

    Use useScreenTracking() for screen-level control and useScreenTrackingCallback() when names are derived from navigation state or other dynamic data.

    Use onStatesReady when application code needs SDK state subscriptions that line up with provider initialization. The provider calls it after async SDK state setup completes and before child screen, navigation, or entry effects can emit events.

    <OptimizationRoot
    clientId="your-client-id"
    onStatesReady={(states) => {
    const subscriptions = [
    states.eventStream.subscribe((event) => {
    if (event) devToolsPanel.logEvent(event)
    }),
    states.blockedEventStream.subscribe((blocked) => {
    if (blocked) devToolsPanel.logBlockedEvent(blocked)
    }),
    ]

    return () => {
    subscriptions.forEach((subscription) => subscription.unsubscribe())
    }
    }}
    >
    <YourApp />
    </OptimizationRoot>

    The callback receives only sdk.states. Use regular hooks and React effects for component-local UI state under the provider.

    Use OptimizationProvider directly with a pre-built sdk only when an application or framework adapter owns initialization. Without onStatesReady, children render immediately because the SDK is already available. When onStatesReady is provided, the provider waits until those subscribers are attached before children mount and runs the returned cleanup on unmount. In both cases, it does not call destroy() on the injected SDK.

    liveUpdates controls whether OptimizedEntry continuously reacts to SDK state changes. The preview panel always forces live updates on while it is open.

    <OptimizationRoot clientId="your-client-id" liveUpdates={true}>
    <OptimizedEntry baselineEntry={entry} liveUpdates={false}>
    {(resolvedEntry) => <Card entry={resolvedEntry} />}
    </OptimizedEntry>
    </OptimizationRoot>

    Enable the preview panel only in authoring or development flows and provide a Contentful client:

    <OptimizationRoot clientId="your-client-id" previewPanel={{ enabled: __DEV__, contentfulClient }}>
    <YourApp />
    </OptimizationRoot>

    AsyncStorage persists SDK state across app launches. When NetInfo is installed, the SDK can queue events while the device is offline and flush them after connectivity returns. Tune queue bounds and retry behavior with queuePolicy when the defaults are not appropriate for your app.

    • Consent policy remains application-owned. The SDK stores consent and blocks non-allowed events until consent is accepted.
    • ContentfulOptimization.create(...) is asynchronous. Prefer OptimizationRoot when React needs to own initialization.
    • View tracking defaults to enabled; tap tracking defaults to disabled.
    • Live updates default to disabled so entries lock to the first resolved value unless enabled globally, per component, or by the preview panel.
    • React Native compatibility polyfills are imported automatically for Iterator Helpers, crypto.randomUUID(), and crypto.getRandomValues(); applications do not need additional setup beyond installing this SDK and its documented dependencies.
    • Call destroy() before creating replacement instances in tests or hot-reload workflows.

    Classes

    ContentfulOptimization

    Interfaces

    ContentfulClient
    ContentfulEntry
    ContentfulEntryCollection
    InteractionTrackingContextValue
    LiveUpdatesContextValue
    LiveUpdatesProviderProps
    OptimizationNavigationContainerProps
    OptimizationRootProps
    OptimizationScrollProviderProps
    OptimizedEntryProps
    PreviewPanelConfig
    PreviewPanelOverlayProps
    PreviewPanelProps
    ScrollContextValue
    UseEntryResolverResult
    UseScreenTrackingOptions
    UseScreenTrackingReturn
    UseTapTrackingOptions
    UseTapTrackingReturn
    UseViewportTrackingOptions
    UseViewportTrackingReturn

    Type Aliases

    EntryInteraction
    OnStatesReady
    OptimizationConfig
    OptimizationProviderProps
    TrackEntryInteractionOptions

    Functions

    LiveUpdatesProvider
    OptimizationNavigationContainer
    OptimizationPreviewPanel
    OptimizationProvider
    OptimizationRoot
    OptimizationScrollProvider
    OptimizedEntry
    PreviewPanelOverlay
    useEntryResolver
    useInteractionTracking
    useLiveUpdates
    useOptimization
    useScreenTracking
    useScreenTrackingCallback
    useScrollContext
    useTapTracking
    useViewportTracking