@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,43 +0,0 @@
1
- ---
2
- layout: docs
3
- ---
4
-
5
- # Nodes
6
-
7
- Nodes are the building blocks of a flow. Each node represents a block in your experience. There are four node types.
8
-
9
- ## Origin
10
-
11
- Every flow starts with an origin node. It's a gray circle on the left side of the canvas. It has one output handle on its right side.
12
-
13
- You can't move, delete, or duplicate the origin. It's always present.
14
-
15
- ## Step
16
-
17
- A step node represents a screen shown to visitors. It appears as a blue rectangle on the canvas.
18
-
19
- Steps hold fields. Drag a field from the entity browser onto a step node to assign it. The node subtitle shows how many fields are assigned.
20
-
21
- Each step has a `layoutName` that tells the SDK which visual layout to use when rendering this step. Configure the layout name in the inspector.
22
-
23
- ## Action
24
-
25
- An action node represents a side effect — something that happens behind the scenes. It appears as a green rectangle.
26
-
27
- Actions trigger when the flow reaches them. Use actions for tasks like tracking events, sending data, or triggering integrations.
28
-
29
- ## Condition
30
-
31
- A condition node represents a branching point. It appears as an amber rectangle.
32
-
33
- Condition nodes have two output handles instead of one. The green handle (top-right) connects to the path taken when the condition is true. The red handle (bottom-right) connects to the path taken when it's false.
34
-
35
- Define the condition logic in the inspector using the visual condition builder. See [Conditions](/conditions) for details.
36
-
37
- ## Handles
38
-
39
- Handles are the connection points on nodes. Input handles sit on the left. Output handles sit on the right. Drag from an output handle to an input handle to connect two nodes.
40
-
41
- ---
42
-
43
- [Overview](/flow-builder/overview) · **Nodes** · [Building Flows](/flow-builder/building-flows) · [Keyboard Shortcuts](/flow-builder/keyboard-shortcuts) · [Condition Builder](/flow-builder/condition-builder)
@@ -1,50 +0,0 @@
1
- ---
2
- layout: docs
3
- ---
4
-
5
- import { Screenshot } from '../../../components/Screenshot'
6
-
7
- # Flow builder
8
-
9
- The flow builder is a visual editor for designing experience flows. You drag blocks onto a canvas, connect them with arrows, and configure each node in an inspector panel.
10
-
11
- <Screenshot
12
- route="/{orgSlug}/{projectId}/workspaces/{workspaceId}/experiences/{experienceId}"
13
- alt="The flow builder with the entity browser, canvas, and inspector panels"
14
- />
15
-
16
- ## Layout
17
-
18
- The flow builder has three panels arranged left to right.
19
-
20
- **Entity browser** (left): Lists all steps, actions, conditions, and fields in your project. Drag items from here onto the canvas.
21
-
22
- **Canvas** (center): The workspace where you build your flow. Nodes represent blocks. Arrows represent connections between them.
23
-
24
- **Inspector** (right): Shows configuration for the selected node. When nothing is selected, it shows experience-level settings.
25
-
26
- ## Panel controls
27
-
28
- Drag the dividers between panels to resize them. Press `Cmd/Ctrl+\` to toggle both side panels. Press `Cmd/Ctrl+Shift+\` to toggle just the inspector.
29
-
30
- ## Navigating the canvas
31
-
32
- **Zoom**: Scroll to zoom in and out.
33
-
34
- **Pan**: Select the hand tool (press `H`) and drag. Or hold `Space` while dragging. Middle-click drag also pans.
35
-
36
- **Select tool**: Press `V` to switch back to the select tool. This is the default — click to select nodes, drag on empty space to marquee-select.
37
-
38
- ## Auto-layout
39
-
40
- Click the auto-layout button in the toolbar to automatically arrange all nodes in a clean hierarchy. Useful after adding many nodes or when the canvas gets messy.
41
-
42
- ## Saving
43
-
44
- Click **Save** in the toolbar to save your flow. The button is enabled when you have unsaved changes.
45
-
46
- The flow builder also auto-saves after a period of inactivity. A dot indicator appears on the save button when there are unsaved changes.
47
-
48
- ---
49
-
50
- **Flow Builder** · [Nodes](/flow-builder/nodes) · [Building Flows](/flow-builder/building-flows) · [Keyboard Shortcuts](/flow-builder/keyboard-shortcuts) · [Condition Builder](/flow-builder/condition-builder)
@@ -1,69 +0,0 @@
1
- ---
2
- layout: docs
3
- ---
4
-
5
- # Google Tag Manager template
6
-
7
- The Picked Ecommerce GTM Tag Template lets you track ecommerce events and send them to Picked directly from Google Tag Manager.
8
-
9
- ## Automatic installation
10
-
11
- Install the template from the GTM Community Gallery:
12
-
13
- 1. In Tag Manager, click **Templates**.
14
- 2. In the **Tag Templates** section, click **Search Gallery**.
15
- 3. Search for `Picked Ecommerce`.
16
- 4. Click the Picked Ecommerce template to view details.
17
- 5. Click **Add to workspace**.
18
- 6. Review the required permissions and click **Add**.
19
-
20
- ![Picked Ecommerce template in the GTM Community Gallery](/gtm/picked-ecommerce-gtm.png)
21
-
22
- ## Manual installation
23
-
24
- If you prefer to import the template file directly:
25
-
26
- 1. Download the [template file](https://github.com/picked-app/gtm-template/blob/main/template.tpl) from GitHub (use the download icon).
27
- 2. In Google Tag Manager, go to **Templates**.
28
- 3. Click **New**.
29
- 4. Open the three-dot menu and click **Import**.
30
- 5. Select the downloaded template file.
31
- 6. Click **Save**.
32
-
33
- ## Setup
34
-
35
- ### 1. Create a Tag ID variable
36
-
37
- Sign in to the [Picked Dashboard](https://dashboard.picked.app) and copy your project Tag ID. Save it as a constant variable in GTM (e.g. `Picked Tag ID`).
38
-
39
- ![Creating a Picked Tag ID variable in GTM](/gtm/gtm-variable.png)
40
-
41
- ### 2. Create an ecommerce data variable
42
-
43
- Create a **Data Layer Variable** with the variable name set to `ecommerce`. This captures the GA4 Enhanced Ecommerce data layer.
44
-
45
- ![GA4 Enhanced Ecommerce data layer variable](/gtm/gtm-ecommerce-variable.png)
46
-
47
- ### 3. Create event triggers
48
-
49
- Add a trigger for each ecommerce event you want to track (e.g. `add_to_cart`, `purchase`, `view_item`).
50
-
51
- ![Event triggers for ecommerce tracking](/gtm/gtm-triggers.png)
52
-
53
- ### 4. Create tags
54
-
55
- Create a new tag for each event, selecting the **Picked Ecommerce** tag template. Assign the matching trigger and configure the options below.
56
-
57
- ![Tags using the Picked Ecommerce template](/gtm/gtm-tags.png)
58
-
59
- ## Configuration options
60
-
61
- | Option | Description |
62
- | --- | --- |
63
- | **Tag ID** | Your Picked project Tag ID. Find it in the [Picked Dashboard](https://dashboard.picked.app). |
64
- | **Event** | The ecommerce event to track (e.g. `add_to_cart`, `purchase`). |
65
- | **Send ecommerce data** | Enable this to send GA4 Enhanced Ecommerce data to Picked. Should be enabled for all ecommerce events. |
66
- | **GA4 Enhanced Ecommerce Data** | The GTM variable containing GA4 ecommerce data. Use the data layer variable created in step 2. |
67
- | **Additional data** | Optional GTM variable for sending extra metadata with the event. |
68
-
69
- ![Picked Ecommerce tag configuration](/gtm/gtm-tag.png)
@@ -1,143 +0,0 @@
1
- ---
2
- layout: docs
3
- ---
4
-
5
- import { Screenshot } from '../../../components/Screenshot'
6
-
7
- # Build a Personalized Page
8
-
9
- Build a personalized landing page with Picked: model it in the dashboard, publish it, and render it server-side in your app.
10
-
11
- ## What you will build
12
-
13
- A standalone, SEO-critical landing page whose content lives in Picked's CMS and renders on your server. You model the page's shape once, fill it with content, publish it, then fetch and render it in React or Svelte. The lifecycle from authoring to a hydrated page:
14
-
15
- ```
16
- Author (dashboard) -> Publish -> Delivery API (config + content)
17
- -> serialize() on server -> Provider seeds client -> ExperienceSlot renders -> hydrate
18
- ```
19
-
20
- ## Model a page layout
21
-
22
- A [Page Layout](/content/layouts) defines the fields your page can hold.
23
-
24
- 1. Open your workspace and click **Models** in the sidebar.
25
- 2. Click **New Model** and choose **Page Layout**.
26
- 3. Enter a name and a **Key**, for example `page-hero`. The Key is a unique, stable identifier you use in SDK code and API references.
27
- 4. Add a few fields: a **Single-line text** field `title`, a **Markdown** field `body`, and an **Asset** field `image`.
28
- 5. Save the layout.
29
-
30
- <Screenshot
31
- route="/{orgSlug}/{projectId}/workspaces/{workspaceId}/models"
32
- alt="A page layout in the schema builder on the Picked dashboard"
33
- />
34
-
35
- See [Page & Step Layouts](/content/layouts) for every field type.
36
-
37
- ## Create and fill the page
38
-
39
- 1. Click **Experiences** in the sidebar, then **New Experience**.
40
- 2. Choose the **Page** type and pick your `page-hero` layout.
41
- 3. On the **Properties** tab, fill in `title`, `body`, and `image`. A [Content Entry](/content/content-entries) is created and linked on first save.
42
- 4. Fix any per-field validation errors.
43
- 5. Publish the workspace to make the page live.
44
-
45
- See [Pages](/content/pages) for the full editor reference.
46
-
47
- ## Fetch the config and content
48
-
49
- Your server fetches two things from the [Delivery API](/delivery-api): the project config (which experiences and steps exist) and the content for the matching experience.
50
-
51
- ```bash
52
- # 1. Project config: find the steps and their content links
53
- curl https://api.picked.app/api/v1/projects/proj_123
54
-
55
- # 2. Experience content: the entry data backing the page
56
- curl https://api.picked.app/api/v1/projects/proj_123/experiences/exp_123/content
57
- ```
58
-
59
- In practice you fetch the config, then let `serialize()` fetch the content for you. See [Project Config](/delivery-api/project-config) and [Experience Content](/delivery-api/experience-content).
60
-
61
- ## Render server-side and hydrate
62
-
63
- On the server, create a per-request client, call `serialize()` to produce a snapshot, render your app, and embed the snapshot. On the client, seed from the snapshot and hydrate.
64
-
65
- ```ts
66
- // server.ts
67
- import { createClient } from '@picked/client'
68
- import { serialize } from '@picked/client/server'
69
-
70
- const client = createClient(options)
71
- const snapshot = await serialize(client, {
72
- projectConfig,
73
- attributes: { location: { pathname: url.pathname } },
74
- })
75
- // Render your app, then embed `snapshot` in the HTML response.
76
- ```
77
-
78
- Render `<ExperienceSlot name="page" />` inside the provider, and register the component the Page maps to (here, `CMSPage`):
79
-
80
- :::code-group
81
-
82
- ```tsx [React]
83
- import type { CreateClientOptions } from '@picked/client'
84
- import { dynamicExperiencesPlugin } from '@picked/client/plugins/dynamic-experiences'
85
- import { adaptReactComponent, ExperienceSlot, PickedProvider } from '@picked/react'
86
- import { reactFrameworkPlugin } from '@picked/react/plugins/framework'
87
- import { useStepContent } from '@picked/react/hooks'
88
-
89
- function CMSPage() {
90
- const content = useStepContent()
91
- const title = typeof content?.title === 'string' ? content.title : ''
92
- return <h1>{title}</h1>
93
- }
94
-
95
- const options = {
96
- projectId: 'proj_123',
97
- components: { CMSPage: adaptReactComponent(CMSPage) },
98
- plugins: [reactFrameworkPlugin({ components: {} }), dynamicExperiencesPlugin()],
99
- } satisfies CreateClientOptions
100
-
101
- export function Page({ snapshot }) {
102
- return (
103
- <PickedProvider options={options} snapshot={snapshot}>
104
- <ExperienceSlot name="page" />
105
- </PickedProvider>
106
- )
107
- }
108
- ```
109
-
110
- ```svelte [Svelte]
111
- <script lang="ts">
112
- import type { CreateClientOptions } from '@picked/client'
113
- import { dynamicExperiencesPlugin } from '@picked/client/plugins/dynamic-experiences'
114
- import { adaptSvelteComponent, ExperienceSlot, setPickedContext } from '@picked/svelte'
115
- import { svelteFrameworkPlugin } from '@picked/svelte/plugins/framework'
116
- import CMSPage from './CMSPage.svelte'
117
-
118
- const { snapshot } = $props()
119
-
120
- const options = {
121
- projectId: 'proj_123',
122
- components: { CMSPage: adaptSvelteComponent(CMSPage) },
123
- plugins: [svelteFrameworkPlugin({ components: {} }), dynamicExperiencesPlugin()],
124
- } satisfies CreateClientOptions
125
-
126
- setPickedContext({ options, snapshot })
127
- </script>
128
-
129
- <ExperienceSlot name="page" />
130
- ```
131
-
132
- :::
133
-
134
- The provider seeds synchronously, so the server HTML and the client's first paint match, then the SDK hydrates. See [Server-Side Rendering](/sdk/ssr) for the full reference.
135
-
136
- ## Verify SEO
137
-
138
- Confirm the page is crawlable end to end:
139
-
140
- 1. View the server response (for example with `curl` or your browser's view-source) and check the rendered HTML contains your `title` and `body`, not an empty shell.
141
- 2. Confirm the content endpoint is reachable anonymously and returns your entry data.
142
-
143
- Published Delivery API responses are crawlable; preview URLs are disallowed. See [Preview, Caching & Crawling](/delivery-api/preview-caching-crawling).
@@ -1,80 +0,0 @@
1
- ---
2
- layout: docs
3
- ---
4
-
5
- # Image optimisation service
6
-
7
- The Picked image optimisation service is a hosted endpoint at `https://img.picked-content.com`. It fetches images from allowed source domains, resizes them, re-encodes to modern formats (WebP or AVIF), and caches the result.
8
-
9
- ## Endpoint
10
-
11
- ```
12
- GET https://img.picked-content.com/_next/image?url={source}&w={width}&q={quality}
13
- ```
14
-
15
- | Parameter | Description |
16
- |-----------|-------------|
17
- | `url` | URL-encoded URL of the source image. Must point to an allowed source domain (see below). |
18
- | `w` | Target width in pixels. Must match one of the supported widths. |
19
- | `q` | Target quality (`25`, `50`, `75`, or `100`). |
20
-
21
- The service performs content negotiation: if the requesting browser advertises `image/avif` or `image/webp` in its `Accept` header, the response uses that format. Otherwise the response uses the source format.
22
-
23
- ## Allowed source domains
24
-
25
- The service only fetches from these hostnames:
26
-
27
- - `**.picked.app`
28
-
29
- A request whose `url` parameter resolves to any other hostname returns `400 Bad Request`.
30
-
31
- ## Supported widths
32
-
33
- Device sizes, for responsive images that span the viewport width:
34
-
35
- ```
36
- 640, 750, 828, 1080, 1200, 1920, 2048, 3840
37
- ```
38
-
39
- Image sizes, for fixed-size UI elements such as icons, avatars, and thumbnails:
40
-
41
- ```
42
- 16, 32, 48, 64, 96, 128, 256, 384
43
- ```
44
-
45
- Requests with any other width return `400 Bad Request`. Pick the smallest width that covers your target rendering size at the user's device pixel ratio.
46
-
47
- ## Supported qualities
48
-
49
- ```
50
- 25, 50, 75, 100
51
- ```
52
-
53
- Lower values reduce bandwidth significantly. `75` is a good default for most images; use `25` or `50` for thumbnails on slow networks.
54
-
55
- ## Responsive images
56
-
57
- Combine the endpoint with the standard `srcset` attribute to let browsers pick the right width per viewport:
58
-
59
- ```html
60
- <img
61
- src="https://img.picked-content.com/_next/image?url=https%3A%2F%2Fcdn.picked.app%2Fhero.png&w=1080&q=75"
62
- srcset="
63
- https://img.picked-content.com/_next/image?url=https%3A%2F%2Fcdn.picked.app%2Fhero.png&w=640&q=75 640w,
64
- https://img.picked-content.com/_next/image?url=https%3A%2F%2Fcdn.picked.app%2Fhero.png&w=1080&q=75 1080w,
65
- https://img.picked-content.com/_next/image?url=https%3A%2F%2Fcdn.picked.app%2Fhero.png&w=1920&q=75 1920w
66
- "
67
- sizes="(max-width: 768px) 100vw, 720px"
68
- alt="..."
69
- />
70
- ```
71
-
72
- ## Caching
73
-
74
- Optimised responses are cached by the upstream CDN. The minimum cache TTL is 60 seconds; the actual lifetime depends on the CDN's eviction policy. If you change the source image at the same URL, expect the optimised variant to remain cached for at least that interval.
75
-
76
- ## Security
77
-
78
- - SVG sources are not optimised. Requests for SVG return the original bytes if the source is allowed; the service never executes embedded scripts.
79
- - Optimised responses carry a strict `Content-Security-Policy` (`default-src *; script-src 'none'; sandbox;`) so even a compromised source cannot run scripts in a viewing browser.
80
- - The response uses `Content-Disposition: inline`, never `attachment`.
package/dist/docs/mcp.md DELETED
@@ -1,120 +0,0 @@
1
- ---
2
- layout: docs
3
- ---
4
-
5
- # MCP server
6
-
7
- Manage your Picked workspace from AI coding tools using the Model Context Protocol (MCP).
8
-
9
- ## Connecting
10
-
11
- The server URL is `https://api.picked.app/mcp`.
12
-
13
- ### Claude Desktop
14
-
15
- 1. Open **Settings > Connectors > Add custom connector**
16
- 2. Set **Name** to `Picked` and **URL** to `https://api.picked.app/mcp`
17
- 3. Click **Connect** and complete the authorization prompt
18
-
19
- ### Project configuration (.mcp.json)
20
-
21
- Add to your repository root. Works with Claude Code, Cursor, Windsurf, and other MCP-compatible tools.
22
-
23
- :::code-group
24
-
25
- ```json [.mcp.json]
26
- {
27
- "mcpServers": {
28
- "picked": {
29
- "type": "http",
30
- "url": "https://api.picked.app/mcp"
31
- }
32
- }
33
- }
34
- ```
35
-
36
- :::
37
-
38
- ### Cursor
39
-
40
- Add to `.cursor/mcp.json` in your project root:
41
-
42
- ```json
43
- {
44
- "mcpServers": {
45
- "picked": {
46
- "type": "http",
47
- "url": "https://api.picked.app/mcp"
48
- }
49
- }
50
- }
51
- ```
52
-
53
- ## Available tools
54
-
55
- ### Discovery
56
-
57
- | Tool | Description |
58
- | ------------------------ | ------------------------------------------------------------ |
59
- | `list_projects` | List organizations and projects |
60
- | `get_workspace_overview` | Full workspace state |
61
- | `get_schema_info` | Documentation for Picked concepts and data model |
62
- | `get_picked_docs` | Fetch the complete Picked documentation (LLM-optimized text) |
63
-
64
- ### Experiences
65
-
66
- | Tool | Description |
67
- | ------------------------ | ----------------------------------------------------------------------------------------- |
68
- | `create_experience` | Create an experience |
69
- | `get_experience` | Get experience details including flow graph |
70
- | `list_experiences` | List experiences |
71
- | `update_experience_flow` | Atomically create, update, or delete steps, conditions, actions, fields, nodes, and edges |
72
-
73
- ### Steps, fields, conditions, and actions
74
-
75
- | Tool | Description |
76
- | ----------------------------------- | --------------- |
77
- | `get_step` / `list_steps` | Read steps |
78
- | `get_field` / `list_fields` | Read fields |
79
- | `get_condition` / `list_conditions` | Read conditions |
80
- | `get_action` / `list_actions` | Read actions |
81
-
82
- ### Features
83
-
84
- | Tool | Description |
85
- | ---------------- | -------------------------------------------------- |
86
- | `create_feature` | Create a feature |
87
- | `get_feature` | Get feature details |
88
- | `list_features` | List features |
89
- | `update_feature` | Update name, description, enabled state, or weight |
90
-
91
- ### Analytics
92
-
93
- | Tool | Description |
94
- | ---------------- | ---------------------------------------------------------------- |
95
- | `query_pickedql` | Execute a PickedQL analytics query and return results as a table |
96
-
97
- Use `get_schema_info` with topic `pickedql` to see available tables, virtual functions, and dimension columns before writing queries.
98
-
99
- ### Publishing
100
-
101
- | Tool | Description |
102
- | ------------------- | ---------------------------------------------- |
103
- | `get_preview_url` | Generate a preview URL for unpublished changes |
104
- | `publish_workspace` | Publish the workspace |
105
-
106
- ## Example prompts
107
-
108
- - "List my Picked projects and show me what's configured"
109
- - "Create a feature flag called 'new-checkout' enabled at 50% traffic"
110
- - "Create an experience with a step that collects email addresses"
111
- - "Show me control vs variant users by device for the last 30 days"
112
- - "Generate a preview URL for my workspace on https://example.com"
113
-
114
- ## Tips
115
-
116
- - Ask your agent to list your projects first, then explore your workspace to see what's configured.
117
- - When building complex experiences, ask your agent about flow graphs and JSON Logic — it can look up the documentation for you.
118
- - Experience flow updates are atomic — your agent can create steps, fields, nodes, and edges in a single operation.
119
- - Preview your changes on your site before publishing to verify everything looks right.
120
- - Ask your agent to query analytics data with PickedQL — it can look up the schema, write the SQL, and explain the results.
@@ -1,145 +0,0 @@
1
- ---
2
- layout: docs
3
- ---
4
-
5
- # Data sources
6
-
7
- PickedQL provides four virtual tables (each optimized for different query patterns) plus three reference tables describing your Picked configuration.
8
-
9
- ## `metrics` — Pre-aggregated daily data
10
-
11
- Best for dashboards and trend analysis. One row per unique combination of dimensions per day. Dimension columns (like `device_category`, `country_code`, `utm_source`) are available directly — no joins needed.
12
-
13
- ```sql
14
- SELECT device_category, control_users(), variant_users()
15
- FROM metrics
16
- WHERE project_id = 'your-project-id'
17
- GROUP BY device_category
18
- ```
19
-
20
- ## `events` — User-level event data
21
-
22
- Best for deep analysis, funnels, and custom breakdowns. One row per event per user. Dimension columns (like `device_category` or `country_code`) are joined automatically when referenced.
23
-
24
- ```sql
25
- SELECT user_canonical_id, device_category
26
- FROM events
27
- WHERE project_id = 'your-project-id'
28
- AND variant_type = 'Control'
29
- ```
30
-
31
- ## `features` — Feature flag analysis
32
-
33
- Best for querying user, session, and event counts per feature flag and bucket. Uses parameterized functions.
34
-
35
- ```sql
36
- SELECT feature_users('homepage_test', 'control')
37
- FROM features
38
- WHERE project_id = 'your-project-id'
39
- ```
40
-
41
- ## `experience_journey` — Sankey-ready step transitions
42
-
43
- Returns per-edge `source, target, users` rows ready to feed a sankey or funnel chart. Wraps the 8-CTE step-transition scaffold (lagInFrame, consecutive-step dedup, top-N path ranking) that cards used to carry inline.
44
-
45
- All filters pass through the **outer `WHERE`** — PickedQL extracts them as parameters and substitutes them into the underlying scaffold. Only `project_id` is required; the rest are optional and default sensibly.
46
-
47
- | Param (WHERE key) | Purpose |
48
- |---|---|
49
- | `project_id` | Required tenant filter. |
50
- | `experience_id` | Restrict to one `fact_events.experience_id`. |
51
- | `starting_step` | Anchor edges at each user's first occurrence of this `step_id`. Absent → anchor at user's first step_enter event. |
52
- | `targeting_step` | Trim each user's window at their first occurrence of this `step_id`. Users who never reach it still contribute their journey up to `num_nodes_after_start`. |
53
- | `num_nodes_after_start` | Forward window size from the starting step (card 4129 semantics). |
54
- | `num_nodes_before_target` | Backward window size from the targeting step (card 2740 semantics). Requires `targeting_step`. |
55
- | `top_n_path` | Keep only the top-N distinct paths by user count. |
56
- | `user_cohort_event` | Restrict to users who have at least one `fact_events` row with this `event_type` (e.g., `'lead_capture'`). Useful for "paths taken by users who eventually converted". |
57
- | `client_local_date` | Date filter. Supports `=`, `<`, `<=`, `>`, `>=`, `BETWEEN`; pushed into the underlying `fact_events` scan. |
58
- | `event_timestamp` | Server-side timestamp filter. Same operators as `client_local_date`. |
59
-
60
- When `num_nodes_after_start` and `num_nodes_before_target` are both set, both predicates apply (intersection).
61
-
62
- ```sql
63
- -- "Overall user journey" sankey (card 4129 pattern) — forward window, target optional
64
- SELECT source, target, users FROM experience_journey
65
- WHERE project_id = 'your-project-id'
66
- AND starting_step = 'step-start'
67
- AND targeting_step = 'step-target'
68
- AND num_nodes_after_start = 10
69
- AND client_local_date >= '2026-04-01' -- optional date range
70
- AND client_local_date <= '2026-04-30'
71
- ```
72
-
73
- ```sql
74
- -- "Paths leading to target" sankey (card 2740 pattern) — backward window + top-N ranking
75
- SELECT source, target, users FROM experience_journey
76
- WHERE project_id = 'your-project-id'
77
- AND experience_id = 'exp-123'
78
- AND starting_step = 'step-start'
79
- AND targeting_step = 'step-target'
80
- AND num_nodes_before_target = 5
81
- AND top_n_path = 10
82
- ```
83
-
84
- ```sql
85
- -- "Drop-off" sankey (card 2744 pattern) — omit targeting_step
86
- SELECT source, target, users FROM experience_journey
87
- WHERE project_id = 'your-project-id'
88
- AND experience_id = 'exp-123'
89
- AND starting_step = 'step-start'
90
- AND num_nodes_after_start = 10
91
- ```
92
-
93
- ```sql
94
- -- Cohort sankey: only users who eventually converted (card 3961 pattern)
95
- SELECT source, target, users FROM experience_journey
96
- WHERE project_id = 'your-project-id'
97
- AND starting_step = 'step-start'
98
- AND targeting_step = 'step-target'
99
- AND num_nodes_after_start = 10
100
- AND user_cohort_event = 'lead_capture' -- restrict to users with ≥1 lead_capture event
101
- ```
102
-
103
- Columns returned:
104
-
105
- | Column | Type | Description |
106
- |---|---|---|
107
- | `source` | String | Edge start, formatted as `NN. <step title>` (e.g., `001. Welcome screen`). PickedQL joins `steps` to resolve the title. |
108
- | `target` | String | Edge end, formatted as `NN. <step title>`. |
109
- | `users` | UInt64 | Distinct `user_canonical_id` count that traversed this edge. |
110
-
111
- :::note
112
- `experience_journey` is aggregated output. Dimension filters (`variant_type`, `device_category`, `country_code`, …) are **not** supported — if you need those, query [`events`](#events--user-level-event-data) directly and build the transitions yourself.
113
- :::
114
-
115
- ## Reference tables — `steps`, `experiences`, `projects`
116
-
117
- Reference tables describing your Picked configuration. They serve two roles:
118
-
119
- - **Auto-joined onto `events`** when their prefixed analyst columns (`step_title`, `experience_title`, `project_name`, `project_timezone`) are referenced.
120
- - **Queryable directly**, with a per-table tenant filter required so you only see rows belonging to a project you have access to.
121
-
122
- | Source | Tenant filter required |
123
- |---|---|
124
- | `steps` | `WHERE project_id = '<project_id>'` |
125
- | `experiences` | `WHERE project_id = '<project_id>'` |
126
- | `projects` | `WHERE id = '<project_id>'` |
127
-
128
- ```sql
129
- -- Direct query: list experiences for a project
130
- SELECT id, title FROM experiences WHERE project_id = 'your-project-id'
131
-
132
- -- Direct query: load metadata for one project
133
- SELECT id, name, timezone FROM projects WHERE id = 'your-project-id'
134
- ```
135
-
136
- ```sql
137
- -- Referenced from events: PickedQL auto-injects the LEFT JOINs
138
- -- (no separate tenant filter on the reference tables — the join is scoped via fact_events)
139
- SELECT experience_title, step_title, count(*)
140
- FROM events
141
- WHERE project_id = 'your-project-id'
142
- GROUP BY experience_title, step_title
143
- ```
144
-
145
- See [Schema → reference tables](./schema#steps-experiences-projects) for the full column list and join keys.