@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
@@ -1,65 +0,0 @@
1
- ---
2
- layout: docs
3
- ---
4
-
5
- # Dimension columns
6
-
7
- Dimension columns are available on all data sources. On `metrics`, they are included directly in the table. On `events` and `features`, the required `LEFT JOIN` is added automatically when you reference them — you never write joins yourself.
8
-
9
- ## Available dimensions
10
-
11
- | Source | Columns |
12
- |---|---|
13
- | `dim_variant` | `variant_type`, `ab_feature_name`, `ab_feature_value` |
14
- | `dim_device` | `device_category`, `browser_name`, `browser_version`, `os_name`, `os_version`, `platform` |
15
- | `dim_geo` | `country_code`, `country_name`, `region`, `city` |
16
- | `dim_utm` | `utm_source`, `utm_medium`, `utm_campaign`, `utm_term`, `utm_content` |
17
- | `dim_product` | `product_name`, `product_category`, `product_page` |
18
- | `steps` | `step_title` |
19
- | `experiences` | `experience_title` |
20
- | `projects` | `project_name`, `project_timezone` |
21
-
22
- The `steps`, `experiences`, and `projects` sources are reference tables sourced from the operational database. They are auto-joined onto `events`/`fact_events` when their analyst-facing columns are referenced, **and** they require their own tenant filter when queried directly:
23
-
24
- | Source | Tenant filter required |
25
- |---|---|
26
- | `steps`, `experiences` | `WHERE project_id = '<project_id>'` |
27
- | `projects` | `WHERE id = '<project_id>'` (the row's `id` IS the project id) |
28
-
29
- When auto-joined, these reference tables also receive a tenant equality on the JOIN's `ON` clause (e.g. `AND st.project_id = '<project_id>'`, `AND pr.id = '<project_id>'`) so ClickHouse prunes the dim scan instead of reading the full table. The predicate is added to `ON` rather than `WHERE` to preserve `LEFT JOIN` semantics.
30
-
31
- Analyst-facing column names are prefixed (`step_title`, `project_name`, etc.) to avoid collisions across sources — for example, `steps.title` and `experiences.title` both exist, but you reference them as `step_title` and `experience_title`.
32
-
33
- ```sql
34
- -- Group events by experience and step name (auto-joins both `experiences` and `steps`)
35
- SELECT experience_title, step_title, count(*)
36
- FROM events
37
- WHERE project_id = 'your-project-id'
38
- GROUP BY experience_title, step_title
39
- ```
40
-
41
- Auto-joins also work inside subqueries and CTEs — reference dimension columns wherever you need them and the required `LEFT JOIN` is injected at that level:
42
-
43
- ```sql
44
- -- Dimension columns inside a CTE
45
- WITH per_step AS (
46
- SELECT step_title, count(*) AS n
47
- FROM events
48
- WHERE project_id = 'your-project-id'
49
- GROUP BY step_title
50
- )
51
- SELECT * FROM per_step ORDER BY n DESC
52
-
53
- -- Dimension columns inside a nested SELECT
54
- SELECT step_title, n FROM (
55
- SELECT step_title, count(*) AS n FROM events
56
- WHERE project_id = 'your-project-id'
57
- GROUP BY step_title
58
- ) sub
59
- ```
60
-
61
- ## Native event columns
62
-
63
- These columns are available directly on `events` and require no join:
64
-
65
- `event_type`, `interaction_type`, `experience_id`, `step_id`, `event_id`, `user_canonical_id`, `session_id`, `client_local_date`, `is_purchase`, `is_cart_add`, `event_meta`.
@@ -1,36 +0,0 @@
1
- ---
2
- layout: docs
3
- ---
4
-
5
- # PickedQL
6
-
7
- PickedQL is a SQL query language for querying your Picked analytics data. Write simple SQL using virtual tables and functions — PickedQL expands them into optimized queries with automatic joins and A/B test aggregations.
8
-
9
- ## Quick start
10
-
11
- ```sql
12
- -- How many users are in the control vs variant group?
13
- SELECT control_users(), variant_users()
14
- FROM metrics
15
- WHERE project_id = 'your-project-id'
16
- ```
17
-
18
- PickedQL handles table mapping and dimension joins automatically. You write concise, readable SQL — PickedQL does the rest.
19
-
20
- ## How PickedQL works
21
-
22
- 1. **Virtual table expansion**: Table names like `metrics` map to underlying data tables
23
- 2. **Virtual function expansion**: Shorthand functions like `control_users()` expand to full aggregate expressions
24
- 3. **Auto dimension joins**: References to dimension columns (like `device_category` or `country_code`) trigger automatic `LEFT JOIN` clauses — you never write joins yourself
25
- 4. **Tenant isolation**: Every query must include a tenant filter in the `WHERE` clause — usually `project_id`, but `projects` uses `id` (the row's `id` IS the project id). PickedQL extracts the filter and verifies you have permission to access that project
26
- 5. **SQL passthrough**: Standard SQL (including `CASE WHEN`, window functions, and subqueries) works alongside virtual functions
27
-
28
- ## Best practices
29
-
30
- - **Use `metrics` for dashboards**: Pre-aggregated data is significantly faster than raw events for standard reporting
31
- - **Use `events` for deep dives**: Raw event-level data gives full flexibility for custom breakdowns and funnels
32
- - **Use `experience_journey` for sankey / funnel charts**: One line of SQL returns `source, target, users` — the 8-CTE scaffold (dedup, top-N path ranking, lagInFrame) is handled internally; pass parameters via `WHERE`
33
- - **Don't write JOINs**: PickedQL injects them automatically when you reference dimension columns
34
- - **Group by any dimension**: Add dimension columns to `SELECT` and `GROUP BY` freely — required joins are handled for you
35
- - **Reference table metadata for free**: Use `step_title`, `experience_title`, `project_name` directly in `events` queries — PickedQL auto-joins the `steps`, `experiences`, and `projects` reference tables
36
-
@@ -1,156 +0,0 @@
1
- ---
2
- layout: docs
3
- ---
4
-
5
- # Schema
6
-
7
- Column reference for each PickedQL data source.
8
-
9
- ## `metrics`
10
-
11
- Pre-aggregated daily data. One row per unique combination of dimensions per day.
12
-
13
- | Column | Type | Description |
14
- |---|---|---|
15
- | `project_id` | String | Project identifier (required in `WHERE`) |
16
- | `project_local_date` | Date | Date in project timezone |
17
- | `experience_id` | String | Experience identifier |
18
- | `step_id` | String | Step identifier |
19
- | `event_type` | String | Event type (e.g., `page_view`, `click`) |
20
- | `interaction_type` | String | Interaction type (e.g., `Button Click`) |
21
- | `variant_type` | String | `Control`, `Variant`, or `Unknown` |
22
- | `device_category` | String | Device category (e.g., `Desktop`, `Mobile`) |
23
- | `country_code` | String | ISO country code |
24
- | `utm_source` | String | UTM source |
25
- | `utm_medium` | String | UTM medium |
26
- | `product_name` | String | Product name |
27
- | `product_category` | String | Product category |
28
- | `landing_page_url` | String | Landing page URL |
29
-
30
- :::note
31
- Aggregate columns (`users`, `sessions`, `events`, etc.) are not queried directly — use [virtual functions](./virtual-functions) instead.
32
- :::
33
-
34
- ## `events`
35
-
36
- User-level event data. One row per event per user. Dimension columns are joined automatically when referenced.
37
-
38
- ### Native columns
39
-
40
- | Column | Type | Description |
41
- |---|---|---|
42
- | `project_id` | String | Project identifier (required in `WHERE`) |
43
- | `event_id` | String | Unique event identifier |
44
- | `user_canonical_id` | String | Canonical user identifier |
45
- | `session_id` | String | Session identifier |
46
- | `experience_id` | String | Experience identifier |
47
- | `step_id` | String | Step identifier |
48
- | `event_type` | String | Event type (e.g., `page_view`, `click`) |
49
- | `interaction_type` | String | Interaction type (e.g., `Button Click`) |
50
- | `client_local_date` | Date | Date in client timezone |
51
- | `is_purchase` | UInt8 | `1` if checkout complete event |
52
- | `is_cart_add` | UInt8 | `1` if cart add event |
53
- | `is_first_session` | UInt8 | `1` if first session for this user |
54
- | `landing_page_url` | String | Landing page URL |
55
- | `features` | Map(String, String) | Feature flag assignments |
56
- | `feature_keys` | Map(String, String) | Feature key assignments |
57
- | `event_meta` | String | Event metadata |
58
-
59
- ### Dimension columns (auto-joined)
60
-
61
- These columns are joined automatically when referenced — no `JOIN` syntax needed.
62
-
63
- | Column | Source | Description |
64
- |---|---|---|
65
- | `variant_type` | dim_variant | `Control`, `Variant`, or `Unknown` |
66
- | `ab_feature_name` | dim_variant | A/B feature name |
67
- | `ab_feature_value` | dim_variant | A/B feature value |
68
- | `device_category` | dim_device | Device category |
69
- | `browser_name` | dim_device | Browser name |
70
- | `browser_version` | dim_device | Browser version |
71
- | `os_name` | dim_device | Operating system name |
72
- | `os_version` | dim_device | Operating system version |
73
- | `platform` | dim_device | Platform |
74
- | `country_code` | dim_geo | ISO country code |
75
- | `country_name` | dim_geo | Country name |
76
- | `region` | dim_geo | Region |
77
- | `city` | dim_geo | City |
78
- | `utm_source` | dim_utm | UTM source |
79
- | `utm_medium` | dim_utm | UTM medium |
80
- | `utm_campaign` | dim_utm | UTM campaign |
81
- | `utm_term` | dim_utm | UTM term |
82
- | `utm_content` | dim_utm | UTM content |
83
- | `product_name` | dim_product | Product name |
84
- | `product_category` | dim_product | Product category |
85
- | `product_page` | dim_product | Product page |
86
- | `step_title` | steps | Step title (joined on `project_id` + `experience_id` + `step_id`) |
87
- | `experience_title` | experiences | Experience title (joined on `project_id` + `experience_id`) |
88
- | `project_name` | projects | Project name |
89
- | `project_timezone` | projects | Project timezone |
90
-
91
- ## `steps`, `experiences`, `projects`
92
-
93
- Reference tables describing your Picked configuration. Auto-joined onto `events` when their analyst-facing columns are referenced; require a per-table tenant filter when queried directly.
94
-
95
- | Source | Real Columns | Analyst Columns (when referenced from `events`) | Tenant filter (when queried directly) |
96
- |---|---|---|---|
97
- | `steps` | `id`, `title`, `experience_id`, `project_id`, `organization_id` | `step_title` | `project_id = '…'` |
98
- | `experiences` | `id`, `title`, `project_id`, `organization_id` | `experience_title` | `project_id = '…'` |
99
- | `projects` | `id`, `name`, `timezone`, `organization_id` | `project_name`, `project_timezone` | `id = '<project_id>'` |
100
-
101
- When queried directly, use the real column names:
102
-
103
- ```sql
104
- -- List all experiences for a project
105
- SELECT id, title FROM experiences WHERE project_id = 'your-project-id'
106
- ```
107
-
108
- When referenced from `events`, use the prefixed analyst names — joins are injected automatically:
109
-
110
- ```sql
111
- SELECT experience_title, step_title, count(*)
112
- FROM events
113
- WHERE project_id = 'your-project-id'
114
- GROUP BY experience_title, step_title
115
- ```
116
-
117
- ## `features`
118
-
119
- The `features` table provides [parameterized virtual functions](./virtual-functions#feature-functions-features--events) for querying feature flag assignments:
120
-
121
- | Function | Description |
122
- |---|---|
123
- | `feature_users('name', 'bucket' [, 'key'])` | Unique users in a feature bucket |
124
- | `feature_sessions('name', 'bucket' [, 'key'])` | Unique sessions in a feature bucket |
125
- | `feature_events('name', 'bucket' [, 'key'])` | Unique events in a feature bucket |
126
-
127
- ## `experience_journey`
128
-
129
- Aggregated step-transition edges for sankey / funnel charts. Parameters are supplied via the outer `WHERE` clause (PickedQL extracts them and substitutes into the underlying scaffold).
130
-
131
- ### Columns
132
-
133
- | Column | Type | Description |
134
- |---|---|---|
135
- | `source` | String | Edge start, formatted as `NN. <step title>` (e.g., `001. Welcome screen`) |
136
- | `target` | String | Edge end, formatted as `NN. <step title>`.
137
- | `users` | UInt64 | Distinct `user_canonical_id` count that traversed this edge. |
138
-
139
- ### Parameters (via `WHERE`)
140
-
141
- | Key | Type | Required | Purpose |
142
- |---|---|---|---|
143
- | `project_id` | String | ✓ | Tenant filter. |
144
- | `experience_id` | String | | Restrict to one `fact_events.experience_id`. |
145
- | `starting_step` | String | | Anchor edges at first occurrence of this `step_id`. Defaults to each user's first step. |
146
- | `targeting_step` | String | | Trim each user's window at their first occurrence of this `step_id`. Non-reachers still contribute their pre-cut journey. |
147
- | `num_nodes_after_start` | Integer | | Forward window from start: keep steps where `seq_pos < start_seq + N` (card 4129 semantics). |
148
- | `num_nodes_before_target` | Integer | | Backward window from target: keep steps where `seq_pos >= target_seq - N` (card 2740 semantics). Requires `targeting_step`. |
149
- | `top_n_path` | Integer | | Keep only the top-N most-walked paths by user count. Defaults to no limit. |
150
- | `user_cohort_event` | String | | Restrict to users who have at least one `fact_events` row with this `event_type`. Implemented as `user_canonical_id IN (SELECT DISTINCT user_canonical_id FROM fact_events WHERE event_type = '…')`. |
151
- | `client_local_date` | Date | | Date range filter, pushed into the underlying scan. Supports `=`, `<`, `<=`, `>`, `>=`, `BETWEEN`. |
152
- | `event_timestamp` | DateTime64 | | Server-side timestamp filter. Same operators as `client_local_date`. |
153
-
154
- When both window params are set, both predicates apply (intersection). Date filters combine via `AND` with the other params.
155
-
156
- See [data sources → experience_journey](./data-sources#experience_journey--sankey-ready-step-transitions) for usage examples.
@@ -1,204 +0,0 @@
1
- ---
2
- layout: docs
3
- ---
4
-
5
- # Virtual functions
6
-
7
- Virtual functions are shorthand for aggregate expressions. They are **table-aware** — the same function expands differently on `metrics` (pre-aggregated) vs `events` (user-level).
8
-
9
- ## A/B test metrics
10
-
11
- | Function | Description |
12
- |---|---|
13
- | `control_users([condition])` | Unique users in the Control group, optionally filtered by a custom condition |
14
- | `variant_users([condition])` | Unique users in the Variant group, optionally filtered by a custom condition |
15
- | `all_users()` | All unique users |
16
- | `control_sessions([condition])` | Unique sessions in the Control group, optionally filtered by a custom condition |
17
- | `variant_sessions([condition])` | Unique sessions in the Variant group, optionally filtered by a custom condition |
18
- | `all_sessions()` | All unique sessions |
19
-
20
- ### Custom filters on `events`
21
-
22
- On the `events` table, `control_*`/`variant_*` functions accept **one optional filter argument** to count only users/sessions matching the given expression, in addition to the implicit `variant_type` filter. The argument can be **positional** or **named** (`filter=`).
23
-
24
- The filter uses the same `column=value` syntax as conversion-rate conditions, with `AND`/`OR` operators and parentheses for grouping.
25
-
26
- ```sql
27
- -- Default: all Control users
28
- SELECT control_users() FROM events
29
-
30
- -- Custom filter (positional)
31
- SELECT control_users('event_type=app_initialize') FROM events
32
- SELECT variant_users('event_type=app_initialize AND step_id=xxx') FROM events
33
-
34
- -- AND/OR + parentheses
35
- SELECT control_users('event_type=app_initialize OR event_type=app_load') FROM events
36
- SELECT control_users('event_type=form_submit AND (step_id=lead-capture OR step_id=xxx)') FROM events
37
-
38
- -- Sessions
39
- SELECT control_sessions('event_type=step_enter') FROM events
40
- SELECT variant_sessions('event_type=step_enter AND step_id=checkout') FROM events
41
-
42
- -- Named form
43
- SELECT control_users(filter='event_type=app_initialize AND step_id=xxx') FROM events
44
- ```
45
-
46
- :::note
47
- Custom filters are **not supported on `metrics`** (pre-aggregated data). On `metrics`, these functions ignore any arguments and use the default Control/Variant filter only.
48
- :::
49
-
50
- ## Conversion metrics
51
-
52
- | Function | Description |
53
- |---|---|
54
- | `all_purchase_users()` | Users who completed a purchase |
55
- | `control_purchase_users()` | Control users who purchased (`metrics` only) |
56
- | `variant_purchase_users()` | Variant users who purchased (`metrics` only) |
57
- | `all_purchase_sessions()` | Sessions with a purchase (`metrics` only) |
58
- | `all_purchase_orders()` | Unique order count (`metrics` only) |
59
- | `all_cart_add_users()` | Users who added to cart |
60
-
61
- ## Conversion rates
62
-
63
- | Function | Description |
64
- |---|---|
65
- | `control_conversion_rate([numerator [, denominator]])` | Conversion rate for Control. Defaults to purchase users / all users |
66
- | `variant_conversion_rate([numerator [, denominator]])` | Conversion rate for Variant. Same args as above |
67
- | `conversion_rate_uplift([numerator [, denominator]])` | Relative improvement: `(variant CR - control CR) / control CR`. Same args as above |
68
-
69
- ### Custom conditions on `events`
70
-
71
- On the `events` table, conversion rate functions accept up to **2 optional arguments** to customize the numerator and denominator. Each argument can be either a **condition expression string** or a **nested virtual function call** (see below). Arguments can be **positional** or **named** (`numerator=`, `denominator=`).
72
-
73
- Each condition expression uses `column=value` with `AND`/`OR` operators and parentheses for grouping.
74
-
75
- ```sql
76
- -- Default: purchase users / all users
77
- SELECT control_conversion_rate() FROM events
78
-
79
- -- Custom numerator, default denominator (all users)
80
- SELECT control_conversion_rate('event_type=form_submit_success') FROM events
81
-
82
- -- AND/OR in conditions
83
- SELECT control_conversion_rate('event_type=checkout_complete OR event_type=order_create') FROM events
84
- SELECT control_conversion_rate('step_id=lead-capture AND event_type=form_submit_success') FROM events
85
-
86
- -- Parentheses for grouping
87
- SELECT control_conversion_rate('event_type=form_submit AND (step_id=lead-capture OR step_id=xxx)') FROM events
88
-
89
- -- Custom numerator AND denominator (positional)
90
- SELECT control_conversion_rate('event_type=form_submit', 'step_id=lead-capture') FROM events
91
-
92
- -- Named arguments (explicit, any order)
93
- SELECT control_conversion_rate(numerator='event_type=form_submit', denominator='step_id=lead-capture') FROM events
94
-
95
- -- Named: denominator only (numerator defaults to purchase)
96
- SELECT control_conversion_rate(denominator='step_id=lead-capture') FROM events
97
-
98
- -- Uplift with named args
99
- SELECT conversion_rate_uplift(numerator='event_type=form_submit', denominator='step_id=lead-capture') FROM events
100
- ```
101
-
102
- #### Nested virtual functions as numerator / denominator
103
-
104
- Instead of a condition string, you can pass a **virtual function call** as the numerator or denominator. The inner aggregate is substituted in place — no implicit `variant_type` filter is added on top of it (the nested function controls its own filter).
105
-
106
- This is the most flexible form when the numerator and denominator have different segments (e.g., Control users who fired event X over **all** users regardless of variant):
107
-
108
- ```sql
109
- -- (Control users who fired app_initialize) / (all users)
110
- SELECT control_conversion_rate(
111
- control_users('event_type=app_initialize'),
112
- all_users()
113
- ) FROM events
114
-
115
- -- Mix string and nested forms
116
- SELECT control_conversion_rate(
117
- 'event_type=form_submit',
118
- all_users()
119
- ) FROM events
120
-
121
- -- Uplift with nested args
122
- SELECT conversion_rate_uplift(
123
- control_users('event_type=app_initialize'),
124
- all_users()
125
- ) FROM events
126
- ```
127
-
128
- :::note
129
- Custom conditions and nested virtual function args are **not supported on `metrics`** (pre-aggregated data). On `metrics`, these functions always use the default purchase / all users definition.
130
- :::
131
-
132
- ## Visitor segmentation (`metrics` only)
133
-
134
- | Function | Description |
135
- |---|---|
136
- | `new_users()` | First-time visitors |
137
- | `returning_users()` | Returning visitors |
138
- | `new_sessions()` | Sessions from new visitors |
139
- | `returning_sessions()` | Sessions from returning visitors |
140
-
141
- ## Funnel metrics (`events` only)
142
-
143
- :::note
144
- Funnel metrics are being continuously updated. Check back for new functions.
145
- :::
146
-
147
- | Function | Description |
148
- |---|---|
149
- | `step_enter_users()` | Users who entered a funnel step |
150
- | `step_enter_sessions()` | Sessions that entered a funnel step |
151
-
152
- ## Cohort filters (`events` only)
153
-
154
- Predicate-shaped functions that emit a `user_canonical_id IN (SELECT … FROM events …)` subquery. Use in `WHERE` to restrict any analysis to users who have at least one event matching a custom condition.
155
-
156
- | Function | Description |
157
- |---|---|
158
- | `user_cohort_filter('<condition>')` | Restrict the query to users with ≥1 `events` row matching `<condition>` |
159
- | `user_cohort_filter(filter='<condition>')` | Same, named-arg form |
160
-
161
- `<condition>` uses the same `column=value [AND\|OR …]` shorthand as `control_users` / `variant_users`.
162
-
163
- ```sql
164
- -- Funnel scoped to users who eventually submitted lead capture
165
- SELECT all_users(), all_purchase_users()
166
- FROM events
167
- WHERE project_id = 'proj-abc'
168
- AND user_cohort_filter('event_type=lead_capture')
169
-
170
- -- Multi-condition cohort with OR-grouping
171
- SELECT all_sessions()
172
- FROM events
173
- WHERE project_id = 'proj-abc'
174
- AND user_cohort_filter('event_type=signup OR event_type=trial_start')
175
- ```
176
-
177
- The outer query MUST filter by a single `project_id` — the function bakes that tenant into the inner subquery so the cohort scan is scoped to your project, not the whole warehouse.
178
-
179
- ## Feature functions (`features` / `events`)
180
-
181
- Parameterized functions that accept the feature name, bucket, and an optional feature key:
182
-
183
- | Function | Description |
184
- |---|---|
185
- | `feature_users('name', 'bucket' [, 'key'])` | Unique users in a feature bucket |
186
- | `feature_sessions('name', 'bucket' [, 'key'])` | Unique sessions in a feature bucket |
187
- | `feature_events('name', 'bucket' [, 'key'])` | Unique events in a feature bucket |
188
-
189
- ```sql
190
- -- Compare feature buckets
191
- SELECT
192
- feature_users('homepage_test', 'control') AS control,
193
- feature_users('homepage_test', 'variant') AS variant
194
- FROM features
195
-
196
- -- With feature key filter
197
- SELECT feature_users('homepage_test', 'control', 'v1') FROM features
198
- ```
199
-
200
- ## Other (`metrics` only)
201
-
202
- | Function | Description |
203
- |---|---|
204
- | `event_count()` | Total event count (from pre-aggregation) |
@@ -1,37 +0,0 @@
1
- ---
2
- layout: docs
3
- ---
4
-
5
- import { Screenshot } from '../../components/Screenshot'
6
-
7
- # Projects
8
-
9
- A project represents one website or app you want to instrument with Picked. Each project has its own set of experiences, entities, and configuration.
10
-
11
- <Screenshot
12
- route="/{orgSlug}"
13
- alt="The organization home page on the Picked dashboard, listing the projects in an organization"
14
- />
15
-
16
- ## Create a project
17
-
18
- You need an organization first. If you don't have one, create it when you sign up.
19
-
20
- 1. Open your organization.
21
- 2. Click **New Project**.
22
- 3. Enter a name.
23
- 4. Click **Create**.
24
-
25
- ## Workspaces
26
-
27
- Each project contains one or more [Workspaces](/workspaces) for configuring and previewing experiences before publishing.
28
-
29
- ## Project home
30
-
31
- When you open a project, you land on the project home page. It shows your SDK installation snippet and a getting-started checklist.
32
-
33
- Copy the snippet and add it to your site. This connects your site to the project and enables experience delivery. See [SDK Installation](/sdk) for setup details.
34
-
35
- ## Project navigation
36
-
37
- The sidebar shows all sections available in your project: **Experiences**, **Fields**, **Steps**, **Actions**, **Conditions**, and more. Some sections appear only when enabled for your account.
@@ -1,18 +0,0 @@
1
- ---
2
- layout: docs
3
- ---
4
-
5
- import { Screenshot } from '../../components/Screenshot'
6
-
7
- # Reports
8
-
9
- Reports show analytics data for your project. Track how visitors interact with your experiences and features.
10
-
11
- <Screenshot
12
- route="/{orgSlug}/{projectId}/reports"
13
- alt="The reports list for a project on the Picked dashboard"
14
- />
15
-
16
- ## View report data
17
-
18
- Open a report to see its analytics. Data updates as new visitor interactions are recorded.
@@ -1,66 +0,0 @@
1
- ---
2
- layout: docs
3
- ---
4
-
5
- # Actions
6
-
7
- Register action handlers on the Picked client so the SDK can invoke them when an experience flow reaches an action node.
8
-
9
- ## Registering actions
10
-
11
- Register actions when creating the Picked client. Each key in the `actions` object must match an action key defined in the dashboard:
12
-
13
- ```ts
14
- import { createClient } from '@picked/client'
15
-
16
- const picked = createClient({
17
- projectId: 'your-project-id',
18
- actions: {
19
- 'track-signup': () => {
20
- analytics.track('signup_completed')
21
- },
22
- 'notify': (params) => {
23
- sendNotification(params)
24
- },
25
- },
26
- })
27
- ```
28
-
29
- Each action is a function that receives optional parameters and usually runs a side effect. When the flow reaches an action node, the SDK calls the matching function and branches on whether it succeeds or throws (see [Success and failure branching](#success-and-failure-branching)).
30
-
31
- ## How actions work
32
-
33
- 1. **Registration**: Actions are registered to the Picked client during initialization
34
- 2. **Flow traversal**: When the SDK traverses the experience flow and reaches an action node, it looks up the action by its key
35
- 3. **Execution**: The matching function is called and awaited. The SDK then continues to the next node based on the action's outcome
36
- 4. **Non-blocking**: Actions don't interrupt the visitor's experience. The current step stays on screen while an async action runs
37
-
38
- ## Success and failure branching
39
-
40
- An action node can have separate **success** and **failure** branches. The SDK selects the branch from the action's outcome:
41
-
42
- - **Failure** — the action throws (or its promise rejects). The flow follows the failure (`onFail`) branch.
43
- - **Success** — the action resolves to any value (`void`, `true`, `false`, or a string). A resolved `false` is a valid response, not a failure. The flow follows the success (`onSuccess`) branch.
44
-
45
- Reserve the failure branch for genuine errors — throw on the failure case, since a returned value never routes to `onFail`:
46
-
47
- ```ts
48
- 'check-eligibility': async () => {
49
- const response = await fetch('/api/eligibility')
50
- // Throw only when the request itself fails — that takes the failure branch.
51
- if (!response.ok) throw new Error('Eligibility request failed')
52
- }
53
- ```
54
-
55
- A valid negative result is not a failure. An API that returns `200` with a "no" (for example `{ serviced: false }`) should record that value as a response and branch on it with a condition, rather than throw:
56
-
57
- ```ts
58
- 'check-serviced-area': async ({ client, responses }) => {
59
- const postcode = responses.find((r) => r.fieldKey === 'postcode')?.value
60
- const { serviced } = await fetch(`/api/serviced?postcode=${postcode}`).then((r) => r.json())
61
- // Commit the outcome as a response; a downstream condition routes the flow.
62
- client.responses.register('is-serviced', serviced)
63
- }
64
- ```
65
-
66
- If an action node has only a single plain connection (no explicit success or failure branch), the flow continues through it on either outcome.
@@ -1,32 +0,0 @@
1
- ---
2
- layout: docs
3
- ---
4
-
5
- # Content Security Policy
6
-
7
- The Picked SDK loads resources from the following domains. Add each to the matching CSP directive.
8
-
9
- ## Required domains
10
-
11
- | Domain | Directive | Purpose |
12
- | --- | --- | --- |
13
- | `api.picked.app` | `connect-src` | API requests, project configuration, experiences, session tracking |
14
- | `evnts.pckd.dev` | `connect-src` | Analytics event collection (Snowplow) |
15
- | `img.picked-content.com` | `img-src` | Optimised images served via the [image optimisation service](../image-optimisation-service.md) |
16
-
17
- ## Configuration
18
-
19
- As an HTTP header:
20
-
21
- ```
22
- Content-Security-Policy: connect-src 'self' https://api.picked.app https://evnts.pckd.dev; img-src 'self' https://img.picked-content.com;
23
- ```
24
-
25
- Or as a `<meta>` tag:
26
-
27
- ```html
28
- <meta
29
- http-equiv="Content-Security-Policy"
30
- content="connect-src 'self' https://api.picked.app https://evnts.pckd.dev; img-src 'self' https://img.picked-content.com;"
31
- />
32
- ```
@@ -1,46 +0,0 @@
1
- ---
2
- layout: docs
3
- ---
4
-
5
- # Experiences
6
-
7
- Define experiences in code with `createExperience()`, or load them from the dashboard at runtime with the [Dynamic Experiences Plugin](./plugins/dynamic-experiences).
8
-
9
- The execution flow below targets a DOM selector and renders into it. A Page experience instead renders through a named slot: target it to `.picked-slot-<name>` and render `<ExperienceSlot name="<name>" />` on your server. Use the slot path for SEO-critical, server-rendered Pages; use the selector path for browser-rendered Flows. See [Server-Side Rendering](/sdk/ssr) and [Slots & Placements](/sdk/ssr/slots-and-placements).
10
-
11
- ## Creating experiences
12
-
13
- ```ts
14
- import { createExperience } from '@picked/client/plugins/create-experience'
15
- import { adaptSvelteComponent } from '@picked/svelte'
16
- import appCss from '../app.css?inline'
17
-
18
- export const productPageExperience = createExperience({
19
- id: 'product-page-experience',
20
- name: 'Product Page Experience',
21
- condition: {
22
- '==': [
23
- { var: 'location.pathname' },
24
- '/product/',
25
- ],
26
- },
27
- targets: [{ selector: 'body', placement: 'after' }],
28
- component: adaptSvelteComponent(
29
- import('../ui/ProductPageExperience.svelte'),
30
- { css: [appCss] },
31
- ),
32
- })
33
- ```
34
-
35
- Register experiences using the [Create Experience Plugin](./plugins/create-experience) for code-defined experiences, or the [Dynamic Experiences Plugin](./plugins/dynamic-experiences) to fetch and manage them from the dashboard at runtime.
36
-
37
- ## How experiences work
38
-
39
- When an experience is registered, the SDK follows this execution flow:
40
-
41
- 1. **Registration**: Experiences are registered to the Picked client using [createExperiencePlugin](./plugins/create-experience) for code-defined experiences, or [dynamicExperiencesPlugin](./plugins/dynamic-experiences) for dashboard-managed experiences
42
- 2. **Condition evaluation**: The SDK evaluates the experience's `condition` using the logic engine to determine if it should be shown
43
- 3. **Target resolution**: The SDK searches the DOM for elements matching the `targets` selectors (e.g., `body`, `.product-page`, `#checkout`)
44
- 4. **Initialization**: If the condition evaluates to `true` and at least one target element exists, the experience is initialized
45
- 5. **Component rendering**: The experience's component is rendered and injected into the DOM at the specified target location and placement (before, after, append, prepend, or replace)
46
- 6. **Flow execution**: If the experience contains steps, fields, and conditionals, users can progress through the multi-step flow with validation and branching logic