Utility Libraries

More utilities to integrate Ninetailed within your current tech stack.

Our Experience API utility libraries provide methods to map experience content to the format required by the <Experience> component exported by our React, Next.js, and Gatsby SDKs.

Use the Contentful Utility SDK if you are are retrieving content and experiences using Contentful's client libraries that interface with the Contentful REST APIs, including:

  • the Contentful Content Delivery API

  • the Contentful Content Preview API

For all other sources, including:

  • the Contentful GraphQL API

  • the Contentstack Content Delivery API

  • your own internal content APIs, middleware, etc.

use the JavaScript Utility SDK and map your experiences to the type required by the ExperienceMapper class methods.

JavaScript Library Usage

npm install @ninetailed/experience.js-utils
# OR
yarn add @ninetailed/experience.js-utils

You must map your fetched CMS Experience entries to a particular shape prior to transforming them with the ExperienceMapper methods. The following examples show the format required in a .map step prior to calling .filter to remove ill-formatted entries.

import { ExperienceMapper } from '@ninetailed/experience.js-utils';

const mappedExperiences = (myEntry.nt_experiences || [])
  .map((experience) => {
    return {
      id: experience.id,
      name: experience.name
      type: experience.nt_type as 'nt_personalization' | 'nt_experiment'
      config: experience.nt_config,
      audience: {
        id: experience.nt_audience.nt_audience_id
        // If mapping for the Preview Plugin, this displays audience names
        name: experience.nt_audience.nt_name
      },
      variants: experience.variants.map((variant) => {
        return {
          id: variant.id, // Required
          // Map any other fields required by your components
          ...variant,
          someComponentProp: variant.foo
        }
      })
    }
  })
  .filter((experience) => ExperienceMapper.isExperienceEntry(experience))
  .map((experience) => ExperienceMapper.mapExperience(experience));

Contentful Library Usage

npm install @ninetailed/experience.js-utils-contentful
# OR
yarn add @ninetailed/experience.js-utils-contentful
import { ExperienceMapper } from '@ninetailed/experience.js-utils-contentful'
import { createClient } from 'contentful';

const client = createClient({
  accessToken: 'youtAccessToken',
  space: 'yourSpaceId'
})

// Specify what entries with Ninetailed Experience references to get from Contentful
const query = {...}

const rawEntries = await client.getEntries(query);
// Extract one entry, as an example
const [yourEntry] = rawEntries.items

// Filter and map with ExperienceMapper methods
const experiences = (yourEntry.fields.nt_experiences || [])
    .filter(ExperienceMapper.isExperienceEntry)
    .map(ExperienceMapper.mapExperience)

See also our Contentful + Next.js example project for context.

ExperienceMapper Class Methods

isExperienceEntry

Determines if a provided entry is of valid type to be consumed by mapExperience. Use with .filter to remove any invalidly typed experiences.

mapExperience

Transform an experience to the type required by the <Experience> component.

isExperimentEntry

Determines if a provided entry is of valid type to be consumed by mapExperiment. Use with .filter to remove any invalidly typed experiments.

mapExperiment

Transform an experiment to the type required by the React and Next.js <NinetailedProvider> experiments prop.

mapCustomExperience

[Contentful Library only] If you need to modify how the variants referenced by an experience entry retrieved from Contentful are mapped, use this method to pass a custom variant mapping function. Example usage:

const experiences = myExperience.fields.nt_experiences
  .filter(ExperienceMapper.isExperienceEntry)
  .map((experience) => {
    ExperienceMapper.mapCustomExperience(experience, (variant) => {
      id: variant.sys.id // required
      // Add any data required by your `component` prop on the <Experience> component
      ...variant.fields,
      someComponentProp: variant.foo
    });
  })

mapCustomExperienceAsync

[Contentful Library only, SDK >= 7.7.x] Similar to mapCustomExperience, but allows asynchronous operations to be executed in the variant mapping step.

const experiences = myExperience.fields.nt_experiences
  .filter(ExperienceMapper.isExperienceEntry)
  .map((experience) => {
    ExperienceMapper.mapCustomExperienceAsync(experience, async (variant) => {
      await new Promise ((resolve) => setTimeout(resolve, 1000)); // Simulated delay supported by async handler
      return {
        id: variant.sys.id // required
        // Add any data required by your `component` prop on the <Experience> component
        ...variant.fields,
        someComponentProp: variant.foo
      }
    });
  })

mapBaselineWithExperiences

[Contentful Library only] Supply an object representing a baseline entry and it's attached experiences and return an array of filtered and mapped experiences.

Last updated