Skip to content

Commit

Permalink
Merge pull request #20 from sanity-io/update-readme
Browse files Browse the repository at this point in the history
fix: update readme
  • Loading branch information
jjburbridge authored Dec 17, 2024
2 parents 6525aa1 + fcdb589 commit b12953a
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 15 deletions.
50 changes: 44 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,26 @@

> This is a **Sanity Studio v3** plugin.
This plugin allows users to add a/b testing experiemtnts on a field level basis
This plugin allows users to add a/b/n testing experiments to individual fields.

![image](./overview.gif)

For this plugin you need to defined the experiments you are running and the variations those experiments have. Each experiment needs to have an id, a label, and an array of variants that have an id and a label. You can either pass an array of experiments in the plugin config, or you can use and async function to retrieve the experiments and variants from an external service like growthbook, Amplitude, LaunchDarkly... You could even store the experiments in your sanity dataset.

Once configured you can query the values using the ids of the experiment and variant

- [@sanity/personalisation-plugin](#@sanity/personalisation-plugin)
- [Installation](#installation)
- [Usage](#usage)
- [Loading Experiments](#loading-experiments)
- [Using complex field configurations](#using-complex-field-configurations)
- [Validation of individual array items](#validation-of-individual-array-items)
- [Shape of stored data](#shape-of-stored-data)
- [Querying data](#querying-data)
- [License](#license)
- [Develop \& test](#develop--test)
- [Release new version](#release-new-version)
- [License](#license-1)

## Installation

Expand Down Expand Up @@ -62,10 +81,10 @@ export default defineConfig({

This will register two new fields to the schema., based on the setting passed intto `fields:`

- `experimentString` an Object field with `string` field called `default`, a `string` field called `experimentValue` and an array field of:
- `varirantsString` an object field with a `string` field called `value`, a string field called `variandId`, a `string` field called `experimentId`.
- `experimentString` an Object field with `string` field called `default`, a `string` field called `experimentId` and an array field of type:
- `varirantsString` an object field with a `string` field called `value`, a string field called `variantId`, a `string` field called `experimentId`.

Use them in your schema like this:
Use the experiment field in your schema like this:

```ts
//for Example in post.ts
Expand Down Expand Up @@ -120,7 +139,26 @@ Or an asynchronous function that returns an array of objects with an id and labe
```ts
experiments: async () => {
const response = await fetch('https://example.com/experiments')
return response.json()
const {externalExperiments} = await response.json()

const experiments: ExperimentType[] = externalExperiments?.map(
(experiment) => {
const experimentId = experiment.id
const experimentLabel = experiment.name
const variants = experiment.variations?.map((variant) => {
return {
id: variant.variationId,
label: variant.name,
}
})
return {
id: experimentId,
label: experimentLabel,
variants,
}
},
)
return experiments
}
```

Expand Down Expand Up @@ -162,7 +200,7 @@ export default defineConfig({

This would also create two new fields in your schema.

- `experimentFeaturedProduct` an Object field with `reference` field called `default`, a `string` field called `experimentId` and an array field of:
- `experimentFeaturedProduct` an Object field with `reference` field called `default`, a `string` field called `experimentId` and an array field of type:
- `variantFeaturedProduct` an object field with a `reference` field called `value`, a string field called `variandId`, a `string` field called `experimentId`.

Note that the name key in the field gets rewritten to value and is instead used to name the object field.
Expand Down
Binary file added overview.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"@sanity/ui": "^2.8.19",
"@sanity/uuid": "^3.0.2",
"fast-deep-equal": "^3.1.3",
"react-icons": "^5.4.0",
"suspend-react": "^0.1.3"
},
"devDependencies": {
Expand Down
15 changes: 8 additions & 7 deletions src/components/ExperimentField.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {AddIcon, CloseIcon} from '@sanity/icons'
import {CloseIcon} from '@sanity/icons'
import {useCallback, useMemo} from 'react'
import {GiSoapExperiment} from 'react-icons/gi'
import {
defineDocumentFieldAction,
DocumentFieldActionItem,
Expand All @@ -25,7 +26,7 @@ const useAddExperimentAction = (
return {
title: 'Add experiment',
type: 'action',
icon: AddIcon,
icon: GiSoapExperiment,
onAction: handleAction,
renderAsButton: true,
}
Expand All @@ -37,13 +38,13 @@ const useRemoveExperimentAction = (
const patchActiveEvent = useMemo(() => {
const activeId = ['active']
return set(false, activeId)
}, [props])
}, [])

const patchClearEvent = useMemo(() => {
const experimentId = ['experimentId'] // `${props.inputId}.experimentId`
const variants = ['variants'] //`${props.inputId}.variants`
return [unset(experimentId), unset(variants)]
}, [props])
}, [])
const handleAction = useCallback(() => {
props.onChange([patchActiveEvent, ...patchClearEvent])
}, [patchActiveEvent, patchClearEvent, props])
Expand All @@ -68,16 +69,16 @@ const newActions = ({onChange, inputId, active}: PatchStuff & {active?: boolean}
useAction: (props) => useAddExperimentAction({...props, onChange, inputId}),
})

export const Experimentfield = (props: ObjectFieldProps) => {
export const ExperimentField = (props: ObjectFieldProps) => {

Check warning on line 72 in src/components/ExperimentField.tsx

View workflow job for this annotation

GitHub Actions / Lint & Build

Missing return type on function
const {onChange} = props.inputProps
const {inputId} = props
const active = props.value?.active as boolean | undefined

const oldActions = props.actions || []

const wihtActionProps = {
const withActionProps = {
...props,
actions: [newActions({onChange, inputId, active}), ...oldActions],
}
return props.renderDefault(wihtActionProps)
return props.renderDefault(withActionProps)
}
4 changes: 2 additions & 2 deletions src/fieldExperiments.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ import {

import {ArrayInput} from './components/Array'
import {CONFIG_DEFAULT, ExperimentProvider} from './components/ExperimentContext'
import {ExperimentField} from './components/ExperimentField'
import {ExperimentInput} from './components/ExperimentInput'
import {VariantPreview} from './components/VariantPreview'
import {ExperimentType, FieldPluginConfig} from './types'
import {flattenSchemaType} from './utils/flattenSchemaType'
import {Experimentfield} from './components/ExperimentField'

const createFieldType = ({
field,
Expand All @@ -30,7 +30,7 @@ const createFieldType = ({
name: `experiment${usedName}`,
type: 'object',
components: {
field: Experimentfield,
field: ExperimentField,
},
fields: [
typeof field === `string`
Expand Down
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -9863,6 +9863,11 @@ react-i18next@14.0.2:
"@babel/runtime" "^7.23.9"
html-parse-stringify "^3.0.1"

react-icons@^5.4.0:
version "5.4.0"
resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-5.4.0.tgz#443000f6e5123ee1b21ea8c0a716f6e7797f7416"
integrity sha512-7eltJxgVt7X64oHh6wSWNwwbKTCtMfK35hcjvJS0yxEAhPM8oUKdS3+kqaW1vicIltw+kR2unHaa12S9pPALoQ==

react-is@^16.13.1, react-is@^16.7.0, react-is@^16.8.4:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
Expand Down

0 comments on commit b12953a

Please sign in to comment.