@sanity/personalization-plugin 2.5.0-launch-darkly.1 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 Jon Burbridge
3
+ Copyright (c) 2026 Jon Burbridge
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -18,13 +18,15 @@ Once configured you can query the values using the ids of the experiment and var
18
18
  - [Validation of individual array items](#validation-of-individual-array-items)
19
19
  - [Shape of stored data](#shape-of-stored-data)
20
20
  - [Querying data](#querying-data)
21
+ - [Split testing](#split-testing)
21
22
  - [Using experiment fields in an array](#using-experiment-fields-in-an-array)
22
23
  - [License](#license)
23
24
  - [Develop \& test](#develop--test)
24
25
  - [Release new version](#release-new-version)
25
26
  - [License](#license-1)
26
27
 
27
- For Specific information about the growthbookFieldLevel export see its [readme](/growthbook.md)
28
+ For Specific information about the Growthbook FieldLevel export see its [readme](/growthbook.md)
29
+ For Specific information about the LaunchDarkly FieldLevel export see its [readme](/launchdarkly.md)
28
30
 
29
31
  ## Installation
30
32
 
@@ -206,7 +208,6 @@ This would also create two new fields in your schema.
206
208
 
207
209
  Note that the name key in the field gets rewritten to value and is instead used to name the object field.
208
210
 
209
-
210
211
  ## Validation of individual array items
211
212
 
212
213
  You may wish to validate individual fields for various reasons. From the variant array field, add a validation rule that can look through all the array items, and return item-specific validation messages at the path of that array item.
@@ -258,7 +259,8 @@ The custom input contains buttons which will add new array items with the experi
258
259
  }
259
260
  ```
260
261
 
261
- Querying data
262
+ ## Querying data
263
+
262
264
  Using GROQ filters you can query for a specific experiment, with a fallback to default value like so:
263
265
 
264
266
  ```ts
@@ -267,9 +269,112 @@ Using GROQ filters you can query for a specific experiment, with a fallback to d
267
269
  }
268
270
  ```
269
271
 
272
+ ## Split testing
273
+
274
+ Split testing involves splitting traffic for one url over 2+ pages, this is used when you want to test more than just a single field in an experiment.
275
+
276
+ ### Studio Setup
277
+
278
+ To do split testing using this plugin define a type that can store a url path
279
+
280
+ ```ts
281
+ export const path = defineType({
282
+ name: 'path',
283
+ type: 'string',
284
+ validation: (Rule) =>
285
+ Rule.required().custom(async (value: string | undefined, context) => {
286
+ if (!value) return true
287
+ if (!value.startsWith('/')) return 'Must start with "/"'
288
+ return true
289
+ }),
290
+ })
291
+ ```
292
+
293
+ add the type to the studio `schema.types` and the plugin config fields:
294
+
295
+ ```ts
296
+ fieldLevelExperiments({
297
+ fields: ['path', ...otherFields],
298
+ experiments: getExperiments,
299
+ }),
300
+ ```
301
+
302
+ and then create a document type that stores the routing information:
303
+
304
+ ```ts
305
+ export const routing = defineType({
306
+ name: 'routing',
307
+ type: 'document',
308
+ title: 'Routing Experiments',
309
+ fields: [
310
+ {
311
+ name: 'pathExperiment',
312
+ type: 'experimentPath',
313
+ initialValue: {active: true},
314
+ },
315
+ ],
316
+ preview: {
317
+ select: {
318
+ path: 'pathExperiment.default',
319
+ experiment: 'pathExperiment.experimentId',
320
+ },
321
+ prepare({path, experiment}) {
322
+ return {
323
+ title: `${path} - ${experiment}`,
324
+ }
325
+ },
326
+ },
327
+ })
328
+ ```
329
+
330
+ ### Frontend usage
331
+
332
+ In your frontend you will need some middleware that can intercept the request for the page and check if the route is included in your split page testing and if so decide which page the user should see.
333
+
334
+ In Next.js Middleware it could be something like
335
+
336
+ ```ts
337
+ const ROUTING_QUERY = defineQuery(`*[
338
+ _type == "routing" &&
339
+ pathExperiment.default == $path
340
+ ][0]{
341
+ "route": coalesce(pathExperiment.variants[experimentId == $experimentId && variantId == $variantId][0].value, pathExperiment.default)
342
+ }`)
343
+
344
+ export async function middleware(request: NextRequest) {
345
+ let response = NextResponse.next()
346
+ const path = request.nextUrl.pathname
347
+ // getExperimentValue is a function that will determine a variant based on some user properties
348
+ const {variant} = await getExperimentValue(path)
349
+
350
+ const queryParams = {
351
+ path,
352
+ experimentId: 'homepage',
353
+ variantId: variant?.id || '',
354
+ }
355
+
356
+ // Instead of doing a query for every page this could be queried at build time and stored in a file.
357
+ const data = await client.fetch(ROUTING_QUERY, queryParams)
358
+ if (data?.route) {
359
+ const url = request.nextUrl.clone()
360
+ url.pathname = data.route
361
+ const rewrite = NextResponse.rewrite(url)
362
+ return rewrite
363
+ }
364
+
365
+ return response
366
+ }
367
+
368
+ export const config = {
369
+ //only run the middleware on pages
370
+ matcher: ['/((?!api|_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)'],
371
+ }
372
+ ```
373
+
270
374
  ## Using experiment fields in an array
271
375
 
272
376
  You may want to add experiment fields as a type with in an array in oder to do this you would need to set an initial value for the experiment to active the schema would be something like:
377
+
273
378
  ```ts
274
379
  defineField({
275
380
  name: 'components',
@@ -284,7 +389,7 @@ defineField({
284
389
  }),
285
390
  ```
286
391
 
287
- You can then use a groq filter to return the base version of you array member so you don't have to create an experiment specific version
392
+ You can then use a groq filter to return the base version of you array member so you don't have to create an experiment specific version
288
393
 
289
394
  ```ts
290
395
  *[