React SDK

<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.

1import type { Ninetailed } from "@ninetailed/experience.js"
2import { NinetailedProvider } from "@ninetailed/experience.js-react"
3// or import { NinetailedProvider } from '@ninetailed/experience.js-next'
4// or import { NinetailedProvider } from '@ninetailed/experience.js-gatsby'
5import type { NinetailedProviderInstantiationProps } from "@ninetailed/experience.js-react"
6
7// Most implementations will rely on the provider to create the Ninetailed instance by passing instantation props
8function createWithInstanceProps({createInstanceProps, children}: {createInstanceProps: NinetailedProviderInstantiationProps, children: ReactNode }) {
9 return (
10 <NinetailedProvider {...createInstanceProps}>
11 {children}
12 </NinetailedProvider>
13 )
14}
15
16// However, you can also pass an existing Ninetailed instance to the `ninetailed` prop
17// Use this if you need to configure fetchImpl on the NinetailedAPIClient
18function createWithNinetailedInstance({ninetailed, children}: {ninetailed: Ninetailed, children: ReactNode }) {
19 return (
20 <NinetailedProvider ninetailed={ninetailed}>
21 {children}
22 </NinetailedProvider>
23 )
24}

The provided Ninetailed instance can be retreived with the useNinetailed hook.

Types

1import type {
2 Locale,
3 NinetailedRequestContext,
4 OnErrorHandler,
5 OnLogHandler
6} from '@ninetailed/experience.js-shared';
7
8import type {
9 Ninetailed,
10 OnInitProfileId,
11 Storage
12} from '@ninetailed/experience.js';
13
14import type { NinetailedPlugin } from '@ninetailed/experience.js-plugin-analytics';
15
16type NinetailedProviderInstantiationProps = {
17 clientId: string;
18 environment?: string;
19 buildClientContext?: () => NinetailedRequestContext;
20 componentViewTrackingThreshold?: number;
21 locale?: Locale;
22 onError?: OnErrorHandler;
23 onInitProfileId?: OnInitProfileId;
24 onLog?: OnLogHandler;
25 plugins?: (NinetailedPlugin | NinetailedPlugin[])[];
26 requestTimeout?: number;
27 storageImpl?: Storage;
28 useSDKEvaluation?: boolean;
29 url?: string;
30}

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.

1import { useExperience } from '@ninetailed/experience.js-react';
2// or import { useExperience } from '@ninetailed/experience.js-next'
3// or import { useExperience } from '@ninetailed/experience.js-gatsby'
4import type { Baseline, ExperienceConfiguration, Profile, Reference } from '@ninetailed/experience.js'
5
6const YourComponent = (props: {
7 baseline: Baseline,
8 experiences: ExperienceConfiguration<Variant extends Reference>[]
9 }) => {
10 const {
11 audience,
12 baseline,
13 error,
14 experience,
15 hasVariants,
16 isPersonalized,
17 loading,
18 profile,
19 status,
20 variant,
21 variantIndex
22 }: {
23 audience: { id: string } | null,
24 baseline: Baseline,
25 error: Error | null,
26 experience: ExperienceConfiguration<Variant> | null,
27 hasVariants: boolean,
28 isPersonalized: boolean,
29 loading: boolean,
30 profile: Profile,
31 status: 'loading' | 'success' | 'error',
32 variant: Variant,
33 variantIndex: number,
34 } = useExperience(baseline, experiences);
35
36 // Go wild
37}

useNinetailed

Retrieves the Ninetailed instance from the nearest <NinetailedProvider> and all of its instance methods and properties as in the Ninetailed Instance documentation.

1import { useNinetailed } from '@ninetailed/experience.js-react';
2// or import { useNinetailed } from '@ninetailed/experience.js-next'
3// or import { useNinetailed } from '@ninetailed/experience.js-gatsby'
4
5const YourComponent = () => {
6 const {
7 debug,
8 identify,
9 observeElement,
10 onIsInitialized,
11 onProfileChange,
12 page,
13 plugins,
14 profileState,
15 reset,
16 track,
17 trackComponentView,
18 unobserveElement
19 } = useNinetailed();
20
21 // Go wild
22}

useProfile

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

1import { useProfile } from '@ninetailed/experience.js-react';
2// or import { useProfile } from '@ninetailed/experience.js-next'
3// or import { useProfile } from '@ninetailed/experience.js-gatsby'
4
5const GreetingComponent = () => {
6 const {
7 error,
8 from,
9 loading,
10 profile,
11 status
12 }: {
13 error: Error | null,
14 from: 'api' | 'hydrated',
15 loading: boolean,
16 profile: Profile | null,
17 status: "error" | "loading" | "success"
18 } = useProfile();
19
20 if (loading) return <p>Loading...</p>
21
22 return <p>Hey {profile?.traits?.firstname ?? 'there'}, nice weather in {profile?.location?.city ?? 'your city'}!</p>
23}

Components

<Experience>

The <Experience> component is the primary way to render personalized content. It wraps a component and automatically selects the correct variant based on the visitor’s audience membership.

1import { Experience } from '@ninetailed/experience.js-react';
2import { ExperienceMapper } from '@ninetailed/experience.js-utils-contentful';
3
4const BlockRenderer = ({ block }) => {
5 const experiences = (block.fields.nt_experiences || [])
6 .filter(ExperienceMapper.isExperienceEntry)
7 .map(ExperienceMapper.mapExperience);
8
9 return (
10 <Experience
11 id={block.sys.id}
12 component={MyComponent}
13 experiences={experiences}
14 {...block.fields}
15 />
16 );
17};

Props:

PropTypeRequiredDescription
idstringYesUnique identifier for the baseline entry (typically entry.sys.id)
componentReact.ComponentTypeYesThe component to render with baseline or variant data
experiencesExperienceConfiguration[]NoMapped experience configurations from ExperienceMapper.mapExperience()
passthroughPropsobjectNoAdditional props passed to the component that are not part of the Contentful entry
loadingComponentReact.ComponentTypeNoComponent to show while the SDK resolves the variant (useful for SSR/ESR setups)

All other props are spread onto the rendered component as the baseline content.

<MergeTag>

The <MergeTag> component renders visitor-specific profile data inline. It resolves a dot-notation path against the visitor’s profile and renders the value, falling back to a default if unavailable.

1import { MergeTag } from '@ninetailed/experience.js-react';
2
3<p>
4 Welcome back, <MergeTag id="traits.firstName" fallback="friend" />!
5 How is <MergeTag id="location.city" fallback="your city" /> today?
6</p>

Props:

PropTypeRequiredDescription
idstringYesDot-notation path into the visitor profile (e.g., traits.firstName, location.city)
fallbackstringNoText to render when the profile value is unavailable

Merge tags can also be embedded as nt_mergetag entries in Contentful rich text fields. See the Experience SDK documentation for rich text rendering patterns.