@picked/client 0.0.56-next.1 → 0.0.56

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.
Files changed (52) hide show
  1. package/dist/api-BfVRVGAR.cjs +1 -0
  2. package/dist/{api-CNxyQeRM.js → api-CTjJzTQT.js} +1 -1
  3. package/dist/cjs/index.js +1 -1
  4. package/dist/cjs/plugins/dynamic-experiences/index.js +1 -1
  5. package/dist/docs/actions.md +58 -0
  6. package/dist/docs/api/index.md +32 -0
  7. package/dist/docs/api-keys.md +33 -0
  8. package/dist/docs/conditions.md +52 -0
  9. package/dist/docs/experiences.md +33 -0
  10. package/dist/docs/features.md +51 -0
  11. package/dist/docs/fields.md +70 -0
  12. package/dist/docs/flow-builder/building-flows.md +61 -0
  13. package/dist/docs/flow-builder/condition-builder.md +54 -0
  14. package/dist/docs/flow-builder/keyboard-shortcuts.md +66 -0
  15. package/dist/docs/flow-builder/nodes.md +43 -0
  16. package/dist/docs/flow-builder/overview.md +43 -0
  17. package/dist/docs/index.md +79 -0
  18. package/dist/docs/pickedql/data-sources.md +39 -0
  19. package/dist/docs/pickedql/dimensions.md +23 -0
  20. package/dist/docs/pickedql/examples.md +165 -0
  21. package/dist/docs/pickedql/filtering.md +31 -0
  22. package/dist/docs/pickedql/index.md +34 -0
  23. package/dist/docs/pickedql/schema.md +95 -0
  24. package/dist/docs/pickedql/virtual-functions.md +84 -0
  25. package/dist/docs/projects.md +30 -0
  26. package/dist/docs/reference/index.md +11 -0
  27. package/dist/docs/reports.md +11 -0
  28. package/dist/docs/sdk/actions.md +7 -0
  29. package/dist/docs/sdk/conditions.md +131 -0
  30. package/dist/docs/sdk/content-security-policy.md +31 -0
  31. package/dist/docs/sdk/experiences.md +41 -0
  32. package/dist/docs/sdk/features.md +213 -0
  33. package/dist/docs/sdk/fields.md +263 -0
  34. package/dist/docs/sdk/index.md +74 -0
  35. package/dist/docs/sdk/plugins/create-experience.md +133 -0
  36. package/dist/docs/sdk/plugins/dynamic-experiences.md +59 -0
  37. package/dist/docs/sdk/plugins/index.md +9 -0
  38. package/dist/docs/sdk/plugins/window-object.md +20 -0
  39. package/dist/docs/sdk/predicates.md +113 -0
  40. package/dist/docs/sdk/steps.md +411 -0
  41. package/dist/docs/steps.md +35 -0
  42. package/dist/docs/team-management.md +40 -0
  43. package/dist/docs/tooling/chrome-extension.md +29 -0
  44. package/dist/docs/tooling/gtm-template.md +69 -0
  45. package/dist/docs/tooling/index.md +19 -0
  46. package/dist/docs/tooling/mcp.md +120 -0
  47. package/dist/docs/tooling/vite-plugin.md +82 -0
  48. package/dist/docs/workspaces.md +35 -0
  49. package/dist/esm/index.js +1 -1
  50. package/dist/esm/plugins/dynamic-experiences/index.js +1 -1
  51. package/package.json +2 -2
  52. package/dist/api-CtE-gT1L.cjs +0 -1
@@ -0,0 +1,74 @@
1
+ ---
2
+ layout: docs
3
+ ---
4
+
5
+ # Picked SDK
6
+
7
+ The Picked SDK enables you to add dynamic, personalized experiences to your web applications with minimal code.
8
+
9
+ :::tip
10
+ The SDK is framework-agnostic and works with React, Svelte, Vue, and vanilla JavaScript.
11
+ :::
12
+
13
+ ## Quick Start
14
+
15
+ :::code-group
16
+
17
+ ```typescript [Browser]
18
+ import { createClient } from '@picked/client'
19
+ import { windowObjectPlugin } from '@picked/client/plugins/window-object'
20
+ import { singlePageAppPlugin } from '@picked/client/plugins/single-page-app'
21
+
22
+ const picked = createClient({
23
+ organizationId: 'your-organization-id',
24
+ projectId: 'your-project-id',
25
+ plugins: [windowObjectPlugin(), singlePageAppPlugin()],
26
+ })
27
+
28
+ picked.init()
29
+ ```
30
+
31
+ ```ts [Server]
32
+ Coming Soon...
33
+ ```
34
+
35
+ :::
36
+
37
+ :::tip
38
+ If you’re running Picked in a browser environment, access the Picked client in the console with `window.Picked`
39
+ :::
40
+
41
+ ## Precondition & Condition
42
+
43
+ | Category | Question | Description |
44
+ | ------------ | ---------------------- | --------------------------------------------------------------------------------------------- |
45
+ | Precondition | Should Picked start? | Use for environment checks, page filtering, or feature flags that completely disable the SDK. |
46
+ | Condition | Is this user eligible? | Use for user segmentation, A/B test enrollment, or targeting specific user groups. |
47
+
48
+ ```ts
49
+ const picked = createClient({
50
+ precondition: {
51
+ and: [
52
+ {
53
+ or: [
54
+ {
55
+ invoke: {
56
+ var: 'features.aa-test',
57
+ },
58
+ },
59
+ true,
60
+ ],
61
+ },
62
+ { invoke: { var: 'predicates.shopify-is-product-page' } },
63
+ ],
64
+ },
65
+ condition: {
66
+ invoke: {
67
+ var: 'features.convincely-enabled',
68
+ },
69
+ },
70
+ // rest of picked config
71
+ })
72
+ ```
73
+
74
+ See [conditions](./conditions.md) for more detail
@@ -0,0 +1,133 @@
1
+ ---
2
+ layout: docs
3
+ ---
4
+
5
+ # Create Experience Plugin
6
+
7
+ A plugin to register an array of experiences to the Picked client.
8
+
9
+ ## Setup Plugin
10
+
11
+ :::code-group
12
+
13
+ ```ts [app.ts]
14
+ import { createClient } from '@picked/client'
15
+ import { createExperiencePlugin } from '@picked/client/plugins/create-experience'
16
+ import { funnelExperience } from '../experiences/funnel-experience'
17
+ import { widgetExperience } from '../experiences/widget-experience'
18
+
19
+ const client = createClient({
20
+ organizationId: 'your-org-id',
21
+ projectId: 'your-project-id',
22
+ plugins: createExperiencePlugin({
23
+ experiences: [funnelExperience, widgetExperience],
24
+ }),
25
+ })
26
+ ```
27
+
28
+ :::
29
+
30
+ ## Defining Steps
31
+
32
+ Steps are defined using `createStep()`. They are added directly to an experience using `experience.addStep()`.
33
+
34
+ ```ts
35
+ import { createExperience, createStep } from '@picked/client/plugins/create-experience'
36
+
37
+ // Define standalone steps
38
+ const welcomeStep = createStep({
39
+ id: 'welcome',
40
+ name: 'Welcome',
41
+ })
42
+
43
+ const contactStep = createStep({
44
+ id: 'contact',
45
+ name: 'Contact Details',
46
+ })
47
+
48
+ // Define the experience and add steps to build the flow
49
+ const onboardingExperience = createExperience({
50
+ id: 'onboarding',
51
+ name: 'User Onboarding',
52
+ targets: [{ selector: 'body', placement: 'after' }],
53
+ })
54
+
55
+ onboardingExperience.addStep(welcomeStep)
56
+ onboardingExperience.addStep(contactStep)
57
+ ```
58
+
59
+ Each step requires a `name` that identifies it in analytics events. An `id` is optional — one will be generated automatically if omitted.
60
+
61
+ Steps can be used on multiple experiences.
62
+
63
+ ### Adding Fields to Steps
64
+
65
+ Fields are defined with `createField()`.
66
+
67
+ ```ts
68
+ import { createStep, createField } from '@picked/client/plugins/create-experience'
69
+
70
+ const emailField = createField({
71
+ id: 'email-address',
72
+ name: 'email-address',
73
+ type: 'text',
74
+ label: 'Email Address',
75
+ multiple: false,
76
+ required: true,
77
+ placeholder: 'you@example.com',
78
+ })
79
+ ```
80
+
81
+ Fields are added to a step with `step.addField()`, or an array of `fieldIds` when creating a step:
82
+
83
+ ```ts
84
+ const contactStep = createStep({
85
+ id: 'contact',
86
+ label: 'Contact Details',
87
+ })
88
+
89
+ contactStep.addField(emailField)
90
+
91
+ //Or
92
+
93
+ const contactStep = createStep({
94
+ id: 'contact',
95
+ label: 'Contact Details',
96
+ fieldIds: [contactStep.id],
97
+ })
98
+ ```
99
+
100
+ ## Using conditions in an experience
101
+
102
+ [Conditions](../conditions) are used to define when an experience will become active for the user.
103
+
104
+ ```ts
105
+ import { createExperience, createStep } from '@picked/client/plugins/create-experience'
106
+
107
+ const productPageFunnel = createExperience({
108
+ id: 'product-page-funnel',
109
+ name: 'Product Page Funnel',
110
+ condition: {
111
+ and: [
112
+ {
113
+ '==': [
114
+ {
115
+ var: 'location.pathname',
116
+ },
117
+ '/product/:id',
118
+ ],
119
+ },
120
+ {
121
+ var: 'actions.isSaleActive',
122
+ },
123
+ ],
124
+ },
125
+ targets: [{ selector: 'body', placement: 'after' }],
126
+ })
127
+ ```
128
+
129
+ Navigation between steps is handled with [conditions](../conditions). Use the `create`
130
+
131
+ ```ts
132
+ import { createExperience, createStep } from '@picked/client/plugins/create-experience'
133
+ ```
@@ -0,0 +1,59 @@
1
+ ---
2
+ layout: docs
3
+ ---
4
+
5
+ # Dynamic Experiences Plugin
6
+
7
+ A plugin that fetches your project configuration from the Picked API at runtime, letting you manage experiences, features, steps, fields, and conditions entirely from the [dashboard](/experiences).
8
+
9
+ ## Setup Plugin
10
+
11
+ :::code-group
12
+
13
+ ```ts [app.ts]
14
+ import { createClient } from '@picked/client'
15
+ import { dynamicExperiencesPlugin } from '@picked/client/plugins/dynamic-experiences'
16
+
17
+ const client = createClient({
18
+ organizationId: 'your-org-id',
19
+ projectId: 'your-project-id',
20
+ plugins: [dynamicExperiencesPlugin()],
21
+ })
22
+
23
+ client.start()
24
+ ```
25
+
26
+ :::
27
+
28
+ :::tip
29
+ Unlike [createExperiencePlugin](./create-experience.md), you do not define experiences, steps, or fields in code. All configuration is managed from the [Picked dashboard](/experiences).
30
+ :::
31
+
32
+ ## How It Works
33
+
34
+ When the client starts, the plugin resolves your project configuration using a three-tier strategy:
35
+
36
+ 1. **Preview mode** — When you [enter preview mode from the dashboard](/workspaces#preview), the plugin fetches fresh config from the API. Feature decisions use session storage so they are not persisted beyond the current tab.
37
+
38
+ 2. **Build-time config** — If `projectConfig` was passed as a plugin option, or the [Vite Plugin](/tooling/vite-plugin) injected config at build time, the plugin uses that config with no network request.
39
+
40
+ 3. **Runtime fetch** — Otherwise, the plugin fetches config from the API when the client starts.
41
+
42
+ Once resolved, the plugin registers all features, conditions, fields, steps, and experiences with the client. Experiences then initialize according to their [conditions](/sdk/conditions) and [target selectors](/sdk/experiences).
43
+
44
+ :::note
45
+ The [Vite Plugin](/tooling/vite-plugin) eliminates the runtime API request in production by embedding your project config at build time. This is the recommended setup for Vite-based applications.
46
+ :::
47
+
48
+ ## Feature Allocation
49
+
50
+ Each [feature](/sdk/features) in your project has an `enabled` state and a `weight` (0–100) that controls the percentage of traffic allocated to it. The plugin uses a deterministic hash of the user's session ID to produce a stable allocation value. A user whose value falls below the feature weight is allocated to that feature — the same user always gets the same result.
51
+
52
+ Feature decisions are cached in `localStorage` by default, or `sessionStorage` when in [preview mode](#preview-mode).
53
+
54
+ ## Preview Mode
55
+
56
+ When you [enter preview mode from the dashboard](/workspaces#preview), the SDK receives a preview token and activates preview mode:
57
+
58
+ - The plugin fetches fresh config from the API using the token, bypassing any build-time or cached config
59
+ - Feature decisions use session storage, so closing the tab resets them
@@ -0,0 +1,9 @@
1
+ ---
2
+ layout: docs
3
+ ---
4
+
5
+ # Plugins
6
+
7
+ [Create Experience](./create-experience.md) — Define experiences, steps, and fields in code.
8
+
9
+ [Dynamic Experiences](./dynamic-experiences.md) — Fetch and register experiences from the Picked API at runtime.
@@ -0,0 +1,20 @@
1
+ ---
2
+ layout: docs
3
+ ---
4
+
5
+ # Window Object
6
+
7
+ A plugin to add the Picked client to the window object
8
+
9
+ ## Setup Plugin
10
+
11
+ ```ts
12
+ import { createClient } from '@picked/client'
13
+ import { windowObjectPlugin } from '@picked/client/plugins/window-object'
14
+
15
+ const client = createClient({
16
+ organizationId: 'your-org-id',
17
+ projectId: 'your-project-id',
18
+ plugins: [windowObjectPlugin()],
19
+ })
20
+ ```
@@ -0,0 +1,113 @@
1
+ ---
2
+ layout: docs
3
+ ---
4
+
5
+ # Predicates
6
+
7
+ Predicates enable reusable condition logic based on current application state. Each predicate is a pure function that receives a state snapshot containing responses, fields, browser context, and optional arguments.
8
+
9
+ ## Defining Predicates
10
+
11
+ Define predicates when creating the Picked client by passing a `predicates` object. Each predicate requires a unique identifier and a function that receives a state snapshot:
12
+
13
+ ```ts
14
+ import { createClient } from '@picked/client'
15
+
16
+ const client = createClient({
17
+ organizationId: 'your-org-id',
18
+ projectId: 'your-project-id',
19
+ predicates: {
20
+ 'is-example-page': ({ location }) => {
21
+ return location?.pathname === '/example'
22
+ },
23
+ 'get-account-tier': async () => {
24
+ const data = await fetch('/api/get-account-tier').then((r) => r.json())
25
+ return data.result // returns "trial"
26
+ },
27
+ },
28
+ })
29
+ ```
30
+
31
+ ## How Predicates Work
32
+
33
+ When a predicate is registered and used in conditions, the SDK follows this execution flow:
34
+
35
+ 1. **Registration**: Predicates are registered to the Picked client during initialization
36
+ 2. **State Snapshot Creation**: When invoked, predicates receive a frozen state snapshot containing current responses, fields, and browser context
37
+ 3. **Condition Evaluation**: Experience conditions invoke predicates with a fresh snapshot whenever called
38
+ 4. **Return Flexibility**: Predicates can return boolean, string, string array, undefined, or promises that resolve to these types
39
+
40
+ ## Using Predicates in Conditions
41
+
42
+ Predicates are most commonly used within condition logic via the `invoke` operator:
43
+
44
+ ```ts
45
+ const myExperience = createExperience({
46
+ // ... other config
47
+ condition: {
48
+ and: [
49
+ {
50
+ '==': [
51
+ {
52
+ invoke: {
53
+ var: 'predicates.is-example-page', // Reference predicate that calls user endpoint
54
+ },
55
+ },
56
+ true, // Check if return value is true
57
+ ],
58
+ },
59
+ {
60
+ '==': [
61
+ {
62
+ invoke: {
63
+ var: 'predicates.account-tier',
64
+ },
65
+ },
66
+ '/trial', // If string matches, evaluate to true
67
+ ],
68
+ },
69
+ ],
70
+ },
71
+ })
72
+ ```
73
+
74
+ :::tip
75
+ Predicates can also be used in `validation` logic
76
+ :::
77
+
78
+ ## Using the State Snapshot
79
+
80
+ Each predicate receives a `StateSnapshot` object with the following properties:
81
+
82
+ ```ts
83
+ interface StateSnapshot {
84
+ client: Picked // The Picked client instance
85
+ responses?: Array<{
86
+ // All user responses
87
+ fieldId: string
88
+ value: FieldValue | undefined
89
+ }>
90
+ args?: unknown[]
91
+ fields?: Field[] // All registered fields
92
+ location?: Location // Browser location (URL, pathname, search, etc.)
93
+ document?: Document // Browser document object
94
+ sessionStorage?: Storage // Browser sessionStorage API
95
+ localStorage?: Storage // Browser localStorage API
96
+ }
97
+ ```
98
+
99
+ :::warning
100
+ In server-side rendering or non-browser environments, `location`, `document`, `sessionStorage`,
101
+ and `localStorage` will be `undefined`.
102
+ :::
103
+
104
+ ## Best Practices
105
+
106
+ - **Keep predicates pure**: Predicates should be deterministic and side-effect free. Given the same snapshot, they should always return the same result
107
+ - **Handle missing data gracefully**: Always check if responses or fields exist before accessing their values. Return `undefined` when data is unavailable rather than throwing errors
108
+ - **Avoid heavy computations**: Predicates may be invoked frequently. Keep logic lightweight and fast
109
+ - **Use async sparingly**: While async predicates are supported, they can delay experience rendering. Prefer synchronous logic when possible
110
+ - **Return consistent types**: Don't mix return types (e.g., sometimes boolean, sometimes string) for the same predicate
111
+ - **Use meaningful names**: Predicate IDs should clearly describe what they evaluate (e.g., `is-premium-user`, `has-items-in-cart`)
112
+ - **Consider caching expensive operations**: If a predicate needs to perform expensive operations, consider caching the result in `localStorage` or `sessionStorage` within the predicate logic
113
+ - **Don't mutate the snapshot**: The state snapshot is frozen. Any attempt to modify it will throw an error in strict mode