@picked/client 0.0.70-next.6 → 0.0.71-next.1

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 (177) hide show
  1. package/dist/.tsbuildinfo +1 -0
  2. package/dist/api-CH2FNa6S.cjs +1 -0
  3. package/dist/api-CgqRvuKL.js +38 -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/actions.mdx +38 -18
  10. package/dist/docs/api/authentication.md +75 -48
  11. package/dist/docs/api/authorization-and-scopes.md +63 -47
  12. package/dist/docs/api/error-handling.md +70 -54
  13. package/dist/docs/api/index.md +41 -22
  14. package/dist/docs/api/pagination.md +30 -20
  15. package/dist/docs/api-keys.mdx +11 -6
  16. package/dist/docs/chrome-extension.md +22 -5
  17. package/dist/docs/conditions.mdx +32 -19
  18. package/dist/docs/content/asset-library.mdx +65 -34
  19. package/dist/docs/content/content-entries.mdx +8 -2
  20. package/dist/docs/content/layouts.mdx +45 -29
  21. package/dist/docs/content/pages.mdx +29 -14
  22. package/dist/docs/content/sections.mdx +19 -8
  23. package/dist/docs/delivery-api/experience-content.md +10 -5
  24. package/dist/docs/delivery-api/index.md +19 -12
  25. package/dist/docs/delivery-api/preview-caching-crawling.md +27 -14
  26. package/dist/docs/delivery-api/project-config.md +6 -4
  27. package/dist/docs/experiences.mdx +26 -10
  28. package/dist/docs/features.mdx +66 -25
  29. package/dist/docs/fields.mdx +42 -27
  30. package/dist/docs/flow-builder/building-flows.md +38 -20
  31. package/dist/docs/flow-builder/condition-builder.md +32 -21
  32. package/dist/docs/flow-builder/keyboard-shortcuts.md +18 -18
  33. package/dist/docs/flow-builder/nodes.md +26 -13
  34. package/dist/docs/flow-builder/overview.mdx +28 -15
  35. package/dist/docs/gtm-template.md +35 -26
  36. package/dist/docs/guides/build-a-personalized-page.mdx +36 -18
  37. package/dist/docs/image-optimisation-service.md +33 -17
  38. package/dist/docs/index.md +28 -17
  39. package/dist/docs/mcp.md +46 -38
  40. package/dist/docs/pickedql/data-sources.md +65 -43
  41. package/dist/docs/pickedql/dimensions.md +27 -12
  42. package/dist/docs/pickedql/examples.md +38 -26
  43. package/dist/docs/pickedql/filtering.md +10 -6
  44. package/dist/docs/pickedql/index.md +32 -14
  45. package/dist/docs/pickedql/schema.md +85 -76
  46. package/dist/docs/pickedql/virtual-functions.md +62 -36
  47. package/dist/docs/projects.mdx +14 -7
  48. package/dist/docs/reports.mdx +5 -3
  49. package/dist/docs/sdk/actions.md +33 -17
  50. package/dist/docs/sdk/conditions.md +8 -5
  51. package/dist/docs/sdk/content-security-policy.md +5 -4
  52. package/dist/docs/sdk/experiences.md +29 -11
  53. package/dist/docs/sdk/feature-allocation.md +79 -47
  54. package/dist/docs/sdk/features.md +130 -76
  55. package/dist/docs/sdk/fields.md +66 -42
  56. package/dist/docs/sdk/index.md +22 -13
  57. package/dist/docs/sdk/plugins/create-experience.md +18 -15
  58. package/dist/docs/sdk/plugins/dynamic-experiences.md +42 -16
  59. package/dist/docs/sdk/predicates.md +53 -37
  60. package/dist/docs/sdk/ssr/index.md +25 -8
  61. package/dist/docs/sdk/ssr/rendering-and-hydration.md +37 -16
  62. package/dist/docs/sdk/ssr/serialize.md +38 -20
  63. package/dist/docs/sdk/ssr/slots-and-placements.md +28 -10
  64. package/dist/docs/sdk/steps.md +100 -55
  65. package/dist/docs/steps.mdx +20 -11
  66. package/dist/docs/team-management.md +17 -11
  67. package/dist/docs/vite-plugin.md +26 -19
  68. package/dist/docs/workspace-versioning.mdx +14 -8
  69. package/dist/docs/workspaces.mdx +55 -24
  70. package/dist/{dom-BwmTHeT7.js → dom-BqcToNL0.js} +1 -3
  71. package/dist/{dom-CDrHc_j9.cjs → dom-DlLH3FxV.cjs} +1 -1
  72. package/dist/esm/form/index.js +2 -4
  73. package/dist/esm/index.js +50 -45
  74. package/dist/esm/plugins/dom-observer/index.js +1 -1
  75. package/dist/esm/plugins/dynamic-experiences/index.js +2 -2
  76. package/dist/esm/preview/index.js +1 -1
  77. package/dist/esm/server/index.js +12 -10
  78. package/dist/{experience-instance-DOJShRk5.js → experience-instance-DGk11d8a.js} +3 -3
  79. package/dist/experience-instance-Dej3P1sE.cjs +1 -0
  80. package/dist/{plugin-BxMR7fOV.js → plugin-D2UqFikQ.js} +2 -2
  81. package/dist/plugin-DCW-tnjO.cjs +1 -0
  82. package/dist/{preview-channel-DW9J8t4B.js → preview-channel-CSr96XAo.js} +1 -1
  83. package/dist/{protocol-DSqOlW2r.js → protocol-C5KkkiZc.js} +1 -1
  84. package/dist/types/client.d.ts +7 -6
  85. package/dist/types/entities/action/action.d.ts +5 -4
  86. package/dist/types/entities/action/action.d.ts.map +1 -1
  87. package/dist/types/entities/component/component.d.ts +6 -5
  88. package/dist/types/entities/component/component.d.ts.map +1 -1
  89. package/dist/types/entities/condition/condition.d.ts +5 -5
  90. package/dist/types/entities/content/content.d.ts +4 -3
  91. package/dist/types/entities/experience/experience.d.ts +11 -10
  92. package/dist/types/entities/experience/experience.d.ts.map +1 -1
  93. package/dist/types/entities/experience-instance/experience-instance.d.ts +10 -9
  94. package/dist/types/entities/feature/feature.d.ts +3 -2
  95. package/dist/types/entities/feature/feature.d.ts.map +1 -1
  96. package/dist/types/entities/field/field.d.ts +7 -6
  97. package/dist/types/entities/framework/framework.d.ts +7 -6
  98. package/dist/types/entities/framework/framework.d.ts.map +1 -1
  99. package/dist/types/entities/history/history.d.ts +6 -6
  100. package/dist/types/entities/plugin/plugin.d.ts +3 -2
  101. package/dist/types/entities/plugin/plugin.d.ts.map +1 -1
  102. package/dist/types/entities/predicate/predicate.d.ts +4 -3
  103. package/dist/types/entities/predicate/predicate.d.ts.map +1 -1
  104. package/dist/types/entities/response/response-validation.d.ts +3 -2
  105. package/dist/types/entities/response/response.d.ts +12 -11
  106. package/dist/types/entities/session/session.d.ts +2 -1
  107. package/dist/types/entities/step/step.d.ts +6 -5
  108. package/dist/types/exports.d.ts +2 -1
  109. package/dist/types/exports.d.ts.map +1 -1
  110. package/dist/types/form/build-responses.d.ts +2 -1
  111. package/dist/types/form/create-field-evaluator.d.ts +4 -3
  112. package/dist/types/form/create-field-validation.d.ts +5 -4
  113. package/dist/types/form/create-form.d.ts +7 -6
  114. package/dist/types/form/create-submit-pipeline.d.ts +7 -6
  115. package/dist/types/form/get-step-fields.d.ts +3 -2
  116. package/dist/types/lifecycle/condition-selection.d.ts +14 -4
  117. package/dist/types/lifecycle/lifecycle.d.ts +4 -3
  118. package/dist/types/lifecycle/rules-logic.d.ts +4 -3
  119. package/dist/types/lifecycle/state-snapshot.d.ts +4 -3
  120. package/dist/types/picked.d.ts +64 -62
  121. package/dist/types/picked.d.ts.map +1 -1
  122. package/dist/types/ping.d.ts +1 -1
  123. package/dist/types/ping.d.ts.map +1 -1
  124. package/dist/types/plugins/create-experience/create-experience.d.ts +9 -8
  125. package/dist/types/plugins/create-experience/create-experience.d.ts.map +1 -1
  126. package/dist/types/plugins/create-experience/plugin.d.ts +3 -2
  127. package/dist/types/plugins/create-experience/plugin.d.ts.map +1 -1
  128. package/dist/types/plugins/create-experience/serialization.d.ts.map +1 -1
  129. package/dist/types/plugins/dom-observer/plugin.d.ts +1 -1
  130. package/dist/types/plugins/dynamic-experiences/plugin.d.ts +3 -3
  131. package/dist/types/plugins/dynamic-experiences/types.d.ts +8 -5
  132. package/dist/types/plugins/experience-browser-storage/plugin.d.ts +1 -1
  133. package/dist/types/plugins/experience-browser-storage/plugin.d.ts.map +1 -1
  134. package/dist/types/plugins/history-browser-storage/plugin.d.ts +1 -1
  135. package/dist/types/plugins/history-browser-storage/plugin.d.ts.map +1 -1
  136. package/dist/types/plugins/responses-browser-storage/plugin.d.ts +1 -1
  137. package/dist/types/plugins/responses-browser-storage/plugin.d.ts.map +1 -1
  138. package/dist/types/plugins/responses-indexeddb/plugin.d.ts +1 -1
  139. package/dist/types/plugins/single-page-app/plugin.d.ts +1 -1
  140. package/dist/types/plugins/single-page-app/plugin.d.ts.map +1 -1
  141. package/dist/types/plugins/web-components/plugin.d.ts +2 -1
  142. package/dist/types/plugins/window-object/plugin.d.ts +2 -2
  143. package/dist/types/preview-channel.d.ts +5 -1
  144. package/dist/types/preview-receiver/index.d.ts +18 -1
  145. package/dist/types/preview-receiver/protocol.d.ts +10 -1
  146. package/dist/types/server/index.d.ts +3 -3
  147. package/dist/types/server/serialize.d.ts +2 -2
  148. package/dist/types/utils/dom.d.ts +2 -1
  149. package/dist/types/utils/events.d.ts +6 -6
  150. package/dist/types/utils/events.d.ts.map +1 -1
  151. package/dist/types/utils/global-obj.d.ts +1 -1
  152. package/dist/types/utils/global-obj.d.ts.map +1 -1
  153. package/dist/types/utils/id.d.ts.map +1 -1
  154. package/dist/types/utils/logger.d.ts +2 -1
  155. package/dist/types/utils/logger.d.ts.map +1 -1
  156. package/dist/types/utils/node-tree/get-next-node-from-action.d.ts +2 -1
  157. package/dist/types/utils/node-tree/get-next-node-from-condition.d.ts +2 -1
  158. package/dist/types/utils/node-tree/get-next-node.d.ts +1 -1
  159. package/dist/types/utils/node-tree/get-next-node.d.ts.map +1 -1
  160. package/dist/types/utils/node-tree/get-origin-node.d.ts +1 -1
  161. package/dist/types/utils/node-tree/get-origin-node.d.ts.map +1 -1
  162. package/dist/types/utils/node-tree/min-max-steps-to-leaf.d.ts +1 -1
  163. package/dist/types/utils/node-tree/min-max-steps-to-leaf.d.ts.map +1 -1
  164. package/dist/types/utils/node-tree/min-max-steps-to-origin.d.ts +1 -1
  165. package/dist/types/utils/node-tree/min-max-steps-to-origin.d.ts.map +1 -1
  166. package/dist/types/utils/node-tree/next-reachable-step-nodes.d.ts +1 -1
  167. package/dist/types/utils/node-tree/next-reachable-step-nodes.d.ts.map +1 -1
  168. package/dist/types/utils/nodes.d.ts +1 -1
  169. package/dist/types/utils/picked-config.d.ts +2 -1
  170. package/dist/types/utils/rules-logic.d.ts +6 -2
  171. package/dist/types/utils/storage.d.ts +1 -1
  172. package/dist/types/utils/storage.d.ts.map +1 -1
  173. package/package.json +22 -23
  174. package/dist/api-CoUkIxIr.cjs +0 -1
  175. package/dist/api-ahdSBQ3Y.js +0 -40
  176. package/dist/experience-instance-DurC3pE-.cjs +0 -1
  177. package/dist/plugin-CASdGtTX.cjs +0 -1
@@ -4,33 +4,51 @@ layout: docs
4
4
 
5
5
  # PickedQL
6
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.
7
+ PickedQL is a SQL query language for your Picked analytics data. Write short SQL with
8
+ a virtual table and a virtual function. PickedQL expands them into a full query, and
9
+ it adds the joins and the A/B test aggregations for you.
8
10
 
9
11
  ## Quick start
10
12
 
11
13
  ```sql
12
- -- How many users are in the control vs variant group?
14
+ -- How many users are in the control group, and how many in the variant group?
13
15
  SELECT control_users(), variant_users()
14
16
  FROM metrics
15
17
  WHERE project_id = 'your-project-id'
16
18
  ```
17
19
 
18
- PickedQL handles table mapping and dimension joins automatically. You write concise, readable SQL — PickedQL does the rest.
20
+ PickedQL maps each table and adds each dimension join for you. You write short SQL
21
+ that a person can read, and PickedQL does the rest.
19
22
 
20
23
  ## How PickedQL works
21
24
 
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
25
+ 1. **Virtual table expansion**: a table name such as `metrics` maps to the data
26
+ tables below it.
27
+ 2. **Virtual function expansion**: a short function such as `control_users()` expands
28
+ to a full aggregate expression.
29
+ 3. **Automatic dimension joins**: PickedQL adds a `LEFT JOIN` when you point at a
30
+ dimension column, such as `device_category` or `country_code`. You write no join.
31
+ 4. **Tenant isolation**: every query must hold a tenant filter in the `WHERE` clause.
32
+ That filter is `project_id` for most tables. The `projects` table uses `id`
33
+ instead, because the `id` of the row is the project ID. PickedQL reads the filter
34
+ and checks that you have permission for that project.
35
+ 5. **SQL passthrough**: standard SQL works next to a virtual function. This includes
36
+ `CASE WHEN`, a window function, and a subquery.
27
37
 
28
38
  ## Best practices
29
39
 
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
40
+ - **Use `metrics` for a dashboard**: data that PickedQL aggregates first is much
41
+ faster than raw events for a standard report.
42
+ - **Use `events` to go deeper**: raw event data lets you build any breakdown or
43
+ funnel that you want.
44
+ - **Use `experience_journey` for a sankey chart or a funnel chart**: one line of SQL
45
+ returns `source, target, users`. PickedQL builds the eight common table expressions
46
+ for you. Those remove the duplicates, rank the top paths, and call `lagInFrame`.
47
+ Pass your parameters in the `WHERE` clause.
48
+ - **Write no JOIN**: PickedQL adds each one when you point at a dimension column.
49
+ - **Group by any dimension**: add a dimension column to `SELECT` and to `GROUP BY`.
50
+ PickedQL adds the join that it needs.
51
+ - **Read the reference tables for no cost**: use `step_title`, `experience_title`, and
52
+ `project_name` directly in an `events` query. PickedQL joins the `steps`,
53
+ `experiences`, and `projects` reference tables for you.
36
54
 
@@ -12,23 +12,23 @@ Pre-aggregated daily data. One row per unique combination of dimensions per day.
12
12
 
13
13
  | Column | Type | Description |
14
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 |
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 (for example `page_view`, `click`) |
20
+ | `interaction_type` | `String` | Interaction type (for example `Button Click`) |
21
+ | `variant_type` | `String` | `Control`, `Variant`, or `Unknown` |
22
+ | `device_category` | `String` | Device category (for example `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
29
 
30
30
  :::note
31
- Aggregate columns (`users`, `sessions`, `events`, etc.) are not queried directly — use [virtual functions](./virtual-functions) instead.
31
+ Aggregate columns (`users`, `sessions`, `events`, and so on) are not queried directly — use [virtual functions](./virtual-functions) instead.
32
32
  :::
33
33
 
34
34
  ## `events`
@@ -39,22 +39,22 @@ User-level event data. One row per event per user. Dimension columns are joined
39
39
 
40
40
  | Column | Type | Description |
41
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 |
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 (for example `page_view`, `click`) |
49
+ | `interaction_type` | `String` | Interaction type (for example `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
55
  | `features` | Map(String, String) | Feature flag assignments |
56
56
  | `feature_keys` | Map(String, String) | Feature key assignments |
57
- | `event_meta` | String | Event metadata |
57
+ | `event_meta` | `String` | Event metadata |
58
58
 
59
59
  ### Dimension columns (auto-joined)
60
60
 
@@ -62,37 +62,39 @@ These columns are joined automatically when referenced — no `JOIN` syntax need
62
62
 
63
63
  | Column | Source | Description |
64
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 |
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` | The name of the operating system |
72
+ | `os_version` | `dim_device` | The version of the operating system |
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
90
 
91
91
  ## `steps`, `experiences`, `projects`
92
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.
93
+ These reference tables hold the options of your Picked project. PickedQL joins them
94
+ onto `events` when you point at one of their analyst-facing columns. Each one needs
95
+ its own tenant filter when you read it directly.
94
96
 
95
- | Source | Real Columns | Analyst Columns (when referenced from `events`) | Tenant filter (when queried directly) |
97
+ | Source | Real columns | Analyst columns, when you point at them from `events` | Tenant filter, when you read the table directly |
96
98
  |---|---|---|---|
97
99
  | `steps` | `id`, `title`, `experience_id`, `project_id`, `organization_id` | `step_title` | `project_id = '…'` |
98
100
  | `experiences` | `id`, `title`, `project_id`, `organization_id` | `experience_title` | `project_id = '…'` |
@@ -116,7 +118,9 @@ GROUP BY experience_title, step_title
116
118
 
117
119
  ## `features`
118
120
 
119
- The `features` table provides [parameterized virtual functions](./virtual-functions#feature-functions-features--events) for querying feature flag assignments:
121
+ The `features` table gives you
122
+ [parameterized virtual functions](./virtual-functions#feature-functions-on-features-and-on-events).
123
+ Use them to read which visitors each feature flag holds:
120
124
 
121
125
  | Function | Description |
122
126
  |---|---|
@@ -126,31 +130,36 @@ The `features` table provides [parameterized virtual functions](./virtual-functi
126
130
 
127
131
  ## `experience_journey`
128
132
 
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).
133
+ This table gives one edge for each step transition, and PickedQL aggregates them
134
+ first. Use the edges in a sankey chart or a funnel chart. Give each parameter in the
135
+ outer `WHERE` clause. PickedQL reads them and puts them into the query below.
130
136
 
131
137
  ### Columns
132
138
 
133
139
  | Column | Type | Description |
134
140
  |---|---|---|
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. |
141
+ | `source` | `String` | Edge start, formatted as `NN. <step title>` (for example `001. Welcome screen`) |
142
+ | `target` | `String` | Edge end, formatted as `NN. <step title>`.
143
+ | `users` | `UInt64` | Distinct `user_canonical_id` count that traversed this edge. |
138
144
 
139
- ### Parameters (via `WHERE`)
145
+ ### Parameters, in the `WHERE` clause
140
146
 
141
147
  | Key | Type | Required | Purpose |
142
148
  |---|---|---|---|
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.
149
+ | `project_id` | `String` | ✓ | The tenant filter. |
150
+ | `experience_id` | `String` | | Limits the rows to one `fact_events.experience_id`. |
151
+ | `starting_step` | `String` | | Anchors each edge at the first time that a user reaches this `step_id`. The default is the first step of each user. |
152
+ | `targeting_step` | `String` | | Trims the window of each user at the first time that the user reaches this `step_id`. A user who never reaches it still gives the journey up to that point. |
153
+ | `num_nodes_after_start` | Integer | | The forward window from the start. It keeps a step where `seq_pos < start_seq + N`. This is what card 4129 does. |
154
+ | `num_nodes_before_target` | Integer | | The backward window from the target. It keeps a step where `seq_pos >= target_seq - N`. This is what card 2740 does. It needs `targeting_step`. |
155
+ | `top_n_path` | Integer | | Keeps the paths that the most users take, and drops the rest. The default is no limit. |
156
+ | `user_cohort_event` | `String` | | Limits the rows to a user with at least one `fact_events` row of this `event_type`. PickedQL writes it as `user_canonical_id IN (SELECT DISTINCT user_canonical_id FROM fact_events WHERE event_type = '…')`. |
157
+ | `client_local_date` | `Date` | | A filter on a range of dates. PickedQL puts it into the read below. It takes `=`, `<`, `<=`, `>`, `>=`, and `BETWEEN`. |
158
+ | `event_timestamp` | `DateTime64` | | A filter on the timestamp from the server. It takes the same operators as `client_local_date`. |
159
+
160
+ When you set both window parameters, both tests apply, and the result is their
161
+ intersection. A date filter joins the other parameters with `AND`.
162
+
163
+ See
164
+ [data sources, `experience_journey`](./data-sources#experience_journey--step-transitions-for-a-sankey-chart)
165
+ for examples.
@@ -4,34 +4,41 @@ layout: docs
4
4
 
5
5
  # Virtual functions
6
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).
7
+ A virtual function is a short form of an aggregate expression. Each one is
8
+ **table-aware**. The same function expands one way on `metrics`, where PickedQL
9
+ aggregates the data first. It expands another way on `events`, where there is one row
10
+ for each user.
8
11
 
9
12
  ## A/B test metrics
10
13
 
11
14
  | Function | Description |
12
15
  |---|---|
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 |
16
+ | `control_users([condition])` | The different users in the Control group. A condition of your own can narrow them. |
17
+ | `variant_users([condition])` | The different users in the Variant group. A condition of your own can narrow them. |
18
+ | `all_users()` | Every different user |
19
+ | `control_sessions([condition])` | The different sessions in the Control group. A condition of your own can narrow them. |
20
+ | `variant_sessions([condition])` | The different sessions in the Variant group. A condition of your own can narrow them. |
21
+ | `all_sessions()` | Every different session |
19
22
 
20
- ### Custom filters on `events`
23
+ ### Your own filters on `events`
21
24
 
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=`).
25
+ On the `events` table, each `control_*` function and each `variant_*` function takes
26
+ **one optional filter argument**. The filter counts only a user or a session that
27
+ matches your expression. It applies together with the `variant_type` filter that
28
+ PickedQL adds. Give the argument in the first place, or by the name `filter=`.
23
29
 
24
- The filter uses the same `column=value` syntax as conversion-rate conditions, with `AND`/`OR` operators and parentheses for grouping.
30
+ The filter uses the same `column=value` syntax as a conversion-rate condition. It
31
+ takes the `AND` and `OR` operators, and parentheses can hold a set of terms.
25
32
 
26
33
  ```sql
27
- -- Default: all Control users
34
+ -- The default: every Control user.
28
35
  SELECT control_users() FROM events
29
36
 
30
- -- Custom filter (positional)
37
+ -- Your own filter, in the first place.
31
38
  SELECT control_users('event_type=app_initialize') FROM events
32
39
  SELECT variant_users('event_type=app_initialize AND step_id=xxx') FROM events
33
40
 
34
- -- AND/OR + parentheses
41
+ -- The AND and OR operators, with parentheses.
35
42
  SELECT control_users('event_type=app_initialize OR event_type=app_load') FROM events
36
43
  SELECT control_users('event_type=form_submit AND (step_id=lead-capture OR step_id=xxx)') FROM events
37
44
 
@@ -44,7 +51,9 @@ SELECT control_users(filter='event_type=app_initialize AND step_id=xxx') FROM ev
44
51
  ```
45
52
 
46
53
  :::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.
54
+ A filter of your own is **not supported on `metrics`**, because PickedQL aggregates
55
+ that data first. On `metrics` these functions ignore every argument. They use the
56
+ default Control filter and Variant filter only.
48
57
  :::
49
58
 
50
59
  ## Conversion metrics
@@ -62,15 +71,19 @@ Custom filters are **not supported on `metrics`** (pre-aggregated data). On `met
62
71
 
63
72
  | Function | Description |
64
73
  |---|---|
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 |
74
+ | `control_conversion_rate([numerator [, denominator]])` | The conversion rate of the Control group. By default it divides the users with a purchase by all users. |
75
+ | `variant_conversion_rate([numerator [, denominator]])` | The conversion rate of the Variant group. It takes the same arguments. |
76
+ | `conversion_rate_uplift([numerator [, denominator]])` | The gain of the Variant over the Control: `(variant CR - control CR) / control CR`. It takes the same arguments. |
68
77
 
69
- ### Custom conditions on `events`
78
+ ### Your own conditions on `events`
70
79
 
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=`).
80
+ On the `events` table, each conversion-rate function takes up to **two optional
81
+ arguments**. They set the numerator and the denominator. Each argument is either a
82
+ **condition expression string** or a **nested virtual function call**. See below.
83
+ Give the arguments in order, or by the names `numerator=` and `denominator=`.
72
84
 
73
- Each condition expression uses `column=value` with `AND`/`OR` operators and parentheses for grouping.
85
+ Each condition expression uses `column=value`, with the `AND` and `OR` operators.
86
+ Parentheses can hold a set of terms.
74
87
 
75
88
  ```sql
76
89
  -- Default: purchase users / all users
@@ -79,11 +92,11 @@ SELECT control_conversion_rate() FROM events
79
92
  -- Custom numerator, default denominator (all users)
80
93
  SELECT control_conversion_rate('event_type=form_submit_success') FROM events
81
94
 
82
- -- AND/OR in conditions
95
+ -- The AND and OR operators in a condition.
83
96
  SELECT control_conversion_rate('event_type=checkout_complete OR event_type=order_create') FROM events
84
97
  SELECT control_conversion_rate('step_id=lead-capture AND event_type=form_submit_success') FROM events
85
98
 
86
- -- Parentheses for grouping
99
+ -- Parentheses hold a set of terms.
87
100
  SELECT control_conversion_rate('event_type=form_submit AND (step_id=lead-capture OR step_id=xxx)') FROM events
88
101
 
89
102
  -- Custom numerator AND denominator (positional)
@@ -95,18 +108,23 @@ SELECT control_conversion_rate(numerator='event_type=form_submit', denominator='
95
108
  -- Named: denominator only (numerator defaults to purchase)
96
109
  SELECT control_conversion_rate(denominator='step_id=lead-capture') FROM events
97
110
 
98
- -- Uplift with named args
111
+ -- The uplift, with the arguments given by name.
99
112
  SELECT conversion_rate_uplift(numerator='event_type=form_submit', denominator='step_id=lead-capture') FROM events
100
113
  ```
101
114
 
102
- #### Nested virtual functions as numerator / denominator
115
+ #### A nested virtual function as the numerator or the denominator
103
116
 
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).
117
+ You can pass a **virtual function call** as the numerator or the denominator, in
118
+ place of a condition string. PickedQL puts the inner aggregate there directly. It
119
+ adds no `variant_type` filter above it, because the nested function sets its own
120
+ filter.
105
121
 
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):
122
+ This form is the most flexible one when the numerator and the denominator come from
123
+ different segments. An example is the Control users who fired one event, over **all**
124
+ users of every variant:
107
125
 
108
126
  ```sql
109
- -- (Control users who fired app_initialize) / (all users)
127
+ -- The Control users who fired `app_initialize`, over all users.
110
128
  SELECT control_conversion_rate(
111
129
  control_users('event_type=app_initialize'),
112
130
  all_users()
@@ -118,7 +136,7 @@ SELECT control_conversion_rate(
118
136
  all_users()
119
137
  ) FROM events
120
138
 
121
- -- Uplift with nested args
139
+ -- The uplift, with a nested function in each place.
122
140
  SELECT conversion_rate_uplift(
123
141
  control_users('event_type=app_initialize'),
124
142
  all_users()
@@ -126,7 +144,9 @@ SELECT conversion_rate_uplift(
126
144
  ```
127
145
 
128
146
  :::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.
147
+ A condition of your own, and a nested virtual function, are both **not supported on
148
+ `metrics`**, because PickedQL aggregates that data first. On `metrics` these
149
+ functions always divide the users with a purchase by all users.
130
150
  :::
131
151
 
132
152
  ## Visitor segmentation (`metrics` only)
@@ -141,7 +161,7 @@ Custom conditions and nested virtual function args are **not supported on `metri
141
161
  ## Funnel metrics (`events` only)
142
162
 
143
163
  :::note
144
- Funnel metrics are being continuously updated. Check back for new functions.
164
+ We add to the funnel metrics all the time. Read this page again for a new function.
145
165
  :::
146
166
 
147
167
  | Function | Description |
@@ -151,14 +171,18 @@ Funnel metrics are being continuously updated. Check back for new functions.
151
171
 
152
172
  ## Cohort filters (`events` only)
153
173
 
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.
174
+ Each of these functions has the shape of a predicate. It writes a
175
+ `user_canonical_id IN (SELECT … FROM events …)` subquery. Put one in a `WHERE` clause
176
+ to limit any analysis to a user with at least one event that matches a condition of
177
+ your own.
155
178
 
156
179
  | Function | Description |
157
180
  |---|---|
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 |
181
+ | `user_cohort_filter('<condition>')` | Limits the query to a user with one or more `events` rows that match `<condition>` |
182
+ | `user_cohort_filter(filter='<condition>')` | The same, with the argument given by name |
160
183
 
161
- `<condition>` uses the same `column=value [AND\|OR …]` shorthand as `control_users` / `variant_users`.
184
+ `<condition>` uses the same short `column=value [AND\|OR …]` form as `control_users`
185
+ and `variant_users`.
162
186
 
163
187
  ```sql
164
188
  -- Funnel scoped to users who eventually submitted lead capture
@@ -174,9 +198,11 @@ WHERE project_id = 'proj-abc'
174
198
  AND user_cohort_filter('event_type=signup OR event_type=trial_start')
175
199
  ```
176
200
 
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.
201
+ The outer query MUST hold one `project_id` filter. The function puts that tenant into
202
+ the inner subquery. The read of the cohort therefore covers your project, and not the
203
+ whole warehouse.
178
204
 
179
- ## Feature functions (`features` / `events`)
205
+ ## Feature functions, on `features` and on `events`
180
206
 
181
207
  Parameterized functions that accept the feature name, bucket, and an optional feature key:
182
208
 
@@ -6,16 +6,17 @@ import { Screenshot } from '../../components/Screenshot'
6
6
 
7
7
  # Projects
8
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.
9
+ A project is one site or one application that you want to measure with Picked. Each
10
+ project has its own experiences, entities, and options.
10
11
 
11
12
  <Screenshot
12
13
  route="/{orgSlug}"
13
- alt="The organization home page on the Picked dashboard, listing the projects in an organization"
14
+ alt="The organization home page on the Picked dashboard, with the projects in an organization"
14
15
  />
15
16
 
16
17
  ## Create a project
17
18
 
18
- You need an organization first. If you don't have one, create it when you sign up.
19
+ You need an organization first. If you do not have one, create it when you sign up.
19
20
 
20
21
  1. Open your organization.
21
22
  2. Click **New Project**.
@@ -24,14 +25,20 @@ You need an organization first. If you don't have one, create it when you sign u
24
25
 
25
26
  ## Workspaces
26
27
 
27
- Each project contains one or more [Workspaces](/workspaces) for configuring and previewing experiences before publishing.
28
+ Each project holds one or more [Workspaces](/workspaces). In a workspace you set the
29
+ options for an experience and you see a preview of it before you make it live.
28
30
 
29
31
  ## Project home
30
32
 
31
- When you open a project, you land on the project home page. It shows your SDK installation snippet and a getting-started checklist.
33
+ When you open a project, you land on the project home page. It shows your SDK
34
+ snippet and a list of the setup tasks that are still open.
32
35
 
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.
36
+ Copy the snippet and add it to your site. The snippet connects your site to the
37
+ project and lets Picked serve experiences to it. See
38
+ [SDK Installation](/sdk) for the setup detail.
34
39
 
35
40
  ## Project navigation
36
41
 
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.
42
+ The sidebar shows every section of your project: **Experiences**, **Fields**,
43
+ **Steps**, **Actions**, **Conditions**, and more. Some sections appear only when your
44
+ account has them.
@@ -6,13 +6,15 @@ import { Screenshot } from '../../components/Screenshot'
6
6
 
7
7
  # Reports
8
8
 
9
- Reports show analytics data for your project. Track how visitors interact with your experiences and feature flags.
9
+ A report shows analytics data for your project. Use a report to track how your
10
+ visitors use your experiences and feature flags.
10
11
 
11
12
  <Screenshot
12
13
  route="/{orgSlug}/{projectId}/reports"
13
14
  alt="The reports list for a project on the Picked dashboard"
14
15
  />
15
16
 
16
- ## View report data
17
+ ## See report data
17
18
 
18
- Open a report to see its analytics. Data updates as new visitor interactions are recorded.
19
+ Open a report to see its analytics. The data updates when Picked records a new
20
+ visitor interaction.