@picked/client 0.0.1-dev.1785305085063 → 0.0.1-dev.1785908062293

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 (291) hide show
  1. package/dist/.tsbuildinfo +1 -0
  2. package/dist/api-03c5jvVk.js +38 -0
  3. package/dist/api-CQxCVIrm.cjs +1 -0
  4. package/dist/cjs/form/index.js +1 -1
  5. package/dist/cjs/index.js +2 -2
  6. package/dist/cjs/plugins/dom-observer/index.js +1 -1
  7. package/dist/cjs/plugins/dynamic-experiences/index.js +1 -1
  8. package/dist/cjs/server/index.js +1 -1
  9. package/dist/docs/explanation/conditions-and-the-logic-engine.md +94 -0
  10. package/dist/docs/explanation/feature-flag-allocation.md +176 -0
  11. package/dist/docs/explanation/how-picked-works.md +124 -0
  12. package/dist/docs/explanation/how-pickedql-works.md +76 -0
  13. package/dist/docs/explanation/pages-and-flows.md +64 -0
  14. package/dist/docs/explanation/the-content-model.md +77 -0
  15. package/dist/docs/explanation/the-two-apis.md +68 -0
  16. package/dist/docs/explanation/why-server-side-rendering.md +76 -0
  17. package/dist/docs/explanation/workspaces-and-versions.md +71 -0
  18. package/dist/docs/how-to/add-a-step-field-or-action.md +43 -0
  19. package/dist/docs/{pickedql/examples.md → how-to/analytics/index.md} +53 -28
  20. package/dist/docs/how-to/archive-or-delete-a-workspace.md +46 -0
  21. package/dist/docs/how-to/authenticate-with-a-magic-link.md +40 -0
  22. package/dist/docs/how-to/authenticate-with-a-password.md +51 -0
  23. package/dist/docs/how-to/authenticate-with-an-api-key.md +51 -0
  24. package/dist/docs/how-to/authenticate-with-oauth.md +40 -0
  25. package/dist/docs/how-to/build-a-flow.md +83 -0
  26. package/dist/docs/how-to/connect-the-mcp-server.md +38 -0
  27. package/dist/docs/how-to/create-a-project.md +29 -0
  28. package/dist/docs/how-to/create-an-experience.md +42 -0
  29. package/dist/docs/how-to/create-and-revoke-an-api-key.md +37 -0
  30. package/dist/docs/how-to/debug-with-the-chrome-extension.md +57 -0
  31. package/dist/docs/how-to/define-a-page-layout.md +39 -0
  32. package/dist/docs/how-to/fill-and-publish-a-page.md +50 -0
  33. package/dist/docs/how-to/install-the-gtm-template.md +84 -0
  34. package/dist/docs/how-to/install-the-sdk.md +68 -0
  35. package/dist/docs/how-to/install-the-vite-plugin.md +56 -0
  36. package/dist/docs/how-to/invite-and-remove-members.md +34 -0
  37. package/dist/docs/how-to/preview-a-workspace.md +28 -0
  38. package/dist/docs/how-to/publish-a-workspace.md +30 -0
  39. package/dist/docs/how-to/read-a-feature-flag.md +101 -0
  40. package/dist/docs/how-to/register-a-component.md +55 -0
  41. package/dist/docs/how-to/register-an-action-handler.md +67 -0
  42. package/dist/docs/how-to/render-a-step-form.md +132 -0
  43. package/dist/docs/how-to/render-an-unpublished-preview.md +41 -0
  44. package/dist/docs/how-to/reuse-a-section.md +37 -0
  45. package/dist/docs/how-to/reuse-a-step-field-or-action.md +28 -0
  46. package/dist/docs/how-to/roll-back-a-published-version.md +26 -0
  47. package/dist/docs/how-to/run-an-ab-test.md +49 -0
  48. package/dist/docs/how-to/run-code-on-a-form-submission.md +125 -0
  49. package/dist/docs/how-to/server-render-a-page.md +81 -0
  50. package/dist/docs/how-to/set-a-content-security-policy.md +32 -0
  51. package/dist/docs/how-to/set-up-mfa.md +69 -0
  52. package/dist/docs/how-to/upload-and-use-an-asset.mdx +73 -0
  53. package/dist/docs/how-to/validate-a-field.md +52 -0
  54. package/dist/docs/how-to/write-a-condition.md +45 -0
  55. package/dist/docs/how-to/write-a-predicate.md +60 -0
  56. package/dist/docs/index.md +41 -59
  57. package/dist/docs/reference/dashboard/actions.mdx +53 -0
  58. package/dist/docs/reference/dashboard/api-keys.mdx +37 -0
  59. package/dist/docs/reference/dashboard/conditions.mdx +42 -0
  60. package/dist/docs/reference/dashboard/content/asset-library.mdx +63 -0
  61. package/dist/docs/reference/dashboard/content/content-entries.mdx +44 -0
  62. package/dist/docs/reference/dashboard/content/layouts.mdx +62 -0
  63. package/dist/docs/reference/dashboard/content/pages.mdx +35 -0
  64. package/dist/docs/reference/dashboard/content/sections.mdx +28 -0
  65. package/dist/docs/reference/dashboard/experiences.mdx +51 -0
  66. package/dist/docs/reference/dashboard/features.mdx +114 -0
  67. package/dist/docs/reference/dashboard/fields.mdx +100 -0
  68. package/dist/docs/reference/dashboard/flow-builder/canvas.mdx +58 -0
  69. package/dist/docs/reference/dashboard/flow-builder/condition-builder.md +57 -0
  70. package/dist/docs/reference/dashboard/flow-builder/keyboard-shortcuts.md +72 -0
  71. package/dist/docs/reference/dashboard/flow-builder/nodes.md +63 -0
  72. package/dist/docs/reference/dashboard/projects.mdx +44 -0
  73. package/dist/docs/reference/dashboard/reports.mdx +43 -0
  74. package/dist/docs/reference/dashboard/steps.mdx +37 -0
  75. package/dist/docs/reference/dashboard/team-management.md +29 -0
  76. package/dist/docs/reference/dashboard/workspace-versioning.mdx +30 -0
  77. package/dist/docs/reference/dashboard/workspaces.mdx +76 -0
  78. package/dist/docs/{delivery-api → reference/delivery-api}/experience-content.md +17 -5
  79. package/dist/docs/reference/delivery-api/index.md +45 -0
  80. package/dist/docs/reference/delivery-api/preview-caching-crawling.md +79 -0
  81. package/dist/docs/{delivery-api → reference/delivery-api}/project-config.md +15 -6
  82. package/dist/docs/reference/glossary.md +173 -0
  83. package/dist/docs/reference/management-api/authentication.md +74 -0
  84. package/dist/docs/{api → reference/management-api}/authorization-and-scopes.md +70 -47
  85. package/dist/docs/reference/management-api/error-handling.md +233 -0
  86. package/dist/docs/{api → reference/management-api}/pagination.md +36 -20
  87. package/dist/docs/reference/pickedql/data-sources.md +174 -0
  88. package/dist/docs/reference/pickedql/dimensions.md +87 -0
  89. package/dist/docs/{pickedql → reference/pickedql}/filtering.md +17 -6
  90. package/dist/docs/reference/pickedql/index.md +18 -0
  91. package/dist/docs/reference/pickedql/schema.md +172 -0
  92. package/dist/docs/reference/pickedql/virtual-functions.md +237 -0
  93. package/dist/docs/reference/sdk/actions.md +30 -0
  94. package/dist/docs/{sdk → reference/sdk}/conditions.md +15 -5
  95. package/dist/docs/reference/sdk/content-security-policy.md +21 -0
  96. package/dist/docs/reference/sdk/experiences.md +51 -0
  97. package/dist/docs/reference/sdk/features.md +233 -0
  98. package/dist/docs/reference/sdk/fields.md +209 -0
  99. package/dist/docs/reference/sdk/index.md +68 -0
  100. package/dist/docs/{sdk → reference/sdk}/plugins/create-experience.md +25 -34
  101. package/dist/docs/reference/sdk/plugins/dynamic-experiences.md +74 -0
  102. package/dist/docs/reference/sdk/plugins/index.md +29 -0
  103. package/dist/docs/{sdk → reference/sdk}/plugins/window-object.md +6 -0
  104. package/dist/docs/reference/sdk/predicates.md +43 -0
  105. package/dist/docs/reference/sdk/ssr/index.md +33 -0
  106. package/dist/docs/reference/sdk/ssr/rendering-and-hydration.md +103 -0
  107. package/dist/docs/reference/sdk/ssr/serialize.md +77 -0
  108. package/dist/docs/reference/sdk/ssr/slots-and-placements.md +59 -0
  109. package/dist/docs/reference/sdk/steps.md +87 -0
  110. package/dist/docs/reference/tools/chrome-extension.md +16 -0
  111. package/dist/docs/reference/tools/image-optimisation-service.md +104 -0
  112. package/dist/docs/reference/tools/mcp.md +88 -0
  113. package/dist/docs/reference/tools/vite-plugin.md +88 -0
  114. package/dist/docs/tutorials/first-api-call.md +228 -0
  115. package/dist/docs/tutorials/first-experience-in-the-dashboard.mdx +143 -0
  116. package/dist/docs/tutorials/first-experience.mdx +255 -0
  117. package/dist/docs/tutorials/first-server-rendered-page.mdx +186 -0
  118. package/dist/{dom-BwmTHeT7.js → dom-BqcToNL0.js} +1 -3
  119. package/dist/{dom-CDrHc_j9.cjs → dom-DlLH3FxV.cjs} +1 -1
  120. package/dist/esm/form/index.js +2 -4
  121. package/dist/esm/index.js +225 -186
  122. package/dist/esm/plugins/dom-observer/index.js +1 -1
  123. package/dist/esm/plugins/dynamic-experiences/index.js +3 -3
  124. package/dist/esm/preview/index.js +1 -1
  125. package/dist/esm/server/index.js +33 -31
  126. package/dist/{experience-instance-DOJShRk5.js → experience-instance-DGk11d8a.js} +3 -3
  127. package/dist/experience-instance-Dej3P1sE.cjs +1 -0
  128. package/dist/plugin-CHOVsx7Z.js +287 -0
  129. package/dist/plugin-DsaGXQHx.cjs +1 -0
  130. package/dist/{preview-channel-DW9J8t4B.js → preview-channel-CSr96XAo.js} +1 -1
  131. package/dist/{protocol-DSqOlW2r.js → protocol-C5KkkiZc.js} +1 -1
  132. package/dist/types/client.d.ts +7 -6
  133. package/dist/types/data-source/api.d.ts +60 -0
  134. package/dist/types/data-source/api.d.ts.map +1 -0
  135. package/dist/types/data-source/provider.d.ts +97 -0
  136. package/dist/types/data-source/provider.d.ts.map +1 -0
  137. package/dist/types/entities/action/action.d.ts +5 -4
  138. package/dist/types/entities/action/action.d.ts.map +1 -1
  139. package/dist/types/entities/component/component.d.ts +6 -5
  140. package/dist/types/entities/component/component.d.ts.map +1 -1
  141. package/dist/types/entities/condition/condition.d.ts +5 -5
  142. package/dist/types/entities/content/content.d.ts +4 -3
  143. package/dist/types/entities/experience/experience.d.ts +11 -10
  144. package/dist/types/entities/experience/experience.d.ts.map +1 -1
  145. package/dist/types/entities/experience-instance/experience-instance.d.ts +10 -9
  146. package/dist/types/entities/feature/feature.d.ts +19 -2
  147. package/dist/types/entities/feature/feature.d.ts.map +1 -1
  148. package/dist/types/entities/field/field.d.ts +7 -6
  149. package/dist/types/entities/framework/framework.d.ts +7 -6
  150. package/dist/types/entities/framework/framework.d.ts.map +1 -1
  151. package/dist/types/entities/history/history.d.ts +6 -6
  152. package/dist/types/entities/plugin/plugin.d.ts +3 -2
  153. package/dist/types/entities/plugin/plugin.d.ts.map +1 -1
  154. package/dist/types/entities/predicate/predicate.d.ts +4 -3
  155. package/dist/types/entities/predicate/predicate.d.ts.map +1 -1
  156. package/dist/types/entities/response/response-validation.d.ts +3 -2
  157. package/dist/types/entities/response/response.d.ts +12 -11
  158. package/dist/types/entities/session/session.d.ts +2 -1
  159. package/dist/types/entities/step/step.d.ts +6 -5
  160. package/dist/types/exports.d.ts +2 -1
  161. package/dist/types/exports.d.ts.map +1 -1
  162. package/dist/types/form/build-responses.d.ts +2 -1
  163. package/dist/types/form/create-field-evaluator.d.ts +4 -3
  164. package/dist/types/form/create-field-validation.d.ts +5 -4
  165. package/dist/types/form/create-form.d.ts +7 -6
  166. package/dist/types/form/create-submit-pipeline.d.ts +7 -6
  167. package/dist/types/form/get-step-fields.d.ts +3 -2
  168. package/dist/types/lifecycle/condition-selection.d.ts +14 -4
  169. package/dist/types/lifecycle/lifecycle.d.ts +4 -3
  170. package/dist/types/lifecycle/rules-logic.d.ts +4 -3
  171. package/dist/types/lifecycle/state-snapshot.d.ts +4 -3
  172. package/dist/types/picked.d.ts +79 -62
  173. package/dist/types/picked.d.ts.map +1 -1
  174. package/dist/types/ping.d.ts +1 -1
  175. package/dist/types/ping.d.ts.map +1 -1
  176. package/dist/types/plugins/create-experience/create-experience.d.ts +9 -8
  177. package/dist/types/plugins/create-experience/create-experience.d.ts.map +1 -1
  178. package/dist/types/plugins/create-experience/plugin.d.ts +3 -2
  179. package/dist/types/plugins/create-experience/plugin.d.ts.map +1 -1
  180. package/dist/types/plugins/create-experience/serialization.d.ts.map +1 -1
  181. package/dist/types/plugins/dom-observer/plugin.d.ts +1 -1
  182. package/dist/types/plugins/dynamic-experiences/hash.d.ts +40 -5
  183. package/dist/types/plugins/dynamic-experiences/hash.d.ts.map +1 -1
  184. package/dist/types/plugins/dynamic-experiences/index.d.ts +2 -0
  185. package/dist/types/plugins/dynamic-experiences/index.d.ts.map +1 -1
  186. package/dist/types/plugins/dynamic-experiences/plugin.d.ts +4 -36
  187. package/dist/types/plugins/dynamic-experiences/plugin.d.ts.map +1 -1
  188. package/dist/types/plugins/dynamic-experiences/types.d.ts +42 -11
  189. package/dist/types/plugins/dynamic-experiences/types.d.ts.map +1 -1
  190. package/dist/types/plugins/experience-browser-storage/plugin.d.ts +1 -1
  191. package/dist/types/plugins/experience-browser-storage/plugin.d.ts.map +1 -1
  192. package/dist/types/plugins/history-browser-storage/plugin.d.ts +1 -1
  193. package/dist/types/plugins/history-browser-storage/plugin.d.ts.map +1 -1
  194. package/dist/types/plugins/responses-browser-storage/plugin.d.ts +1 -1
  195. package/dist/types/plugins/responses-browser-storage/plugin.d.ts.map +1 -1
  196. package/dist/types/plugins/responses-indexeddb/plugin.d.ts +1 -1
  197. package/dist/types/plugins/single-page-app/plugin.d.ts +1 -1
  198. package/dist/types/plugins/single-page-app/plugin.d.ts.map +1 -1
  199. package/dist/types/plugins/web-components/plugin.d.ts +2 -1
  200. package/dist/types/plugins/window-object/plugin.d.ts +2 -2
  201. package/dist/types/preview-channel.d.ts +5 -1
  202. package/dist/types/preview-receiver/index.d.ts +18 -1
  203. package/dist/types/preview-receiver/protocol.d.ts +10 -1
  204. package/dist/types/server/index.d.ts +3 -3
  205. package/dist/types/server/serialize.d.ts +8 -2
  206. package/dist/types/server/serialize.d.ts.map +1 -1
  207. package/dist/types/utils/dom.d.ts +2 -1
  208. package/dist/types/utils/events.d.ts +6 -6
  209. package/dist/types/utils/events.d.ts.map +1 -1
  210. package/dist/types/utils/global-obj.d.ts +1 -1
  211. package/dist/types/utils/global-obj.d.ts.map +1 -1
  212. package/dist/types/utils/id.d.ts.map +1 -1
  213. package/dist/types/utils/logger.d.ts +2 -1
  214. package/dist/types/utils/logger.d.ts.map +1 -1
  215. package/dist/types/utils/node-tree/get-next-node-from-action.d.ts +2 -1
  216. package/dist/types/utils/node-tree/get-next-node-from-condition.d.ts +2 -1
  217. package/dist/types/utils/node-tree/get-next-node.d.ts +1 -1
  218. package/dist/types/utils/node-tree/get-next-node.d.ts.map +1 -1
  219. package/dist/types/utils/node-tree/get-origin-node.d.ts +1 -1
  220. package/dist/types/utils/node-tree/get-origin-node.d.ts.map +1 -1
  221. package/dist/types/utils/node-tree/min-max-steps-to-leaf.d.ts +1 -1
  222. package/dist/types/utils/node-tree/min-max-steps-to-leaf.d.ts.map +1 -1
  223. package/dist/types/utils/node-tree/min-max-steps-to-origin.d.ts +1 -1
  224. package/dist/types/utils/node-tree/min-max-steps-to-origin.d.ts.map +1 -1
  225. package/dist/types/utils/node-tree/next-reachable-step-nodes.d.ts +1 -1
  226. package/dist/types/utils/node-tree/next-reachable-step-nodes.d.ts.map +1 -1
  227. package/dist/types/utils/nodes.d.ts +1 -1
  228. package/dist/types/utils/picked-config.d.ts +2 -1
  229. package/dist/types/utils/rehydrate-scripts.d.ts +6 -0
  230. package/dist/types/utils/rehydrate-scripts.d.ts.map +1 -1
  231. package/dist/types/utils/rules-logic.d.ts +6 -2
  232. package/dist/types/utils/storage.d.ts +1 -1
  233. package/dist/types/utils/storage.d.ts.map +1 -1
  234. package/package.json +22 -23
  235. package/dist/api-CPL40b7A.js +0 -40
  236. package/dist/api-Dz5rgRgQ.cjs +0 -1
  237. package/dist/docs/actions.mdx +0 -78
  238. package/dist/docs/api/authentication.md +0 -376
  239. package/dist/docs/api/error-handling.md +0 -211
  240. package/dist/docs/api/index.md +0 -197
  241. package/dist/docs/api-keys.mdx +0 -40
  242. package/dist/docs/chrome-extension.md +0 -51
  243. package/dist/docs/conditions.mdx +0 -59
  244. package/dist/docs/content/asset-library.mdx +0 -93
  245. package/dist/docs/content/content-entries.mdx +0 -30
  246. package/dist/docs/content/layouts.mdx +0 -70
  247. package/dist/docs/content/pages.mdx +0 -67
  248. package/dist/docs/content/sections.mdx +0 -33
  249. package/dist/docs/delivery-api/index.md +0 -46
  250. package/dist/docs/delivery-api/preview-caching-crawling.md +0 -59
  251. package/dist/docs/experiences.mdx +0 -42
  252. package/dist/docs/features.mdx +0 -58
  253. package/dist/docs/fields.mdx +0 -79
  254. package/dist/docs/flow-builder/building-flows.md +0 -61
  255. package/dist/docs/flow-builder/condition-builder.md +0 -54
  256. package/dist/docs/flow-builder/keyboard-shortcuts.md +0 -66
  257. package/dist/docs/flow-builder/nodes.md +0 -43
  258. package/dist/docs/flow-builder/overview.mdx +0 -50
  259. package/dist/docs/gtm-template.md +0 -69
  260. package/dist/docs/guides/build-a-personalized-page.mdx +0 -143
  261. package/dist/docs/image-optimisation-service.md +0 -80
  262. package/dist/docs/mcp.md +0 -120
  263. package/dist/docs/pickedql/data-sources.md +0 -145
  264. package/dist/docs/pickedql/dimensions.md +0 -65
  265. package/dist/docs/pickedql/index.md +0 -36
  266. package/dist/docs/pickedql/schema.md +0 -156
  267. package/dist/docs/pickedql/virtual-functions.md +0 -204
  268. package/dist/docs/projects.mdx +0 -37
  269. package/dist/docs/reports.mdx +0 -18
  270. package/dist/docs/sdk/actions.md +0 -66
  271. package/dist/docs/sdk/content-security-policy.md +0 -32
  272. package/dist/docs/sdk/experiences.md +0 -46
  273. package/dist/docs/sdk/features.md +0 -212
  274. package/dist/docs/sdk/fields.md +0 -263
  275. package/dist/docs/sdk/index.md +0 -83
  276. package/dist/docs/sdk/plugins/dynamic-experiences.md +0 -58
  277. package/dist/docs/sdk/plugins/index.md +0 -9
  278. package/dist/docs/sdk/predicates.md +0 -112
  279. package/dist/docs/sdk/ssr/index.md +0 -62
  280. package/dist/docs/sdk/ssr/rendering-and-hydration.md +0 -141
  281. package/dist/docs/sdk/ssr/serialize.md +0 -86
  282. package/dist/docs/sdk/ssr/slots-and-placements.md +0 -35
  283. package/dist/docs/sdk/steps.md +0 -434
  284. package/dist/docs/steps.mdx +0 -44
  285. package/dist/docs/team-management.md +0 -40
  286. package/dist/docs/vite-plugin.md +0 -82
  287. package/dist/docs/workspace-versioning.mdx +0 -28
  288. package/dist/docs/workspaces.mdx +0 -102
  289. package/dist/experience-instance-DurC3pE-.cjs +0 -1
  290. package/dist/plugin-CFXwbXeM.js +0 -247
  291. package/dist/plugin-m4qekgtA.cjs +0 -1
@@ -0,0 +1,71 @@
1
+ ---
2
+ type: explanation
3
+ layout: docs
4
+ ---
5
+
6
+ # About workspaces and versions
7
+
8
+ Why can you not edit what your visitors see? Because Picked keeps two things separate on
9
+ purpose: the work in progress, and the thing that it serves.
10
+
11
+ ## The two states
12
+
13
+ A **workspace** holds your changes. Edit a flow, a feature flag, a step, a field, an
14
+ action, or a condition, and the change stays in the workspace. No visitor sees it.
15
+
16
+ A **version** is what your visitors get. When you publish, Picked takes the current
17
+ workspace and makes an immutable snapshot of it. A project serves exactly one version at a
18
+ time, the live one.
19
+
20
+ Everything else follows from that split.
21
+
22
+ ## Why the snapshot is immutable
23
+
24
+ A published version cannot change. That is what makes a roll-back safe. When you restore
25
+ an earlier version, Picked moves the live pointer of the project and changes no data. The
26
+ version that you restore is the exact version that was live before, and not a copy that
27
+ Picked builds again.
28
+
29
+ It is also what lets your draft continue. When you publish, your workspace stays
30
+ editable, and a roll-back discards no draft. The two move at their own speed.
31
+
32
+ ## The three workspace states
33
+
34
+ - **Live** — the workspace whose snapshot the SDK serves. Each project has exactly one.
35
+ - **Draft** — a workspace that no visitor sees. Edit it, see a preview of it, publish it.
36
+ - **Archived** — a draft that you put to one side. It is still editable, but it is out of
37
+ the default list.
38
+
39
+ Picked keeps these two operations separate on purpose. Archive a draft when you are not
40
+ certain about it. You cannot reverse a delete, but you can always unarchive.
41
+
42
+ ## Why the publish modal shows a diff
43
+
44
+ It is the one step in the dashboard that you cannot take back. It is therefore the one
45
+ place that shows you exactly what changes. The modal compares the current workspace
46
+ against the last published snapshot. It puts the changes into groups, and marks each row
47
+ added, removed, or modified.
48
+
49
+ The diff also carries a warning that a plain list of changes cannot give you. Some changes
50
+ break other records. Remove a field while steps still point at it, and those steps
51
+ now have an error. The preview shows that above the diff, before you publish and not after.
52
+
53
+ The first publish of a workspace has no earlier snapshot to compare against, so the modal
54
+ shows the contents instead of a diff.
55
+
56
+ ## A preview does not reach production
57
+
58
+ A preview sends the workspace state to the SDK in the query parameters. Your unpublished
59
+ workspace therefore applies to your browser and to nothing else. The visitors on your live
60
+ site see no change.
61
+
62
+ One result of this matters. In a preview the SDK stores a feature flag decision in session
63
+ storage and not in local storage. A preview allocation is therefore disposable, and it can
64
+ differ from a production one. See
65
+ [About feature flag allocation](/explanation/feature-flag-allocation).
66
+
67
+ ## Related
68
+
69
+ - [About how Picked works](/explanation/how-picked-works) — what a publish feeds.
70
+ - [Workspaces](/reference/dashboard/workspaces) — the states and the settings.
71
+ - [Publish history](/reference/dashboard/workspace-versioning) — the version list.
@@ -0,0 +1,43 @@
1
+ ---
2
+ type: how-to
3
+ layout: docs
4
+ ---
5
+
6
+ # How to add a step, a field, an action, or a condition
7
+
8
+ This guide shows you how to create the parts that a flow is built from. All four follow
9
+ the same shape, and all four belong to the project: you can use one in more than one flow.
10
+
11
+ ## Steps
12
+
13
+ 1. Open a flow. The library is on the left of the flow builder.
14
+ 2. Find the **Steps**, **Fields**, **Actions**, or **Conditions** section in it.
15
+ 3. Click the **+** next to that section.
16
+ 4. Enter a name. The dashboard makes the key from it.
17
+ 5. Click the **Create** button for that kind: **Create step**, **Create field**,
18
+ **Create action**, **Create condition**.
19
+
20
+ The flow builder opens again, and the new one is in the library.
21
+
22
+ **Fields** also has its own sidebar entry, so you can make a field without a flow. A step,
23
+ an action, and a condition belong to a flow, and the library is the only way to reach
24
+ them.
25
+
26
+ The key is the identifier that your application uses. You set it one time, and you cannot
27
+ change it later. Your visitors never see a name or a key.
28
+
29
+ ## What each one needs after that
30
+
31
+ | Kind | Set this next |
32
+ | --- | --- |
33
+ | Step | A **Layout**, such as `card`, `modal`, or `fullscreen`. |
34
+ | Field | A **Label**, a type, and any validation rule. |
35
+ | Action | Nothing in the dashboard. Register the handler in your code. |
36
+ | Condition | The rule, in the **Logic** section of the inspector. |
37
+
38
+ ## Related
39
+
40
+ - [How to build a flow](/how-to/build-a-flow) — put it on the canvas.
41
+ - [How to write a condition](/how-to/write-a-condition)
42
+ - [How to register an action handler](/how-to/register-an-action-handler)
43
+ - [How to reuse a step, a field, or an action](/how-to/reuse-a-step-field-or-action)
@@ -1,8 +1,16 @@
1
1
  ---
2
+ type: how-to
2
3
  layout: docs
3
4
  ---
4
5
 
5
- # Example queries
6
+ # How to run an analytics query
7
+
8
+ This guide gives you a query for each common analytics question. Copy one, put your own
9
+ project ID in the `WHERE` clause, and run it.
10
+
11
+ Every query must carry a tenant filter. See
12
+ [About PickedQL](/explanation/how-pickedql-works) for why, and
13
+ [Data sources](/reference/pickedql/data-sources) for every table.
6
14
 
7
15
  ## Daily A/B test trend
8
16
 
@@ -51,7 +59,9 @@ ORDER BY project_local_date
51
59
 
52
60
  ## Custom conversion rate definition
53
61
 
54
- Override the default purchase conversion with your own numerator and denominator. Useful when conversion is defined by a form submission, lead capture, or any custom event.
62
+ Override the default conversion, which counts a `purchase` event, with your own
63
+ numerator and denominator. Use this when a form submission, a lead capture, or
64
+ another event of your own defines a conversion.
55
65
 
56
66
  ```sql
57
67
  -- Lead capture conversion: form submissions / lead-capture step entries
@@ -75,7 +85,7 @@ ORDER BY project_local_date
75
85
  You can also combine multiple events with `OR` and group with parentheses:
76
86
 
77
87
  ```sql
78
- -- Either checkout_complete or order_create counts as a conversion
88
+ -- A `checkout_complete` event or an `order_create` event counts as a conversion.
79
89
  SELECT
80
90
  control_conversion_rate(
81
91
  'event_type=checkout_complete OR event_type=order_create'
@@ -87,12 +97,15 @@ FROM events
87
97
  WHERE project_id = '{{ your project ID }}'
88
98
  ```
89
99
 
90
- ## Custom segment with `control_users` / `variant_users`
100
+ ## Your own segment with `control_users` and `variant_users`
91
101
 
92
- On `events`, `control_users` / `variant_users` / `control_sessions` / `variant_sessions` accept an optional filter string to count only users/sessions matching the given expression in addition to the implicit `variant_type` filter.
102
+ On `events`, four functions take an optional filter string: `control_users`,
103
+ `variant_users`, `control_sessions`, and `variant_sessions`. The filter counts only a
104
+ user or a session that matches your expression. It applies together with the
105
+ `variant_type` filter that PickedQL adds.
93
106
 
94
107
  ```sql
95
- -- Control users who fired app_initialize, broken down by step
108
+ -- The control users who fired an `app_initialize` event, by step.
96
109
  SELECT
97
110
  step_id,
98
111
  control_users('event_type=app_initialize') AS control_initialized,
@@ -113,10 +126,13 @@ WHERE project_id = '{{ your project ID }}'
113
126
 
114
127
  ## Conversion rate from nested virtual functions
115
128
 
116
- When numerator and denominator come from different segments — e.g., Control users who fired a custom event divided by **all** users (not just Control) — pass virtual function calls directly as conversion-rate args:
129
+ The numerator and the denominator can come from different segments. An example is the
130
+ control users who fired an event of your own, divided by **all** users and not by the
131
+ control users alone. For that, pass a virtual function call directly as an argument
132
+ of the conversion rate:
117
133
 
118
134
  ```sql
119
- -- (Control users who fired app_initialize) / (all users, regardless of variant)
135
+ -- The control users who fired `app_initialize`, over all users of every variant.
120
136
  SELECT
121
137
  control_conversion_rate(
122
138
  control_users('event_type=app_initialize'),
@@ -188,9 +204,9 @@ GROUP BY utm_source
188
204
 
189
205
  | utm_source | users | purchasers |
190
206
  | ---------- | ------ | ---------- |
191
- | meta | 12031 | 101 |
192
- | fb | 3656 | 31 |
193
- | an | 100366 | 299 |
207
+ | `meta` | 12031 | 101 |
208
+ | `fb` | 3656 | 31 |
209
+ | `an` | 100366 | 299 |
194
210
 
195
211
  ## Step funnel for variant users
196
212
 
@@ -211,18 +227,19 @@ ORDER BY variant DESC
211
227
 
212
228
  | step_id | variant |
213
229
  | ------------------------------ | ------- |
214
- | who-are-you-protecting-step | 1093 |
215
- | about-yourself-step | 533 |
216
- | date-of-birth-step | 435 |
217
- | employment-status-step | 408 |
218
- | nicotine-usage-step | 407 |
219
- | coverage-motivation-step | 405 |
220
- | lead-capture-step | 398 |
230
+ | `who-are-you-protecting-step` | 1093 |
231
+ | `about-yourself-step` | 533 |
232
+ | `date-of-birth-step` | 435 |
233
+ | `employment-status-step` | 408 |
234
+ | `nicotine-usage-step` | 407 |
235
+ | `coverage-motivation-step` | 405 |
236
+ | `lead-capture-step` | 398 |
221
237
 
222
238
 
223
239
  ## Sankey — overall user journey
224
240
 
225
- Forward window from the starting step. Non-reachers of `targeting_step` still contribute edges up to `num_nodes_after_start`. Mirrors dashboard 1156 card 4129's semantics.
241
+ A forward window from the starting step. A user who never reaches `targeting_step`
242
+ still gives edges, up to `num_nodes_after_start`.
226
243
 
227
244
  ```sql
228
245
  SELECT source, target, users FROM experience_journey
@@ -236,13 +253,14 @@ WHERE project_id = '{{ your project ID }}'
236
253
 
237
254
  | source | target | users |
238
255
  | ------------------------- | ------------------------- | ----- |
239
- | 001. step-start | 002. step-questionnaire-1 | 182 |
240
- | 002. step-questionnaire-1 | 003. step-quote | 144 |
241
- | 003. step-quote | 004. step-target | 121 |
256
+ | `001. step-start` | `002. step-questionnaire-1` | 182 |
257
+ | `002. step-questionnaire-1` | `003. step-quote` | 144 |
258
+ | `003. step-quote` | `004. step-target` | 121 |
242
259
 
243
- ## Sankey — top paths leading to a target step
260
+ ## Sankey — the top paths to a target step
244
261
 
245
- Backward window anchored at the target, plus top-N path ranking. Mirrors dashboard 1156 card 3961 / dashboard 991 card 2740 semantics.
262
+ A backward window anchored at the target. It also ranks the paths and keeps the ones
263
+ with the most users.
246
264
 
247
265
  ```sql
248
266
  SELECT source, target, users FROM experience_journey
@@ -256,7 +274,7 @@ WHERE project_id = '{{ your project ID }}'
256
274
 
257
275
  ## Sankey — drop-off view
258
276
 
259
- Starts at `starting_step` and emits every consecutive transition until `num_nodes_after_start` steps later (no target). Mirrors card 2744.
277
+ Starts at `starting_step` and emits every consecutive transition until `num_nodes_after_start` steps later (no target).
260
278
 
261
279
  ```sql
262
280
  SELECT source, target, users FROM experience_journey
@@ -284,6 +302,13 @@ WHERE project_id = '{{ your project ID }}'
284
302
 
285
303
  | device_category | user_canonical_id |
286
304
  | --------------- | ------------------------------------ |
287
- | Mobile | 019cc336-5a6a-7c32-b638-cdcc983b3e70 |
288
- | Mobile | 019cc336-5a6a-7d8f-994c-69bc28e5f550 |
289
- | Mobile | 019cc80f-503c-7181-b2c6-986b1f76d496 |
305
+ | Mobile | `019cc336-5a6a-7c32-b638-cdcc983b3e70` |
306
+ | Mobile | `019cc336-5a6a-7d8f-994c-69bc28e5f550` |
307
+ | Mobile | `019cc80f-503c-7181-b2c6-986b1f76d496` |
308
+
309
+ ## Related
310
+
311
+ - [About PickedQL](/explanation/how-pickedql-works) — what the layer expands for you.
312
+ - [Virtual functions](/reference/pickedql/virtual-functions) — every function.
313
+ - [Dimensions](/reference/pickedql/dimensions) — every dimension column.
314
+ - [Reports](/reference/dashboard/reports) — the same data as an embedded dashboard.
@@ -0,0 +1,46 @@
1
+ ---
2
+ type: how-to
3
+ layout: docs
4
+ ---
5
+
6
+ # How to archive or delete a workspace
7
+
8
+ This guide shows you how to take a draft workspace out of use. Archive it when you want
9
+ to keep it. Delete it only when you are certain, because you cannot reverse a delete.
10
+
11
+ You cannot archive or delete a live workspace. Make a different workspace live first.
12
+
13
+ ## Archive a workspace
14
+
15
+ 1. Open the workspace settings page.
16
+ 2. Click **Archive workspace** in the page header.
17
+ 3. Confirm in the modal.
18
+
19
+ The workspace leaves the default list. It stays editable.
20
+
21
+ ## Unarchive a workspace
22
+
23
+ 1. Open the workspace settings page.
24
+ 2. Click **Unarchive workspace** in the page header.
25
+
26
+ ## Delete a workspace
27
+
28
+ 1. Open the workspace settings page.
29
+ 2. Click **Delete workspace**.
30
+ 3. Confirm in the modal.
31
+
32
+ Picked removes the workspace, and everything in it, permanently.
33
+
34
+ ## Rename a workspace
35
+
36
+ 1. Open the workspace settings page.
37
+ 2. Change the **Workspace name** field.
38
+ 3. Click **Save changes**.
39
+
40
+ A name is unique inside a project. The dashboard rejects a duplicate name.
41
+
42
+ ## Related
43
+
44
+ - [About workspaces and versions](/explanation/workspaces-and-versions) — why Picked keeps
45
+ these two operations separate.
46
+ - [Workspaces](/reference/dashboard/workspaces) — the settings reference.
@@ -0,0 +1,40 @@
1
+ ---
2
+ type: how-to
3
+ layout: docs
4
+ ---
5
+
6
+ # How to authenticate with a magic link
7
+
8
+ This guide shows you how to sign a user in through an email address, with no password.
9
+
10
+ ## 1. Send the link
11
+
12
+ ```graphql
13
+ mutation {
14
+ magicLinkSend(input: {
15
+ email: "user@example.com"
16
+ redirectUrl: "https://app.example.com/auth/verify"
17
+ }) {
18
+ success
19
+ }
20
+ }
21
+ ```
22
+
23
+ The user receives an email, and the link in it holds a token.
24
+
25
+ ## 2. Verify the token
26
+
27
+ ```graphql
28
+ mutation {
29
+ magicLinkVerify(input: {
30
+ email: "user@example.com"
31
+ token: "token-from-magic-link"
32
+ }) {
33
+ session { accessToken refreshToken }
34
+ }
35
+ }
36
+ ```
37
+
38
+ ## Related
39
+
40
+ - [Authentication](/reference/management-api/authentication) — every mutation.
@@ -0,0 +1,51 @@
1
+ ---
2
+ type: how-to
3
+ layout: docs
4
+ ---
5
+
6
+ # How to authenticate with a password
7
+
8
+ This guide shows you how to get an access token from an email address and a password.
9
+
10
+ ## 1. Create a session
11
+
12
+ ```graphql
13
+ mutation {
14
+ sessionCreate(input: {
15
+ email: "user@example.com"
16
+ password: "secure-password"
17
+ }) {
18
+ session { accessToken refreshToken expiresAt }
19
+ requiresMfa
20
+ }
21
+ }
22
+ ```
23
+
24
+ When `requiresMfa` is `true`, complete the challenge first. See
25
+ [How to set up MFA](/how-to/set-up-mfa).
26
+
27
+ ## 2. Send the token
28
+
29
+ ```
30
+ Authorization: Bearer <accessToken>
31
+ ```
32
+
33
+ ## 3. Refresh before it expires
34
+
35
+ The `expiresAt` field gives the time at which the access token expires.
36
+
37
+ ```graphql
38
+ mutation {
39
+ sessionRefresh(input: { refreshToken: "v1.refresh-token..." }) {
40
+ session { accessToken refreshToken expiresAt }
41
+ }
42
+ }
43
+ ```
44
+
45
+ The API invalidates the earlier refresh token. This mutation needs no `Authorization`
46
+ header.
47
+
48
+ ## Related
49
+
50
+ - [Authentication](/reference/management-api/authentication) — every mutation.
51
+ - [Your first API call](/tutorials/first-api-call).
@@ -0,0 +1,51 @@
1
+ ---
2
+ type: how-to
3
+ layout: docs
4
+ ---
5
+
6
+ # How to authenticate with an API key
7
+
8
+ This guide shows you how to authenticate a server-to-server integration. An API key gives
9
+ access for a long time, inside a set of scopes.
10
+
11
+ ## 1. Create the key
12
+
13
+ Only a user with a session can create a key. Another API key cannot.
14
+
15
+ ```graphql
16
+ mutation {
17
+ apiKeyCreate(input: {
18
+ organizationId: "org-id"
19
+ name: "CI/CD Pipeline Key"
20
+ projectId: "project-id"
21
+ scopes: [ORGANIZATION_READ, ORGANIZATION_PROJECTS_READ]
22
+ }) {
23
+ apiKey
24
+ }
25
+ }
26
+ ```
27
+
28
+ The response holds the full key one time only. Keep it in a secure place.
29
+
30
+ The scopes that you ask for must all be scopes of the user who creates the key.
31
+
32
+ ## 2. Send the key
33
+
34
+ ```
35
+ x-api-key: pk_live_abc123...
36
+ ```
37
+
38
+ ## 3. Revoke the key
39
+
40
+ ```graphql
41
+ mutation {
42
+ apiKeyRevoke(input: { keyId: "key-id", organizationId: "org-id" })
43
+ }
44
+ ```
45
+
46
+ ## Related
47
+
48
+ - [Authorization and scopes](/reference/management-api/authorization-and-scopes) — every
49
+ scope.
50
+ - [How to create and revoke an API key](/how-to/create-and-revoke-an-api-key) — the
51
+ dashboard path.
@@ -0,0 +1,40 @@
1
+ ---
2
+ type: how-to
3
+ layout: docs
4
+ ---
5
+
6
+ # How to authenticate with OAuth
7
+
8
+ This guide shows you how to sign a user in through Google.
9
+
10
+ ## 1. Get the authorization URL
11
+
12
+ ```graphql
13
+ mutation {
14
+ oauthAuthorize(input: {
15
+ provider: GOOGLE
16
+ redirectUrl: "https://app.example.com/auth/callback"
17
+ scopes: ["openid", "email", "profile"]
18
+ }) {
19
+ url
20
+ }
21
+ }
22
+ ```
23
+
24
+ ## 2. Send the user to that URL
25
+
26
+ Google authenticates the user and sends them back with a `code` parameter.
27
+
28
+ ## 3. Exchange the code
29
+
30
+ ```graphql
31
+ mutation {
32
+ oauthCallback(input: { provider: GOOGLE, code: "auth-code-from-google" }) {
33
+ session { accessToken refreshToken expiresAt }
34
+ }
35
+ }
36
+ ```
37
+
38
+ ## Related
39
+
40
+ - [Authentication](/reference/management-api/authentication) — every mutation.
@@ -0,0 +1,83 @@
1
+ ---
2
+ type: how-to
3
+ layout: docs
4
+ ---
5
+
6
+ # How to build a flow
7
+
8
+ This guide shows you how to put a flow together on the canvas. You need an experience
9
+ first. See [How to create an experience](/how-to/create-an-experience).
10
+
11
+ ## Add nodes
12
+
13
+ Drag a step, an action, or a condition from the library onto the canvas. A new
14
+ node appears where you drop it.
15
+
16
+ You can also drop a block directly onto an arrow that is there already. The flow
17
+ builder puts the node into the line. The first arrow splits into two arrows, with the
18
+ new node between them. A **+** indicator appears when you hold the pointer over a
19
+ valid arrow.
20
+
21
+ ## Connect nodes
22
+
23
+ Click the output handle of a node, on the right side. Drag to the input handle of
24
+ another node, on the left side. An arrow then joins the two nodes.
25
+
26
+ The flow follows the arrows from left to right, and it starts at the origin. Every
27
+ node after the origin is part of the experience flow.
28
+
29
+ ## Branch with conditions
30
+
31
+ Connect the origin, or any other node, to a condition node. The condition evaluates
32
+ its rule and sends the flow down one of two paths.
33
+
34
+ Connect the green handle, for a true result, to the nodes that must run when the
35
+ condition holds. Connect the red handle, for a false result, to the other path. Each
36
+ path can lead to more steps, more actions, and more conditions.
37
+
38
+ ## Assign fields to steps
39
+
40
+ Drag a field from the library onto a step node and drop it. That step then
41
+ holds the field.
42
+
43
+ You can assign more than one field to one step. The step node gives the number of
44
+ assigned fields. To see which fields it holds, choose the step. Then read the **Fields**
45
+ section in the inspector.
46
+
47
+ ## Choose nodes
48
+
49
+ Click a node to choose it. Its inspector opens in the right panel.
50
+
51
+ Drag on empty canvas to choose every node inside a rectangle. Press `Cmd/Ctrl+A` to
52
+ choose every node.
53
+
54
+ When you choose more than one node, the inspector gives a count and a list in groups.
55
+ Click an item in that list to open its inspector.
56
+
57
+ ## Move nodes
58
+
59
+ Drag a node to move it. Each node snaps to the grid.
60
+
61
+ Use the arrow keys to move a node a small distance. Hold `Shift` to move it further.
62
+
63
+ ## Delete nodes
64
+
65
+ Choose one or more nodes. Press `Delete` or `Backspace`. The flow builder removes
66
+ those nodes and every arrow that joins them.
67
+
68
+ ## Duplicate nodes
69
+
70
+ Choose one or more nodes. Press `Cmd/Ctrl+D`. A copy of each node appears next to the
71
+ first one.
72
+
73
+ ## Undo and redo
74
+
75
+ Press `Cmd/Ctrl+Z` to undo. Press `Cmd/Ctrl+Shift+Z` to redo. The undo stack records
76
+ each node that you add, each node that you delete, each connection, and each move.
77
+
78
+ ## Related
79
+
80
+ - [Canvas](/reference/dashboard/flow-builder/canvas) — the panels and the view controls.
81
+ - [Nodes](/reference/dashboard/flow-builder/nodes) — every node type.
82
+ - [Keyboard shortcuts](/reference/dashboard/flow-builder/keyboard-shortcuts)
83
+ - [About how Picked works](/explanation/how-picked-works) — why a flow is a graph.
@@ -0,0 +1,38 @@
1
+ ---
2
+ type: how-to
3
+ layout: docs
4
+ ---
5
+
6
+ # How to connect the MCP server
7
+
8
+ This guide shows you how to control your Picked workspace from an AI tool that writes
9
+ code. The server URL is `https://api.picked.app/mcp`.
10
+
11
+ ## Claude Desktop
12
+
13
+ 1. Open **Settings > Connectors > Add custom connector**.
14
+ 2. Set **Name** to `Picked`.
15
+ 3. Set **URL** to `https://api.picked.app/mcp`.
16
+ 4. Click **Connect**.
17
+ 5. Answer the authorization prompt.
18
+
19
+ ## Claude Code, Cursor, Windsurf, and others
20
+
21
+ Add `.mcp.json` to the root of your repository:
22
+
23
+ ```json
24
+ {
25
+ "mcpServers": {
26
+ "picked": {
27
+ "type": "http",
28
+ "url": "https://api.picked.app/mcp"
29
+ }
30
+ }
31
+ }
32
+ ```
33
+
34
+ Cursor reads the same content from `.cursor/mcp.json`.
35
+
36
+ ## Related
37
+
38
+ - [MCP server](/reference/tools/mcp) — every tool that the server gives you.
@@ -0,0 +1,29 @@
1
+ ---
2
+ type: how-to
3
+ layout: docs
4
+ ---
5
+
6
+ # How to create a project
7
+
8
+ This guide shows you how to add a project. A project is one site or one application, and
9
+ it holds its own experiences, content, and options.
10
+
11
+ ## Steps
12
+
13
+ 1. Open your organization.
14
+ 2. Click **New project**.
15
+ 3. Enter a name.
16
+ 4. Click **Create project**.
17
+
18
+ The project home page opens. It shows your SDK snippet and the setup tasks that are still
19
+ open.
20
+
21
+ ## Next
22
+
23
+ Copy the snippet and add it to your site. See
24
+ [How to install the SDK](/how-to/install-the-sdk).
25
+
26
+ ## Related
27
+
28
+ - [Projects](/reference/dashboard/projects) — the project surface.
29
+ - [Add Picked to your application](/tutorials/first-experience) — the whole path.