> This page is for Personalization.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://contentful-staging.ferndocs.com/developers/docs/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://contentful-staging.ferndocs.com/developers/docs/_mcp/server.

# React SDK

> Work with Ninetailed Experiences, instances, and profiles within React and React-based meta-frameworks.

## `<NinetailedProvider>`

The `<NinetailedProvider>` provides a Ninetailed instance to the application. It can accept all of the same instantiation options as a Ninetailed instance to create a new one or accept an existing Ninetailed instance.

```typescript
import type { Ninetailed } from "@ninetailed/experience.js"
import { NinetailedProvider } from "@ninetailed/experience.js-react"
// or import { NinetailedProvider } from '@ninetailed/experience.js-next' 
// or import { NinetailedProvider } from '@ninetailed/experience.js-gatsby'
import type { NinetailedProviderInstantiationProps } from "@ninetailed/experience.js-react"

// Most implementations will rely on the provider to create the Ninetailed instance by passing instantation props
function createWithInstanceProps({createInstanceProps, children}: {createInstanceProps: NinetailedProviderInstantiationProps, children: ReactNode }) {
    return (
        <NinetailedProvider {...createInstanceProps}>
            {children}
        </NinetailedProvider>
    )
}

// However, you can also pass an existing Ninetailed instance to the `ninetailed` prop
// Use this if you need to configure fetchImpl on the NinetailedAPIClient
function createWithNinetailedInstance({ninetailed, children}: {ninetailed: Ninetailed, children: ReactNode }) {
    return (
        <NinetailedProvider ninetailed={ninetailed}>
            {children}
        </NinetailedProvider>
    )
}
```

The provided Ninetailed instance can be retreived with the [useNinetailed](#useninetailed) hook.

### Types

```typescript
import type {
  Locale,
  NinetailedRequestContext,
  OnErrorHandler,
  OnLogHandler
} from '@ninetailed/experience.js-shared';

import type {
  Ninetailed,
  OnInitProfileId,
  Storage
} from '@ninetailed/experience.js';

import type { NinetailedPlugin } from '@ninetailed/experience.js-plugin-analytics';

type NinetailedProviderInstantiationProps = {
    clientId: string;
    environment?: string;
    buildClientContext?: () => NinetailedRequestContext;
    componentViewTrackingThreshold?: number;
    locale?: Locale;
    onError?: OnErrorHandler;
    onInitProfileId?: OnInitProfileId;
    onLog?: OnLogHandler;
    plugins?: (NinetailedPlugin | NinetailedPlugin[])[];
    requestTimeout?: number;
    storageImpl?: Storage;
    useSDKEvaluation?: boolean;
    url?: string;
}
```

## Hooks

### useExperience

Returns the loading state of an experience and once loaded, the all relevant metadata of the experience including the assigned variant and variant index. This hook powers the React `<Experience>` component exported by the SDKs.

This hook is useful when you need imperative access to the metadata an assigned experience, often in circumstances where you are not intending to render out CMS-sourced content variations. For example, you might be using a feature-flag style experiment where you have no need for the `<Experience>` component, but your application still needs to change behavior and/or send tracking calls based on the assigned `variantIndex`.

```typescript
import { useExperience } from '@ninetailed/experience.js-react';
// or import { useExperience } from '@ninetailed/experience.js-next' 
// or import { useExperience } from '@ninetailed/experience.js-gatsby'
import type { Baseline, ExperienceConfiguration, Profile, Reference } from '@ninetailed/experience.js'

const YourComponent = (props: { 
        baseline: Baseline,
        experiences: ExperienceConfiguration<Variant extends Reference>[]
    }) => {
    const {
        audience,
        baseline, 
        error,
        experience,
        hasVariants,
        isPersonalized,
        loading,
        profile,
        status,
        variant,
        variantIndex
    }: {
        audience: { id: string } | null,
        baseline: Baseline,
        error: Error | null,
        experience: ExperienceConfiguration<Variant> | null,
        hasVariants: boolean,
        isPersonalized: boolean,
        loading: boolean,
        profile: Profile,
        status: 'loading' | 'success' | 'error',
        variant: Variant,
        variantIndex: number,
    } = useExperience(baseline, experiences);
    
    // Go wild
}
```

### useNinetailed

Retrieves the Ninetailed instance from the nearest `<NinetailedProvider>` and all of its instance methods and properties as in the [Ninetailed Instance](/personalization/the-ninetailed-instance) documentation.

```typescript
import { useNinetailed } from '@ninetailed/experience.js-react';
// or import { useNinetailed } from '@ninetailed/experience.js-next' 
// or import { useNinetailed } from '@ninetailed/experience.js-gatsby'

const YourComponent = () => {
    const { 
        debug,
        identify,
        observeElement,
        onIsInitialized,
        onProfileChange,
        page,
        plugins,
        profileState,
        reset,
        track,
        trackComponentView,
        unobserveElement
    } = useNinetailed();
    
    // Go wild
}
```

### useProfile

Retrieves the current profile state from the nearest `<NinetailedProvider>`.

```typescript
import { useProfile } from '@ninetailed/experience.js-react';
// or import { useProfile } from '@ninetailed/experience.js-next' 
// or import { useProfile } from '@ninetailed/experience.js-gatsby'

const GreetingComponent = () => {
    const { 
        error,
        from,
        loading, 
        profile, 
        status 
    }: { 
        error: Error | null, 
        from: 'api' | 'hydrated',
        loading: boolean, 
        profile: Profile | null, 
        status: "error" | "loading" | "success"
    } = useProfile();
    
    return <p>Hey {profile.traits.firstname}, nice weather in {profile.location.city}!</p>
}
```