@picked/client 0.0.1-dev.1776647766999 → 0.0.1-dev.1776837084253

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 (87) hide show
  1. package/dist/{api-i5hIjZ7M.js → api-6oxKA__k.js} +1 -1
  2. package/dist/{api-tt6bWMJv.cjs → api-CIC-Uysx.cjs} +1 -1
  3. package/dist/cjs/form/index.js +1 -1
  4. package/dist/cjs/index.js +2 -2
  5. package/dist/cjs/plugins/create-experience/index.js +1 -1
  6. package/dist/cjs/plugins/dynamic-experiences/index.js +1 -1
  7. package/dist/cjs/plugins/experience-browser-storage/index.js +1 -1
  8. package/dist/cjs/plugins/single-page-app/index.js +1 -1
  9. package/dist/cjs/plugins/web-components/index.js +1 -1
  10. package/dist/cjs/plugins/window-object/index.js +1 -1
  11. package/dist/cjs/server/index.js +1 -1
  12. package/dist/docs/actions.md +58 -0
  13. package/dist/docs/api/index.md +32 -0
  14. package/dist/docs/api-keys.md +33 -0
  15. package/dist/docs/conditions.md +52 -0
  16. package/dist/docs/experiences.md +33 -0
  17. package/dist/docs/features.md +51 -0
  18. package/dist/docs/fields.md +70 -0
  19. package/dist/docs/flow-builder/building-flows.md +61 -0
  20. package/dist/docs/flow-builder/condition-builder.md +54 -0
  21. package/dist/docs/flow-builder/keyboard-shortcuts.md +66 -0
  22. package/dist/docs/flow-builder/nodes.md +43 -0
  23. package/dist/docs/flow-builder/overview.md +43 -0
  24. package/dist/docs/index.md +79 -0
  25. package/dist/docs/pickedql/data-sources.md +98 -0
  26. package/dist/docs/pickedql/dimensions.md +23 -0
  27. package/dist/docs/pickedql/examples.md +249 -0
  28. package/dist/docs/pickedql/filtering.md +31 -0
  29. package/dist/docs/pickedql/index.md +35 -0
  30. package/dist/docs/pickedql/schema.md +123 -0
  31. package/dist/docs/pickedql/virtual-functions.md +121 -0
  32. package/dist/docs/projects.md +30 -0
  33. package/dist/docs/reference/index.md +11 -0
  34. package/dist/docs/reports.md +11 -0
  35. package/dist/docs/sdk/actions.md +37 -0
  36. package/dist/docs/sdk/conditions.md +137 -0
  37. package/dist/docs/sdk/content-security-policy.md +31 -0
  38. package/dist/docs/sdk/experiences.md +44 -0
  39. package/dist/docs/sdk/features.md +213 -0
  40. package/dist/docs/sdk/fields.md +263 -0
  41. package/dist/docs/sdk/index.md +74 -0
  42. package/dist/docs/sdk/plugins/create-experience.md +133 -0
  43. package/dist/docs/sdk/plugins/dynamic-experiences.md +59 -0
  44. package/dist/docs/sdk/plugins/index.md +9 -0
  45. package/dist/docs/sdk/plugins/window-object.md +20 -0
  46. package/dist/docs/sdk/predicates.md +113 -0
  47. package/dist/docs/sdk/steps.md +411 -0
  48. package/dist/docs/steps.md +35 -0
  49. package/dist/docs/team-management.md +40 -0
  50. package/dist/docs/tooling/chrome-extension.md +29 -0
  51. package/dist/docs/tooling/gtm-template.md +69 -0
  52. package/dist/docs/tooling/index.md +19 -0
  53. package/dist/docs/tooling/mcp.md +120 -0
  54. package/dist/docs/tooling/vite-plugin.md +82 -0
  55. package/dist/docs/workspaces.md +35 -0
  56. package/dist/esm/form/index.js +1 -1
  57. package/dist/esm/index.js +158 -284
  58. package/dist/esm/plugins/create-experience/index.js +1 -1
  59. package/dist/esm/plugins/dynamic-experiences/index.js +2 -2
  60. package/dist/esm/plugins/experience-browser-storage/index.js +1 -1
  61. package/dist/esm/plugins/single-page-app/index.js +28 -14
  62. package/dist/esm/plugins/web-components/index.js +1 -1
  63. package/dist/esm/plugins/window-object/index.js +1 -1
  64. package/dist/esm/server/index.js +1 -1
  65. package/dist/experience-CNIhapU2.js +136 -0
  66. package/dist/experience-CTEBY-it.cjs +1 -0
  67. package/dist/experience-instance-Cu8oGGr9.cjs +1 -0
  68. package/dist/experience-instance-DIpWYaA6.js +387 -0
  69. package/dist/nodes-2fst8XKi.js +101 -0
  70. package/dist/nodes-DBK4N9YY.cjs +1 -0
  71. package/dist/rules-logic-D7dL30U1.js +263 -0
  72. package/dist/rules-logic-DJhGFqhC.cjs +1 -0
  73. package/dist/types/plugins/single-page-app/plugin.d.ts +15 -4
  74. package/dist/types/plugins/single-page-app/plugin.d.ts.map +1 -1
  75. package/package.json +2 -2
  76. package/dist/experience-instance-DG9HFNSE.cjs +0 -1
  77. package/dist/experience-instance-DffMstSs.js +0 -486
  78. package/dist/object-C82v79xc.js +0 -25
  79. package/dist/object-CUJOjanb.cjs +0 -1
  80. package/dist/rules-logic-B--rEvGw.js +0 -240
  81. package/dist/rules-logic-D_dZ52-Q.cjs +0 -1
  82. /package/dist/{id-Bv44ilEo.cjs → id-Cg7fVl1O.cjs} +0 -0
  83. /package/dist/{id-CRqy981z.js → id-n2yrHvNo.js} +0 -0
  84. /package/dist/{logger-6z_gb4rA.js → logger-C44jSdYl.js} +0 -0
  85. /package/dist/{logger-fbvQC40v.cjs → logger-CJUj90QX.cjs} +0 -0
  86. /package/dist/{supports-0XIfd4-R.js → supports-B_trw6lj.js} +0 -0
  87. /package/dist/{supports-Dsjg-82e.cjs → supports-CKSVYpQx.cjs} +0 -0
@@ -0,0 +1,249 @@
1
+ ---
2
+ layout: docs
3
+ ---
4
+
5
+ # Example queries
6
+
7
+ ## Daily A/B test trend
8
+
9
+ ```sql
10
+ SELECT
11
+ project_local_date,
12
+ control_users() AS control,
13
+ variant_users() AS variant
14
+ FROM metrics
15
+ WHERE project_id = '{{ your project ID }}'
16
+ AND project_local_date >= '2026-04-01'
17
+ GROUP BY project_local_date
18
+ ORDER BY project_local_date
19
+ ```
20
+
21
+ **Result:**
22
+
23
+ | project_local_date | control | variant |
24
+ | ----------------- | ------- | ------- |
25
+ | 2026-04-11 | 4361 | 101 |
26
+ | 2026-04-12 | 4178 | 126 |
27
+ | 2026-04-13 | 5008 | 176 |
28
+
29
+ ## Conversion rate uplift by date
30
+
31
+ ```sql
32
+ SELECT
33
+ project_local_date,
34
+ control_conversion_rate() AS control_conversion_rate,
35
+ variant_conversion_rate() AS variant_conversion_rate,
36
+ conversion_rate_uplift() AS conversion_rate_uplift_pct
37
+ FROM metrics
38
+ WHERE project_id = '{{ your project ID }}'
39
+ AND project_local_date >= '2026-04-01'
40
+ GROUP BY project_local_date
41
+ ORDER BY project_local_date
42
+ ```
43
+
44
+ **Result:**
45
+
46
+ | project_local_date | control_conversion_rate | variant_conversion_rate | conversion_rate_uplift_pct |
47
+ | ----------------- | ----------------------- | ----------------------- | -------------------------- |
48
+ | 2026-04-01 | 0.0322 | 0.0349 | 0.0349 |
49
+ | 2026-04-02 | 0.0398 | 0.0416 | 0.0416 |
50
+ | 2026-04-03 | 0.0462 | 0 | -0.0001 |
51
+
52
+ ## Custom conversion rate definition
53
+
54
+ Override the default purchase conversion with your own numerator and denominator. Useful when conversion is defined by a form submission, lead capture, or any custom event.
55
+
56
+ ```sql
57
+ -- Lead capture conversion: form submissions / lead-capture step entries
58
+ SELECT
59
+ project_local_date,
60
+ control_conversion_rate(
61
+ numerator='event_type=form_submit_success',
62
+ denominator='step_id=lead-capture-step'
63
+ ) AS control_lead_cr,
64
+ variant_conversion_rate(
65
+ numerator='event_type=form_submit_success',
66
+ denominator='step_id=lead-capture-step'
67
+ ) AS variant_lead_cr
68
+ FROM events
69
+ WHERE project_id = '{{ your project ID }}'
70
+ AND client_local_date >= '2026-04-01'
71
+ GROUP BY project_local_date
72
+ ORDER BY project_local_date
73
+ ```
74
+
75
+ You can also combine multiple events with `OR` and group with parentheses:
76
+
77
+ ```sql
78
+ -- Either checkout_complete or order_create counts as a conversion
79
+ SELECT
80
+ control_conversion_rate(
81
+ 'event_type=checkout_complete OR event_type=order_create'
82
+ ) AS control_cr,
83
+ variant_conversion_rate(
84
+ 'event_type=checkout_complete OR event_type=order_create'
85
+ ) AS variant_cr
86
+ FROM events
87
+ WHERE project_id = '{{ your project ID }}'
88
+ ```
89
+
90
+ ## A/B test by device
91
+
92
+ ```sql
93
+ SELECT
94
+ device_category,
95
+ control_users() AS control,
96
+ variant_users() AS variant
97
+ FROM metrics
98
+ WHERE project_id = '{{ your project ID }}'
99
+ GROUP BY device_category
100
+ ```
101
+
102
+ **Result:**
103
+
104
+ | device_category | control | variant |
105
+ | --------------- | ------- | ------- |
106
+ | Phone | 193430 | 1723 |
107
+ | Desktop | 23423 | 309 |
108
+ | Tablet | 13294 | 65 |
109
+
110
+ ## Daily A/B test trend by device
111
+
112
+ Combine date and device dimensions to spot device-specific trends:
113
+
114
+ ```sql
115
+ SELECT
116
+ project_local_date,
117
+ device_category,
118
+ control_users() AS control,
119
+ variant_users() AS variant
120
+ FROM metrics
121
+ WHERE project_id = '{{ your project ID }}'
122
+ AND project_local_date >= '2026-04-01'
123
+ GROUP BY project_local_date, device_category
124
+ ORDER BY project_local_date, device_category
125
+ ```
126
+
127
+ **Result:**
128
+
129
+ | project_local_date | device_category | control | variant |
130
+ | ----------------- | --------------- | ------- | ------- |
131
+ | 2026-04-13 | Tablet | 175 | 2 |
132
+ | 2026-04-14 | Desktop | 37 | 1 |
133
+ | 2026-04-14 | Phone | 244 | 1 |
134
+
135
+ ## Purchase by UTM source
136
+
137
+ ```sql
138
+ SELECT
139
+ utm_source,
140
+ all_users() AS users,
141
+ total_purchase_users() AS purchasers
142
+ FROM metrics
143
+ WHERE project_id = '{{ your project ID }}'
144
+ GROUP BY utm_source
145
+ ```
146
+
147
+ **Result:**
148
+
149
+ | utm_source | users | purchasers |
150
+ | ---------- | ------ | ---------- |
151
+ | meta | 12031 | 101 |
152
+ | fb | 3656 | 31 |
153
+ | an | 100366 | 299 |
154
+
155
+ ## Step funnel for variant users
156
+
157
+ Count unique variant users per step to understand the conversion funnel:
158
+
159
+ ```sql
160
+ SELECT
161
+ step_id,
162
+ variant_users() AS variant
163
+ FROM metrics
164
+ WHERE project_id = '{{ your project ID }}'
165
+ AND project_local_date >= '2026-04-01'
166
+ GROUP BY step_id
167
+ ORDER BY variant DESC
168
+ ```
169
+
170
+ **Result:**
171
+
172
+ | step_id | variant |
173
+ | ------------------------------ | ------- |
174
+ | who-are-you-protecting-step | 1093 |
175
+ | about-yourself-step | 533 |
176
+ | date-of-birth-step | 435 |
177
+ | employment-status-step | 408 |
178
+ | nicotine-usage-step | 407 |
179
+ | coverage-motivation-step | 405 |
180
+ | lead-capture-step | 398 |
181
+
182
+
183
+ ## Sankey — overall user journey
184
+
185
+ Forward window from the starting step. Non-reachers of `targeting_step` still contribute edges up to `num_nodes_after_start`. Mirrors dashboard 1156 card 4129's semantics.
186
+
187
+ ```sql
188
+ SELECT source, target, users FROM experience_journey
189
+ WHERE project_id = '{{ your project ID }}'
190
+ AND starting_step = '{{ starting step ID }}'
191
+ AND targeting_step = '{{ target step ID }}'
192
+ AND num_nodes_after_start = 10
193
+ ```
194
+
195
+ **Result:**
196
+
197
+ | source | target | users |
198
+ | ------------------------- | ------------------------- | ----- |
199
+ | 001. step-start | 002. step-questionnaire-1 | 182 |
200
+ | 002. step-questionnaire-1 | 003. step-quote | 144 |
201
+ | 003. step-quote | 004. step-target | 121 |
202
+
203
+ ## Sankey — top paths leading to a target step
204
+
205
+ Backward window anchored at the target, plus top-N path ranking. Mirrors dashboard 1156 card 3961 / dashboard 991 card 2740 semantics.
206
+
207
+ ```sql
208
+ SELECT source, target, users FROM experience_journey
209
+ WHERE project_id = '{{ your project ID }}'
210
+ AND experience_id = '{{ experience ID }}'
211
+ AND starting_step = '{{ starting step ID }}'
212
+ AND targeting_step = '{{ target step ID }}'
213
+ AND num_nodes_before_target = 5
214
+ AND top_n_path = 10
215
+ ```
216
+
217
+ ## Sankey — drop-off view
218
+
219
+ Starts at `starting_step` and emits every consecutive transition until `num_nodes_after_start` steps later (no target). Mirrors card 2744.
220
+
221
+ ```sql
222
+ SELECT source, target, users FROM experience_journey
223
+ WHERE project_id = '{{ your project ID }}'
224
+ AND experience_id = '{{ experience ID }}'
225
+ AND starting_step = '{{ starting step ID }}'
226
+ AND num_nodes_after_start = 10
227
+ ```
228
+
229
+ ## List all control users for mobile (user-level)
230
+
231
+ Use `events` when you need data at the individual user level:
232
+
233
+ ```sql
234
+ SELECT
235
+ device_category,
236
+ user_canonical_id
237
+ FROM events
238
+ WHERE project_id = '{{ your project ID }}'
239
+ AND device_category = 'Mobile'
240
+ AND variant_type = 'Control'
241
+ ```
242
+
243
+ **Result:**
244
+
245
+ | device_category | user_canonical_id |
246
+ | --------------- | ------------------------------------ |
247
+ | Mobile | 019cc336-5a6a-7c32-b638-cdcc983b3e70 |
248
+ | Mobile | 019cc336-5a6a-7d8f-994c-69bc28e5f550 |
249
+ | Mobile | 019cc80f-503c-7181-b2c6-986b1f76d496 |
@@ -0,0 +1,31 @@
1
+ ---
2
+ layout: docs
3
+ ---
4
+
5
+ # Filtering
6
+
7
+ Add `WHERE` clauses as usual. Every query must include a `project_id` filter — PickedQL extracts it and verifies you have permission to access that project. Queries without a `project_id` filter are rejected.
8
+
9
+ ```sql
10
+ -- Date range
11
+ SELECT control_users() FROM metrics
12
+ WHERE project_id = 'your-project-id'
13
+ AND project_local_date BETWEEN '2026-03-01' AND '2026-03-31'
14
+
15
+ -- By experience
16
+ SELECT step_enter_users() FROM events
17
+ WHERE project_id = 'your-project-id'
18
+ AND experience_id = 'my-experience'
19
+ GROUP BY step_id
20
+
21
+ -- Combined filters
22
+ SELECT control_users(), variant_users() FROM metrics
23
+ WHERE project_id = 'your-project-id'
24
+ AND project_local_date >= '2026-03-01'
25
+ AND experience_id = 'my-experience'
26
+ AND device_category = 'Mobile'
27
+ ```
28
+
29
+ :::warning
30
+ Each query can only filter on a single `project_id`. Queries that reference multiple projects will be rejected.
31
+ :::
@@ -0,0 +1,35 @@
1
+ ---
2
+ layout: docs
3
+ ---
4
+
5
+ # PickedQL
6
+
7
+ PickedQL is a SQL query language for querying your Picked analytics data. Write simple SQL using virtual tables and functions — PickedQL expands them into optimized queries with automatic joins and A/B test aggregations.
8
+
9
+ ## Quick start
10
+
11
+ ```sql
12
+ -- How many users are in the control vs variant group?
13
+ SELECT control_users(), variant_users()
14
+ FROM metrics
15
+ WHERE project_id = 'your-project-id'
16
+ ```
17
+
18
+ PickedQL handles table mapping and dimension joins automatically. You write concise, readable SQL — PickedQL does the rest.
19
+
20
+ ## How PickedQL works
21
+
22
+ 1. **Virtual table expansion**: Table names like `metrics` map to underlying data tables
23
+ 2. **Virtual function expansion**: Shorthand functions like `control_users()` expand to full aggregate expressions
24
+ 3. **Auto dimension joins**: References to dimension columns (like `device_category` or `country_code`) trigger automatic `LEFT JOIN` clauses — you never write joins yourself
25
+ 4. **Tenant isolation**: Every query must include a `project_id` filter in the `WHERE` clause. PickedQL extracts it and verifies you have permission to access that project
26
+ 5. **SQL passthrough**: Standard SQL (including `CASE WHEN`, window functions, and subqueries) works alongside virtual functions
27
+
28
+ ## Best practices
29
+
30
+ - **Use `metrics` for dashboards**: Pre-aggregated data is significantly faster than raw events for standard reporting
31
+ - **Use `events` for deep dives**: Raw event-level data gives full flexibility for custom breakdowns and funnels
32
+ - **Use `experience_journey` for sankey / funnel charts**: One line of SQL returns `source, target, users` — the 8-CTE scaffold (dedup, top-N path ranking, lagInFrame) is handled internally; pass parameters via `WHERE`
33
+ - **Don't write JOINs**: PickedQL injects them automatically when you reference dimension columns
34
+ - **Group by any dimension**: Add dimension columns to `SELECT` and `GROUP BY` freely — required joins are handled for you
35
+
@@ -0,0 +1,123 @@
1
+ ---
2
+ layout: docs
3
+ ---
4
+
5
+ # Schema
6
+
7
+ Column reference for each PickedQL data source.
8
+
9
+ ## `metrics`
10
+
11
+ Pre-aggregated daily data. One row per unique combination of dimensions per day.
12
+
13
+ | Column | Type | Description |
14
+ |---|---|---|
15
+ | `project_id` | String | Project identifier (required in `WHERE`) |
16
+ | `project_local_date` | Date | Date in project timezone |
17
+ | `experience_id` | String | Experience identifier |
18
+ | `step_id` | String | Step identifier |
19
+ | `event_type` | String | Event type (e.g., `page_view`, `click`) |
20
+ | `interaction_type` | String | Interaction type (e.g., `Button Click`) |
21
+ | `variant_type` | String | `Control`, `Variant`, or `Unknown` |
22
+ | `device_category` | String | Device category (e.g., `Desktop`, `Mobile`) |
23
+ | `country_code` | String | ISO country code |
24
+ | `utm_source` | String | UTM source |
25
+ | `utm_medium` | String | UTM medium |
26
+ | `product_name` | String | Product name |
27
+ | `product_category` | String | Product category |
28
+ | `landing_page_url` | String | Landing page URL |
29
+
30
+ :::note
31
+ Aggregate columns (`users`, `sessions`, `events`, etc.) are not queried directly — use [virtual functions](./virtual-functions) instead.
32
+ :::
33
+
34
+ ## `events`
35
+
36
+ User-level event data. One row per event per user. Dimension columns are joined automatically when referenced.
37
+
38
+ ### Native columns
39
+
40
+ | Column | Type | Description |
41
+ |---|---|---|
42
+ | `project_id` | String | Project identifier (required in `WHERE`) |
43
+ | `event_id` | String | Unique event identifier |
44
+ | `user_canonical_id` | String | Canonical user identifier |
45
+ | `session_id` | String | Session identifier |
46
+ | `experience_id` | String | Experience identifier |
47
+ | `step_id` | String | Step identifier |
48
+ | `event_type` | String | Event type (e.g., `page_view`, `click`) |
49
+ | `interaction_type` | String | Interaction type (e.g., `Button Click`) |
50
+ | `client_local_date` | Date | Date in client timezone |
51
+ | `is_purchase` | UInt8 | `1` if checkout complete event |
52
+ | `is_cart_add` | UInt8 | `1` if cart add event |
53
+ | `is_first_session` | UInt8 | `1` if first session for this user |
54
+ | `landing_page_url` | String | Landing page URL |
55
+ | `features` | Map(String, String) | Feature flag assignments |
56
+ | `feature_keys` | Map(String, String) | Feature key assignments |
57
+ | `event_meta` | String | Event metadata |
58
+
59
+ ### Dimension columns (auto-joined)
60
+
61
+ These columns are joined automatically when referenced — no `JOIN` syntax needed.
62
+
63
+ | Column | Source | Description |
64
+ |---|---|---|
65
+ | `variant_type` | dim_variant | `Control`, `Variant`, or `Unknown` |
66
+ | `ab_feature_name` | dim_variant | A/B feature name |
67
+ | `ab_feature_value` | dim_variant | A/B feature value |
68
+ | `device_category` | dim_device | Device category |
69
+ | `browser_name` | dim_device | Browser name |
70
+ | `browser_version` | dim_device | Browser version |
71
+ | `os_name` | dim_device | Operating system name |
72
+ | `os_version` | dim_device | Operating system version |
73
+ | `platform` | dim_device | Platform |
74
+ | `country_code` | dim_geo | ISO country code |
75
+ | `country_name` | dim_geo | Country name |
76
+ | `region` | dim_geo | Region |
77
+ | `city` | dim_geo | City |
78
+ | `utm_source` | dim_utm | UTM source |
79
+ | `utm_medium` | dim_utm | UTM medium |
80
+ | `utm_campaign` | dim_utm | UTM campaign |
81
+ | `utm_term` | dim_utm | UTM term |
82
+ | `utm_content` | dim_utm | UTM content |
83
+ | `product_name` | dim_product | Product name |
84
+ | `product_category` | dim_product | Product category |
85
+ | `product_page` | dim_product | Product page |
86
+
87
+ ## `features`
88
+
89
+ The `features` table provides [parameterized virtual functions](./virtual-functions#feature-functions-features--events) for querying feature flag assignments:
90
+
91
+ | Function | Description |
92
+ |---|---|
93
+ | `feature_users('name', 'bucket' [, 'key'])` | Unique users in a feature bucket |
94
+ | `feature_sessions('name', 'bucket' [, 'key'])` | Unique sessions in a feature bucket |
95
+ | `feature_events('name', 'bucket' [, 'key'])` | Unique events in a feature bucket |
96
+
97
+ ## `experience_journey`
98
+
99
+ 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).
100
+
101
+ ### Columns
102
+
103
+ | Column | Type | Description |
104
+ |---|---|---|
105
+ | `source` | String | Edge start, formatted as `NN. step_id` (e.g., `01. welcome`). |
106
+ | `target` | String | Edge end, formatted as `NN. step_id`. |
107
+ | `users` | UInt64 | Distinct `user_canonical_id` count that traversed this edge. |
108
+
109
+ ### Parameters (via `WHERE`)
110
+
111
+ | Key | Type | Required | Purpose |
112
+ |---|---|---|---|
113
+ | `project_id` | String | ✓ | Tenant filter. |
114
+ | `experience_id` | String | | Restrict to one `fact_events.experience_id`. |
115
+ | `starting_step` | String | | Anchor edges at first occurrence of this `step_id`. Defaults to each user's first step. |
116
+ | `targeting_step` | String | | Trim each user's window at their first occurrence of this `step_id`. Non-reachers still contribute their pre-cut journey. |
117
+ | `num_nodes_after_start` | Integer | | Forward window from start: keep steps where `seq_pos < start_seq + N` (card 4129 semantics). |
118
+ | `num_nodes_before_target` | Integer | | Backward window from target: keep steps where `seq_pos >= target_seq - N` (card 2740 semantics). Requires `targeting_step`. |
119
+ | `top_n_path` | Integer | | Keep only the top-N most-walked paths by user count. Defaults to no limit. |
120
+
121
+ When both window params are set, both predicates apply (intersection).
122
+
123
+ See [data sources → experience_journey](./data-sources#experience_journey--sankey-ready-step-transitions) for usage examples.
@@ -0,0 +1,121 @@
1
+ ---
2
+ layout: docs
3
+ ---
4
+
5
+ # Virtual functions
6
+
7
+ Virtual functions are shorthand for aggregate expressions. They are **table-aware** — the same function expands differently on `metrics` (pre-aggregated) vs `events` (user-level).
8
+
9
+ ## A/B test metrics
10
+
11
+ | Function | Description |
12
+ |---|---|
13
+ | `control_users()` | Unique users in the Control group |
14
+ | `variant_users()` | Unique users in the Variant group |
15
+ | `all_users()` | All unique users |
16
+ | `control_sessions()` | Unique sessions in the Control group |
17
+ | `variant_sessions()` | Unique sessions in the Variant group |
18
+ | `all_sessions()` | All unique sessions |
19
+
20
+ ## Conversion metrics
21
+
22
+ | Function | Description |
23
+ |---|---|
24
+ | `total_purchase_users()` | Users who completed a purchase |
25
+ | `control_purchase_users()` | Control users who purchased (`metrics` only) |
26
+ | `variant_purchase_users()` | Variant users who purchased (`metrics` only) |
27
+ | `total_purchase_sessions()` | Sessions with a purchase (`metrics` only) |
28
+ | `total_purchase_orders()` | Unique order count (`metrics` only) |
29
+ | `total_cart_add_users()` | Users who added to cart |
30
+
31
+ ## Conversion rates
32
+
33
+ | Function | Description |
34
+ |---|---|
35
+ | `control_conversion_rate([numerator [, denominator]])` | Conversion rate for Control. Defaults to purchase users / all users |
36
+ | `variant_conversion_rate([numerator [, denominator]])` | Conversion rate for Variant. Same args as above |
37
+ | `conversion_rate_uplift([numerator [, denominator]])` | Relative improvement: `(variant CR - control CR) / control CR`. Same args as above |
38
+
39
+ ### Custom conditions on `events`
40
+
41
+ On the `events` table, conversion rate functions accept up to **2 optional arguments** to customize the numerator and denominator. Arguments can be **positional** or **named** (`numerator=`, `denominator=`).
42
+
43
+ Each argument is a condition expression using `column=value` with `AND`/`OR` operators and parentheses for grouping.
44
+
45
+ ```sql
46
+ -- Default: purchase users / all users
47
+ SELECT control_conversion_rate() FROM events
48
+
49
+ -- Custom numerator, default denominator (all users)
50
+ SELECT control_conversion_rate('event_type=form_submit_success') FROM events
51
+
52
+ -- AND/OR in conditions
53
+ SELECT control_conversion_rate('event_type=checkout_complete OR event_type=order_create') FROM events
54
+ SELECT control_conversion_rate('step_id=lead-capture AND event_type=form_submit_success') FROM events
55
+
56
+ -- Parentheses for grouping
57
+ SELECT control_conversion_rate('event_type=form_submit AND (step_id=lead-capture OR step_id=xxx)') FROM events
58
+
59
+ -- Custom numerator AND denominator (positional)
60
+ SELECT control_conversion_rate('event_type=form_submit', 'step_id=lead-capture') FROM events
61
+
62
+ -- Named arguments (explicit, any order)
63
+ SELECT control_conversion_rate(numerator='event_type=form_submit', denominator='step_id=lead-capture') FROM events
64
+
65
+ -- Named: denominator only (numerator defaults to purchase)
66
+ SELECT control_conversion_rate(denominator='step_id=lead-capture') FROM events
67
+
68
+ -- Uplift with named args
69
+ SELECT conversion_rate_uplift(numerator='event_type=form_submit', denominator='step_id=lead-capture') FROM events
70
+ ```
71
+
72
+ :::note
73
+ Custom conditions are **not supported on `metrics`** (pre-aggregated data). On `metrics`, these functions always use the default purchase / all users definition.
74
+ :::
75
+
76
+ ## Visitor segmentation (`metrics` only)
77
+
78
+ | Function | Description |
79
+ |---|---|
80
+ | `new_users()` | First-time visitors |
81
+ | `returning_users()` | Returning visitors |
82
+ | `new_sessions()` | Sessions from new visitors |
83
+ | `returning_sessions()` | Sessions from returning visitors |
84
+
85
+ ## Funnel metrics (`events` only)
86
+
87
+ :::note
88
+ Funnel metrics are being continuously updated. Check back for new functions.
89
+ :::
90
+
91
+ | Function | Description |
92
+ |---|---|
93
+ | `step_enter_users()` | Users who entered a funnel step |
94
+ | `step_enter_sessions()` | Sessions that entered a funnel step |
95
+
96
+ ## Feature functions (`features` / `events`)
97
+
98
+ Parameterized functions that accept the feature name, bucket, and an optional feature key:
99
+
100
+ | Function | Description |
101
+ |---|---|
102
+ | `feature_users('name', 'bucket' [, 'key'])` | Unique users in a feature bucket |
103
+ | `feature_sessions('name', 'bucket' [, 'key'])` | Unique sessions in a feature bucket |
104
+ | `feature_events('name', 'bucket' [, 'key'])` | Unique events in a feature bucket |
105
+
106
+ ```sql
107
+ -- Compare feature buckets
108
+ SELECT
109
+ feature_users('homepage_test', 'control') AS control,
110
+ feature_users('homepage_test', 'variant') AS variant
111
+ FROM features
112
+
113
+ -- With feature key filter
114
+ SELECT feature_users('homepage_test', 'control', 'v1') FROM features
115
+ ```
116
+
117
+ ## Other (`metrics` only)
118
+
119
+ | Function | Description |
120
+ |---|---|
121
+ | `event_count()` | Total event count (from pre-aggregation) |
@@ -0,0 +1,30 @@
1
+ ---
2
+ layout: docs
3
+ ---
4
+
5
+ # Projects
6
+
7
+ A project represents one website or app you want to instrument with Picked. Each project has its own set of experiences, entities, and configuration.
8
+
9
+ ## Create a project
10
+
11
+ You need an organization first. If you don't have one, create it when you sign up.
12
+
13
+ 1. Open your organization.
14
+ 2. Click **New Project**.
15
+ 3. Enter a name.
16
+ 4. Click **Create**.
17
+
18
+ ## Workspaces
19
+
20
+ Each project contains one or more [Workspaces](/workspaces) for configuring and previewing experiences before publishing.
21
+
22
+ ## Project home
23
+
24
+ When you open a project, you land on the project home page. It shows your SDK installation snippet and a getting-started checklist.
25
+
26
+ 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.
27
+
28
+ ## Project navigation
29
+
30
+ 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.
@@ -0,0 +1,11 @@
1
+ ---
2
+ layout: docs
3
+ ---
4
+
5
+ # Reference
6
+
7
+ Typedoc Reference
8
+
9
+ ## Getting Started
10
+
11
+ Coming soon
@@ -0,0 +1,11 @@
1
+ ---
2
+ layout: docs
3
+ ---
4
+
5
+ # Reports
6
+
7
+ Reports show analytics data for your project. Track how visitors interact with your experiences and features.
8
+
9
+ ## View report data
10
+
11
+ Open a report to see its analytics. Data updates as new visitor interactions are recorded.
@@ -0,0 +1,37 @@
1
+ ---
2
+ layout: docs
3
+ ---
4
+
5
+ # Actions
6
+
7
+ Register action handlers on the Picked client so the SDK can invoke them when an experience flow reaches an action node.
8
+
9
+ ## Registering actions
10
+
11
+ Register actions when creating the Picked client. Each key in the `actions` object must match an action key defined in the dashboard:
12
+
13
+ ```ts
14
+ import { createClient } from '@picked/client'
15
+
16
+ const picked = createClient({
17
+ organizationId: 'your-org-id',
18
+ projectId: 'your-project-id',
19
+ actions: {
20
+ 'track-signup': () => {
21
+ analytics.track('signup_completed')
22
+ },
23
+ 'notify': (params) => {
24
+ sendNotification(params)
25
+ },
26
+ },
27
+ })
28
+ ```
29
+
30
+ Each action is a function that receives optional parameters and returns nothing. When the flow reaches an action node, the SDK calls the matching function.
31
+
32
+ ## How actions work
33
+
34
+ 1. **Registration**: Actions are registered to the Picked client during initialization
35
+ 2. **Flow traversal**: When the SDK traverses the experience flow and reaches an action node, it looks up the action by its key
36
+ 3. **Execution**: The matching function is called. Actions execute synchronously within the flow — the SDK continues to the next node after the function returns
37
+ 4. **Non-blocking**: Actions don't interrupt the visitor's experience. The flow continues to the next connected node automatically