@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.
- package/dist/{api-i5hIjZ7M.js → api-6oxKA__k.js} +1 -1
- package/dist/{api-tt6bWMJv.cjs → api-CIC-Uysx.cjs} +1 -1
- package/dist/cjs/form/index.js +1 -1
- package/dist/cjs/index.js +2 -2
- package/dist/cjs/plugins/create-experience/index.js +1 -1
- package/dist/cjs/plugins/dynamic-experiences/index.js +1 -1
- package/dist/cjs/plugins/experience-browser-storage/index.js +1 -1
- package/dist/cjs/plugins/single-page-app/index.js +1 -1
- package/dist/cjs/plugins/web-components/index.js +1 -1
- package/dist/cjs/plugins/window-object/index.js +1 -1
- package/dist/cjs/server/index.js +1 -1
- package/dist/docs/actions.md +58 -0
- package/dist/docs/api/index.md +32 -0
- package/dist/docs/api-keys.md +33 -0
- package/dist/docs/conditions.md +52 -0
- package/dist/docs/experiences.md +33 -0
- package/dist/docs/features.md +51 -0
- package/dist/docs/fields.md +70 -0
- package/dist/docs/flow-builder/building-flows.md +61 -0
- package/dist/docs/flow-builder/condition-builder.md +54 -0
- package/dist/docs/flow-builder/keyboard-shortcuts.md +66 -0
- package/dist/docs/flow-builder/nodes.md +43 -0
- package/dist/docs/flow-builder/overview.md +43 -0
- package/dist/docs/index.md +79 -0
- package/dist/docs/pickedql/data-sources.md +98 -0
- package/dist/docs/pickedql/dimensions.md +23 -0
- package/dist/docs/pickedql/examples.md +249 -0
- package/dist/docs/pickedql/filtering.md +31 -0
- package/dist/docs/pickedql/index.md +35 -0
- package/dist/docs/pickedql/schema.md +123 -0
- package/dist/docs/pickedql/virtual-functions.md +121 -0
- package/dist/docs/projects.md +30 -0
- package/dist/docs/reference/index.md +11 -0
- package/dist/docs/reports.md +11 -0
- package/dist/docs/sdk/actions.md +37 -0
- package/dist/docs/sdk/conditions.md +137 -0
- package/dist/docs/sdk/content-security-policy.md +31 -0
- package/dist/docs/sdk/experiences.md +44 -0
- package/dist/docs/sdk/features.md +213 -0
- package/dist/docs/sdk/fields.md +263 -0
- package/dist/docs/sdk/index.md +74 -0
- package/dist/docs/sdk/plugins/create-experience.md +133 -0
- package/dist/docs/sdk/plugins/dynamic-experiences.md +59 -0
- package/dist/docs/sdk/plugins/index.md +9 -0
- package/dist/docs/sdk/plugins/window-object.md +20 -0
- package/dist/docs/sdk/predicates.md +113 -0
- package/dist/docs/sdk/steps.md +411 -0
- package/dist/docs/steps.md +35 -0
- package/dist/docs/team-management.md +40 -0
- package/dist/docs/tooling/chrome-extension.md +29 -0
- package/dist/docs/tooling/gtm-template.md +69 -0
- package/dist/docs/tooling/index.md +19 -0
- package/dist/docs/tooling/mcp.md +120 -0
- package/dist/docs/tooling/vite-plugin.md +82 -0
- package/dist/docs/workspaces.md +35 -0
- package/dist/esm/form/index.js +1 -1
- package/dist/esm/index.js +158 -284
- package/dist/esm/plugins/create-experience/index.js +1 -1
- package/dist/esm/plugins/dynamic-experiences/index.js +2 -2
- package/dist/esm/plugins/experience-browser-storage/index.js +1 -1
- package/dist/esm/plugins/single-page-app/index.js +28 -14
- package/dist/esm/plugins/web-components/index.js +1 -1
- package/dist/esm/plugins/window-object/index.js +1 -1
- package/dist/esm/server/index.js +1 -1
- package/dist/experience-CNIhapU2.js +136 -0
- package/dist/experience-CTEBY-it.cjs +1 -0
- package/dist/experience-instance-Cu8oGGr9.cjs +1 -0
- package/dist/experience-instance-DIpWYaA6.js +387 -0
- package/dist/nodes-2fst8XKi.js +101 -0
- package/dist/nodes-DBK4N9YY.cjs +1 -0
- package/dist/rules-logic-D7dL30U1.js +263 -0
- package/dist/rules-logic-DJhGFqhC.cjs +1 -0
- package/dist/types/plugins/single-page-app/plugin.d.ts +15 -4
- package/dist/types/plugins/single-page-app/plugin.d.ts.map +1 -1
- package/package.json +2 -2
- package/dist/experience-instance-DG9HFNSE.cjs +0 -1
- package/dist/experience-instance-DffMstSs.js +0 -486
- package/dist/object-C82v79xc.js +0 -25
- package/dist/object-CUJOjanb.cjs +0 -1
- package/dist/rules-logic-B--rEvGw.js +0 -240
- package/dist/rules-logic-D_dZ52-Q.cjs +0 -1
- /package/dist/{id-Bv44ilEo.cjs → id-Cg7fVl1O.cjs} +0 -0
- /package/dist/{id-CRqy981z.js → id-n2yrHvNo.js} +0 -0
- /package/dist/{logger-6z_gb4rA.js → logger-C44jSdYl.js} +0 -0
- /package/dist/{logger-fbvQC40v.cjs → logger-CJUj90QX.cjs} +0 -0
- /package/dist/{supports-0XIfd4-R.js → supports-B_trw6lj.js} +0 -0
- /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
|
+
# 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
|