Preview Plugin
Previewing Experiences before they are published.
Add plugin to the
plugins
prop of the NinetailedProvider
and provide an array of all Ninetailed Experience and Ninetailed Audience entries to the plugin. Ensure that you are supplying both all published and all draft entries of each to the plugin.The Preview Plugin is designed for preview and development. Ensure that you are not instantiating the plugin in production contexts.
React
Next
Gatsby
<NinetailedProvider
//...
plugins={[
new NinetailedPreviewPlugin({
// Required: Experiences from your CMS
experiences: yourExperiences || [],
// Required: Audiences from your CMS
audiences: yourAudiences || [],
// Optional: Callback to handle user forwarding to the experience entry in your CMS
onOpenExperienceEditor: (experience) => { },
// Optional: Determine the visibility of the Preview Plugin
ui: { opener: { hide: false } },
})
]}
>
<MyAppComponents />
</NinetailedProvider>
<NinetailedProvider
//...
plugins={[
new NinetailedPreviewPlugin({
// Required: Experiences from your CMS
experiences: yourExperiences || [],
// Required: Audiences from your CMS
audiences: yourAudiences || [],
// Optional: Callback to handle user forwarding to the experience entry in your CMS
onOpenExperienceEditor: (experience) => { },
// Optional: Determine the visibility of the Preview Plugin
ui: { opener: { hide: false } },
})
]}
>
<Component {...pageProps} />
</NinetailedProvider>
gatsby-config.js
import {audienceQuery, audienceMapper, experienceQuery, experienceMapper } from '@/lib/yourFunctions'
plugins: [
// ...
{
resolve: `@ninetailed/experience.js-gatsby`,
options: {
clientId: NINETAILED_CLIENT_ID,
environment: NINETAILED_ENVIRONMENT,
ninetailedPlugins: [
{
resolve: `@ninetailed/experience.js-plugin-preview`,
name: "@ninetailed/experience.js-plugin-preview",
options: {
// Options specific to Gatsby - optional
customOptions: {
// Query all audiences
audienceQuery,
// Mapper function for audiences
audienceMapper,
// Query all experiences
experienceQuery,
// Mapper function for experiences
experienceMapper,
},
// Callback to handle user forwarding to the experience entry in your CMS - optional
onOpenExperienceEditor: (experience) => { },
// Determine the visibility of the Preview Plugin - optional
ui: { opener: { hide: false } },
},
},
],
},
},
];
Define the functions for retrieving and mapping Gatsby data so they can be used in
gatsby-config.js
. These example queries are compatible with gatsby-source-contentful
; adjust your queries based on the content source you are using.lib/yourFunctions.js
import {
ExperienceLike,
ExperienceMapper,
} from "@ninetailed/experience.js-utils";
export const audienceQuery = `
query NinetailedAudienceQuery {
allContentfulNinetailedAudience {
edges {
node {
nt_audience_id
nt_name
nt_description {
nt_description
}
}
}
}
}
`
export const audienceMapper = audienceData => {
return audienceData.allContentfulNinetailedAudience.edges.map(audience => {
return {
id: audience.node.nt_audience_id,
name: audience.node.nt_name,
description: audience.node.nt_description?.nt_description,
}
})
}
export const experienceQuery = `
query NinetailedExperienceQuery {
allContentfulNinetailedExperience {
edges {
node {
id: contentful_id
name: nt_name
type: nt_type
audience: nt_audience {
id: contentful_id
name: nt_name
}
config: nt_config {
distribution
traffic
components {
baseline {
id
}
variants {
hidden
id
}
}
}
variants: nt_variants {
... on ContentfulEntry {
id: contentful_id
}
}
}
}
}
}
`
export const experienceMapper = (experienceData: any) => {
return experienceData.allContentfulNinetailedExperience.edges
.filter(({ node }: { node: any }) =>
ExperienceMapper.isExperienceEntry(node)
)
.map(({ node }: { node: ExperienceLike }) =>
ExperienceMapper.mapExperience(node)
);
};
The Preview Plugin expects a specific format for the provided
experiences
and audiences
. Use the appropriate Utility Library to map these to the required format, depending on your content source.Contentful Utility Library
JavaScript Utility Library
When fetching your Experiences and Audiences from Contentful, we provide a utility package (
@ninetailed/experience.js-utils-contentful
) which handles the transformation.import { ExperienceMapper, ExperienceEntryLike, AudienceMapper, AudienceEntryLike } from 'experience.js-utils-contentful';
import { yourContentfulPreviewClient } from 'lib/api'
export const getAllExperiences = async () => {
const entries = await yourContentfulPreviewClient.getEntries({
content_type: 'nt_experience',
include: 1,
});
return (entries.items as ExperienceEntryLike[])
.filter(ExperienceMapper.isExperienceEntry)
.map(ExperienceMapper.mapExperience);
};
export const getAllAudiences = async () => {
const entries = await yourContentfulPreviewClient.getEntries({
content_type: 'nt_audiences',
});
return (entries.items as AudienceEntryLike[])
.filter(AudienceMapper.isAudienceEntry)
.map(AudienceMapper.mapAudience);
};
import { ExperienceMapper, ExperienceEntryLike, Audience } from 'experience.js-utils';
import { yourContentPreviewClient } from 'lib/api'
export const getAllExperiences = async () => {
const experiencers = await yourContentPreviewClient.getAllExperienceEntries()
return experiences
.map((entry: any) => {
return {
id: experience.uid,
name: experience.nt_name,
type: experience.nt_type,
config: experience.nt_config,
audience: {
id: experience.nt_audience[0].nt_audience_id,
name: experience.nt_audience[0].title,
},
variants: experience.nt_variants?.map((variant: any) => {
return {
id: variant.uid,
};
}),
};
})
}
.filter((experience) => ExperienceMapper.isExperienceEntry)
.map((experience) => ExperienceMapper.mapExperience);
};
export const getAllAudiences = async () => {
const audiences = await yourContentPreviewClient.getAllAudienceEntries()
// map to exported Audience type if required
return audiences.map((audience) => {
return {
id: audience["id"], // Required: Your audience id property, normally audience.nt_audience_id
name: audience["name"], // Required: Your audience name property, normally audience.nt_name
description: audience["description"] // Optional: normally audience.nt_description
} as Audience
})
};
Last modified 1d ago