@picked/client 0.0.101-next.2 → 0.0.101

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 (147) hide show
  1. package/README.md +34 -158
  2. package/dist/{api-BlRFU0Fi.js → api-BOKA2i46.js} +1 -1
  3. package/dist/{api-AaQeg3Ij.cjs → api-C5jUHF3A.cjs} +1 -1
  4. package/dist/cjs/index.js +2 -2
  5. package/dist/cjs/plugins/dynamic-experiences/index.js +1 -1
  6. package/dist/cjs/server/index.js +1 -1
  7. package/dist/esm/index.js +2 -2
  8. package/dist/esm/plugins/dynamic-experiences/index.js +2 -2
  9. package/dist/esm/server/index.js +2 -2
  10. package/dist/{plugin-CVD2TnRC.cjs → plugin-BcB9ah7q.cjs} +1 -1
  11. package/dist/{plugin-DhznDG-h.js → plugin-COWxZiTa.js} +2 -2
  12. package/dist/{preview-unavailable-mW4Pj3Ph.js → preview-unavailable-BJjc3UNr.js} +1 -1
  13. package/dist/{preview-unavailable-xWLCr93y.cjs → preview-unavailable-CV1BonKA.cjs} +1 -1
  14. package/dist/{provider-COb_V-yq.js → provider-CszmtTg3.js} +1 -1
  15. package/dist/{provider-zag5m5GH.cjs → provider-daBChM0G.cjs} +1 -1
  16. package/package.json +5 -5
  17. package/dist/docs/_root.css +0 -101
  18. package/dist/docs/explanation/conditions-and-the-logic-engine.md +0 -94
  19. package/dist/docs/explanation/content-references.md +0 -99
  20. package/dist/docs/explanation/feature-flag-allocation.md +0 -218
  21. package/dist/docs/explanation/how-picked-works.md +0 -124
  22. package/dist/docs/explanation/how-pickedql-works.md +0 -76
  23. package/dist/docs/explanation/pages-and-flows.md +0 -64
  24. package/dist/docs/explanation/the-content-model.md +0 -87
  25. package/dist/docs/explanation/the-two-apis.md +0 -68
  26. package/dist/docs/explanation/why-server-side-rendering.md +0 -76
  27. package/dist/docs/explanation/workspaces-and-versions.md +0 -71
  28. package/dist/docs/how-to/add-a-step-field-or-action.md +0 -43
  29. package/dist/docs/how-to/analytics/index.md +0 -316
  30. package/dist/docs/how-to/archive-or-delete-a-workspace.md +0 -46
  31. package/dist/docs/how-to/authenticate-the-cli.md +0 -101
  32. package/dist/docs/how-to/authenticate-with-a-magic-link.md +0 -47
  33. package/dist/docs/how-to/authenticate-with-a-password.md +0 -59
  34. package/dist/docs/how-to/authenticate-with-an-api-key.md +0 -51
  35. package/dist/docs/how-to/authenticate-with-oauth.md +0 -40
  36. package/dist/docs/how-to/build-a-flow.md +0 -93
  37. package/dist/docs/how-to/call-an-external-api-from-a-workflow.md +0 -102
  38. package/dist/docs/how-to/connect-the-mcp-server.md +0 -46
  39. package/dist/docs/how-to/create-a-content-entry.md +0 -48
  40. package/dist/docs/how-to/create-a-project.md +0 -29
  41. package/dist/docs/how-to/create-an-experience.md +0 -42
  42. package/dist/docs/how-to/create-and-revoke-an-api-key.md +0 -42
  43. package/dist/docs/how-to/debug-with-the-chrome-extension.md +0 -57
  44. package/dist/docs/how-to/define-a-page-layout.md +0 -46
  45. package/dist/docs/how-to/fill-and-publish-a-page.md +0 -66
  46. package/dist/docs/how-to/install-the-gtm-template.md +0 -84
  47. package/dist/docs/how-to/install-the-sdk.md +0 -93
  48. package/dist/docs/how-to/install-the-vite-plugin.md +0 -69
  49. package/dist/docs/how-to/invite-and-remove-members.md +0 -35
  50. package/dist/docs/how-to/point-one-entry-at-another.md +0 -61
  51. package/dist/docs/how-to/preview-a-workspace.md +0 -28
  52. package/dist/docs/how-to/publish-a-workspace.md +0 -30
  53. package/dist/docs/how-to/read-a-feature-flag.md +0 -113
  54. package/dist/docs/how-to/read-a-referenced-entry.md +0 -109
  55. package/dist/docs/how-to/register-a-component.md +0 -55
  56. package/dist/docs/how-to/register-an-action-handler.md +0 -85
  57. package/dist/docs/how-to/register-an-api-that-uses-oauth2.md +0 -107
  58. package/dist/docs/how-to/render-a-step-form.md +0 -131
  59. package/dist/docs/how-to/render-an-unpublished-preview.md +0 -41
  60. package/dist/docs/how-to/retry-a-failed-call-with-a-loop.md +0 -81
  61. package/dist/docs/how-to/reuse-a-section.md +0 -53
  62. package/dist/docs/how-to/reuse-a-step-field-or-action.md +0 -28
  63. package/dist/docs/how-to/roll-back-a-published-version.md +0 -26
  64. package/dist/docs/how-to/run-an-ab-test.md +0 -49
  65. package/dist/docs/how-to/run-code-on-a-form-submission.md +0 -125
  66. package/dist/docs/how-to/server-render-a-page.md +0 -81
  67. package/dist/docs/how-to/set-a-content-security-policy.md +0 -32
  68. package/dist/docs/how-to/set-up-mfa.md +0 -113
  69. package/dist/docs/how-to/switch-workspaces.md +0 -122
  70. package/dist/docs/how-to/upload-and-use-an-asset.mdx +0 -73
  71. package/dist/docs/how-to/validate-a-field.md +0 -52
  72. package/dist/docs/how-to/wait-for-an-action-response.md +0 -182
  73. package/dist/docs/how-to/write-a-condition.md +0 -45
  74. package/dist/docs/how-to/write-a-predicate.md +0 -60
  75. package/dist/docs/index.md +0 -59
  76. package/dist/docs/reference/dashboard/actions.mdx +0 -56
  77. package/dist/docs/reference/dashboard/api-keys.mdx +0 -38
  78. package/dist/docs/reference/dashboard/conditions.mdx +0 -42
  79. package/dist/docs/reference/dashboard/content/asset-library.mdx +0 -63
  80. package/dist/docs/reference/dashboard/content/blocks.mdx +0 -57
  81. package/dist/docs/reference/dashboard/content/content-entries.mdx +0 -95
  82. package/dist/docs/reference/dashboard/content/models.mdx +0 -108
  83. package/dist/docs/reference/dashboard/content/pages.mdx +0 -61
  84. package/dist/docs/reference/dashboard/experiences.mdx +0 -51
  85. package/dist/docs/reference/dashboard/external-apis.md +0 -169
  86. package/dist/docs/reference/dashboard/features.mdx +0 -154
  87. package/dist/docs/reference/dashboard/fields.mdx +0 -106
  88. package/dist/docs/reference/dashboard/flow-builder/canvas.mdx +0 -58
  89. package/dist/docs/reference/dashboard/flow-builder/condition-builder.md +0 -57
  90. package/dist/docs/reference/dashboard/flow-builder/keyboard-shortcuts.md +0 -72
  91. package/dist/docs/reference/dashboard/flow-builder/nodes.md +0 -63
  92. package/dist/docs/reference/dashboard/labels.md +0 -321
  93. package/dist/docs/reference/dashboard/lead-search.md +0 -224
  94. package/dist/docs/reference/dashboard/projects.mdx +0 -44
  95. package/dist/docs/reference/dashboard/reports.mdx +0 -43
  96. package/dist/docs/reference/dashboard/steps.mdx +0 -37
  97. package/dist/docs/reference/dashboard/team-management.md +0 -29
  98. package/dist/docs/reference/dashboard/workflow-runs.md +0 -142
  99. package/dist/docs/reference/dashboard/workflow-templates.md +0 -182
  100. package/dist/docs/reference/dashboard/workflow-test-runs.md +0 -77
  101. package/dist/docs/reference/dashboard/workspace-versioning.mdx +0 -30
  102. package/dist/docs/reference/dashboard/workspaces.mdx +0 -76
  103. package/dist/docs/reference/delivery-api/experience-content.md +0 -152
  104. package/dist/docs/reference/delivery-api/index.md +0 -45
  105. package/dist/docs/reference/delivery-api/preview-caching-crawling.md +0 -79
  106. package/dist/docs/reference/delivery-api/project-config.md +0 -65
  107. package/dist/docs/reference/delivery-api/workspace-schema.md +0 -107
  108. package/dist/docs/reference/glossary.md +0 -201
  109. package/dist/docs/reference/management-api/authentication.md +0 -87
  110. package/dist/docs/reference/management-api/authorization-and-scopes.md +0 -291
  111. package/dist/docs/reference/management-api/error-handling.md +0 -232
  112. package/dist/docs/reference/management-api/pagination.md +0 -192
  113. package/dist/docs/reference/pickedql/data-sources.md +0 -174
  114. package/dist/docs/reference/pickedql/dimensions.md +0 -103
  115. package/dist/docs/reference/pickedql/filtering.md +0 -64
  116. package/dist/docs/reference/pickedql/index.md +0 -18
  117. package/dist/docs/reference/pickedql/schema.md +0 -172
  118. package/dist/docs/reference/pickedql/virtual-functions.md +0 -248
  119. package/dist/docs/reference/sdk/actions.md +0 -154
  120. package/dist/docs/reference/sdk/analytics-events.md +0 -453
  121. package/dist/docs/reference/sdk/conditions.md +0 -147
  122. package/dist/docs/reference/sdk/content-security-policy.md +0 -21
  123. package/dist/docs/reference/sdk/content.md +0 -253
  124. package/dist/docs/reference/sdk/experiences.md +0 -51
  125. package/dist/docs/reference/sdk/features.md +0 -256
  126. package/dist/docs/reference/sdk/fields.md +0 -255
  127. package/dist/docs/reference/sdk/index.md +0 -68
  128. package/dist/docs/reference/sdk/plugins/create-experience.md +0 -123
  129. package/dist/docs/reference/sdk/plugins/dynamic-experiences.md +0 -74
  130. package/dist/docs/reference/sdk/plugins/index.md +0 -29
  131. package/dist/docs/reference/sdk/plugins/window-object.md +0 -25
  132. package/dist/docs/reference/sdk/predicates.md +0 -43
  133. package/dist/docs/reference/sdk/ssr/index.md +0 -33
  134. package/dist/docs/reference/sdk/ssr/rendering-and-hydration.md +0 -103
  135. package/dist/docs/reference/sdk/ssr/serialize.md +0 -80
  136. package/dist/docs/reference/sdk/ssr/slots-and-placements.md +0 -113
  137. package/dist/docs/reference/sdk/steps.md +0 -86
  138. package/dist/docs/reference/sdk/type-generation.md +0 -265
  139. package/dist/docs/reference/tools/chrome-extension.md +0 -16
  140. package/dist/docs/reference/tools/cli.md +0 -292
  141. package/dist/docs/reference/tools/image-optimisation-service.md +0 -104
  142. package/dist/docs/reference/tools/mcp.md +0 -136
  143. package/dist/docs/reference/tools/vite-plugin.md +0 -163
  144. package/dist/docs/tutorials/first-api-call.md +0 -235
  145. package/dist/docs/tutorials/first-experience-in-the-dashboard.mdx +0 -143
  146. package/dist/docs/tutorials/first-experience.mdx +0 -254
  147. package/dist/docs/tutorials/first-server-rendered-page.mdx +0 -186
@@ -1,192 +0,0 @@
1
- ---
2
- type: reference
3
- layout: docs
4
- ---
5
-
6
- # Pagination
7
-
8
- The Picked API paginates every list field that can return a large result. It uses a
9
- cursor, in the Relay-style pattern. This guide covers the connection pattern and
10
- shows how to move through a result.
11
-
12
- ## Connection pattern
13
-
14
- A paginated field returns a **connection** object with this shape:
15
-
16
- ```graphql
17
- type ExampleConnection {
18
- edges: [ExampleEdge!]!
19
- pageInfo: PageInfo!
20
- totalCount: Int!
21
- }
22
-
23
- type ExampleEdge {
24
- cursor: String!
25
- node: Example!
26
- }
27
-
28
- type PageInfo {
29
- hasNextPage: Boolean!
30
- hasPreviousPage: Boolean!
31
- startCursor: String
32
- endCursor: String
33
- }
34
- ```
35
-
36
- | Field | Description |
37
- |-------|-------------|
38
- | `edges` | An ordered list of edges. Each edge holds a `cursor` and a `node`, and the `node` holds the data. |
39
- | `pageInfo.hasNextPage` | `true` when more results come after the last edge |
40
- | `pageInfo.hasPreviousPage` | `true` when results come before the first edge |
41
- | `pageInfo.startCursor` | The cursor of the first edge on the current page |
42
- | `pageInfo.endCursor` | The cursor of the last edge on the current page |
43
- | `totalCount` | The number of items on every page together |
44
-
45
- ## Forward pagination with `first` and `after`
46
-
47
- To move forward through the results, use two arguments. The `first` argument gives
48
- the page size. The `after` argument gives the cursor to start after.
49
-
50
- ### First page
51
-
52
- Leave the `after` argument out to read the first page:
53
-
54
- ```graphql
55
- query {
56
- organizations(input: { first: 10 }) {
57
- edges {
58
- cursor
59
- node {
60
- id
61
- name
62
- }
63
- }
64
- pageInfo {
65
- hasNextPage
66
- endCursor
67
- }
68
- totalCount
69
- }
70
- }
71
- ```
72
-
73
- ### Next page
74
-
75
- Pass the `endCursor` from the previous response as the `after` argument:
76
-
77
- ```graphql
78
- query {
79
- organizations(input: { first: 10, after: "cursor_from_previous_page" }) {
80
- edges {
81
- cursor
82
- node {
83
- id
84
- name
85
- }
86
- }
87
- pageInfo {
88
- hasNextPage
89
- endCursor
90
- }
91
- totalCount
92
- }
93
- }
94
- ```
95
-
96
- ## Check for more pages
97
-
98
- Read the `hasNextPage` field before you ask for the next page:
99
-
100
- - `hasNextPage: true` — more results are available. Pass `endCursor` as the `after`
101
- argument of the next request.
102
- - `hasNextPage: false` — you read every result. Stop here.
103
-
104
- ## Full paginated query example
105
-
106
- This example reads every member of an organization, one page at a time:
107
-
108
- ```graphql
109
- # Page 1
110
- query {
111
- organization(input: { slug: "my-company" }) {
112
- members(first: 20) {
113
- edges {
114
- cursor
115
- node {
116
- id
117
- userEmail
118
- role
119
- joinedAt
120
- }
121
- }
122
- pageInfo {
123
- hasNextPage
124
- endCursor
125
- }
126
- totalCount
127
- }
128
- }
129
- }
130
- ```
131
-
132
- If `pageInfo.hasNextPage` is `true`, fetch the next page:
133
-
134
- ```graphql
135
- # Page 2
136
- query {
137
- organization(input: { slug: "my-company" }) {
138
- members(first: 20, after: "cursor_from_page_1") {
139
- edges {
140
- cursor
141
- node {
142
- id
143
- userEmail
144
- role
145
- joinedAt
146
- }
147
- }
148
- pageInfo {
149
- hasNextPage
150
- endCursor
151
- }
152
- totalCount
153
- }
154
- }
155
- }
156
- ```
157
-
158
- Continue until `hasNextPage` returns `false`.
159
-
160
- ## Paginated fields
161
-
162
- These fields in the schema return a connection type. They all take the `first` and
163
- `after` arguments:
164
-
165
- | Parent Type | Field | Connection Type |
166
- |------------|-------|----------------|
167
- | `Query` | `organizations` | `OrganizationConnection` |
168
- | `User` | `organizations` | `OrganizationConnection` |
169
- | `User` | `invitations` | `ViewerInvitationConnection` |
170
- | `Organization` | `members` | `OrganizationMemberConnection` |
171
- | `Organization` | `invitations` | `OrganizationInvitationConnection` |
172
- | `Organization` | `projects` | `ProjectConnection` |
173
- | `Project` | `reports` | `ProjectReportConnection` |
174
-
175
- All of these fields accept the same `first` and `after` arguments and return the standard `edges`, `pageInfo`, and `totalCount` structure.
176
-
177
- ## Tips
178
-
179
- - **The default page size** — the API applies a default limit when you leave `first`
180
- out. Set `first` yourself to make sure that each page has the size you expect.
181
- - **A cursor is opaque** — treat a cursor string as an opaque token. Do not parse it,
182
- build it, or change it. Pass it back exactly as the API gave it.
183
- - **The order is stable** — a connection returns its results in a stable order. The
184
- same cursor always points at the same position in the result.
185
- - **Use them with other fields** — you can use the pagination arguments together with
186
- other query fields. One request that reads an organization and the first page of
187
- its members is common, and it is efficient.
188
-
189
- ## Related
190
-
191
- - [Your first API call](/tutorials/first-api-call)
192
- - [Authorization and scopes](/reference/management-api/authorization-and-scopes)
@@ -1,174 +0,0 @@
1
- ---
2
- type: reference
3
- layout: docs
4
- ---
5
-
6
- # Data sources
7
-
8
- PickedQL gives you four virtual tables. Each table is fast for one kind of work. It also gives you three reference tables, and those hold the options of your
9
- Picked project.
10
-
11
- ## `metrics` — data that PickedQL aggregates each day
12
-
13
- Use it for a dashboard and to study a trend. There is one row for each unique set of
14
- dimensions on each day. The dimension columns are there directly, and they need no
15
- join. Examples are `device_category`, `country_code`, and `utm_source`.
16
-
17
- ```sql
18
- SELECT device_category, control_users(), variant_users()
19
- FROM metrics
20
- WHERE project_id = 'your-project-id'
21
- GROUP BY device_category
22
- ```
23
-
24
- ## `events` — one row for each event of each user
25
-
26
- Use it for a deep study, for a funnel, and for a breakdown of your own. There is one
27
- row for each event of each user. PickedQL joins a dimension column, such as
28
- `device_category` or `country_code`, when you point at it.
29
-
30
- ```sql
31
- SELECT user_canonical_id, device_category
32
- FROM events
33
- WHERE project_id = 'your-project-id'
34
- AND variant_type = 'Control'
35
- ```
36
-
37
- ## `features` — one row for each feature flag
38
-
39
- Use it to count the users, the sessions, and the events for each feature flag and
40
- bucket. It uses parameterized functions.
41
-
42
- ```sql
43
- SELECT feature_users('homepage_test', 'control')
44
- FROM features
45
- WHERE project_id = 'your-project-id'
46
- ```
47
-
48
- ## `experience_journey` — step transitions for a sankey chart
49
-
50
- It returns one `source, target, users` row for each edge. You can put those rows
51
- directly into a sankey chart or a funnel chart. It holds the eight common table
52
- expressions that a card carried before. Those call `lagInFrame`, remove a duplicate
53
- between two steps that follow each other, and rank the top paths.
54
-
55
- Every filter goes in the **outer `WHERE`** clause. PickedQL reads each one as a
56
- parameter and puts it into the query below. Only `project_id` is necessary. The rest
57
- are optional, and each has a sensible default.
58
-
59
- | Parameter, as a WHERE key | What it does |
60
- |---|---|
61
- | `project_id` | The tenant filter. It is necessary. |
62
- | `experience_id` | Limits the rows to one `fact_events.experience_id`. |
63
- | `starting_step` | Anchors each edge at the first time that a user reaches this `step_id`. With no value, it anchors at the first `step_enter` event of that user. |
64
- | `targeting_step` | 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 a journey, up to `num_nodes_after_start`. |
65
- | `num_nodes_after_start` | The size of the forward window from the start step. |
66
- | `num_nodes_before_target` | The size of the backward window from the target step. It needs `targeting_step`. |
67
- | `top_n_path` | Keeps the paths with the most users, and drops the rest. |
68
- | `user_cohort_event` | Limits the rows to a user with at least one `fact_events` row of this `event_type`, such as `'lead_capture'`. Use it for the paths of the users who reached a goal. |
69
- | `client_local_date` | A filter on the date. It takes `=`, `<`, `<=`, `>`, `>=`, and `BETWEEN`. PickedQL puts it into the `fact_events` read below. |
70
- | `event_timestamp` | A filter on the timestamp from the server. It takes the same operators as `client_local_date`. |
71
-
72
- When you set both `num_nodes_after_start` and `num_nodes_before_target`, both tests
73
- apply. The result is the intersection of the two.
74
-
75
- ```sql
76
- -- The "overall user journey" sankey.
77
- -- It uses a forward window. The target step is optional.
78
- SELECT source, target, users FROM experience_journey
79
- WHERE project_id = 'your-project-id'
80
- AND starting_step = 'step-start'
81
- AND targeting_step = 'step-target'
82
- AND num_nodes_after_start = 10
83
- AND client_local_date >= '2026-04-01' -- An optional range of dates.
84
- AND client_local_date <= '2026-04-30'
85
- ```
86
-
87
- ```sql
88
- -- The "paths to a target" sankey.
89
- -- It uses a backward window and it ranks the top paths.
90
- SELECT source, target, users FROM experience_journey
91
- WHERE project_id = 'your-project-id'
92
- AND experience_id = 'exp-123'
93
- AND starting_step = 'step-start'
94
- AND targeting_step = 'step-target'
95
- AND num_nodes_before_target = 5
96
- AND top_n_path = 10
97
- ```
98
-
99
- ```sql
100
- -- The "drop-off" sankey. Leave the target step out.
101
- SELECT source, target, users FROM experience_journey
102
- WHERE project_id = 'your-project-id'
103
- AND experience_id = 'exp-123'
104
- AND starting_step = 'step-start'
105
- AND num_nodes_after_start = 10
106
- ```
107
-
108
- ```sql
109
- -- A cohort sankey. It holds the users who reached the goal only.
110
- SELECT source, target, users FROM experience_journey
111
- WHERE project_id = 'your-project-id'
112
- AND starting_step = 'step-start'
113
- AND targeting_step = 'step-target'
114
- AND num_nodes_after_start = 10
115
- AND user_cohort_event = 'lead_capture' -- Users with one or more of these events.
116
- ```
117
-
118
- The columns that it returns:
119
-
120
- | Column | Type | Description |
121
- |---|---|---|
122
- | `source` | String | The start of the edge, in the form `NN. <step title>`, such as `001. Welcome screen`. PickedQL joins `steps` to find the title. |
123
- | `target` | String | The end of the edge, in the form `NN. <step title>`. |
124
- | `users` | `UInt64` | The number of different `user_canonical_id` values that went along this edge. |
125
-
126
- :::note
127
- `experience_journey` returns data that PickedQL aggregates first. It does **not**
128
- support a dimension filter such as `variant_type`, `device_category`, or
129
- `country_code`. To use one of those, query
130
- [`events`](#events--one-row-for-each-event-of-each-user) directly and build the
131
- transitions yourself.
132
- :::
133
-
134
- ## Reference tables — `steps`, `experiences`, `projects`
135
-
136
- These reference tables hold the configuration of your Picked project. They have two uses:
137
-
138
- - **PickedQL joins them onto `events`** when you point at one of their analyst
139
- columns: `step_title`, `experience_title`, `project_name`, or `project_timezone`.
140
- - **You can read them directly.** Each one then needs its own tenant filter, so that
141
- you see only the rows of a project that you can reach.
142
-
143
- | Source | The tenant filter that it needs |
144
- |---|---|
145
- | `steps` | `WHERE project_id = '<project_id>'` |
146
- | `experiences` | `WHERE project_id = '<project_id>'` |
147
- | `projects` | `WHERE id = '<project_id>'` |
148
-
149
- ```sql
150
- -- A direct query that reads the experiences of a project.
151
- SELECT id, title FROM experiences WHERE project_id = 'your-project-id'
152
-
153
- -- A direct query that reads the metadata of one project.
154
- SELECT id, name, timezone FROM projects WHERE id = 'your-project-id'
155
- ```
156
-
157
- ```sql
158
- -- Pointed at from events. PickedQL adds each LEFT JOIN for you.
159
- -- The reference tables need no separate tenant filter, because
160
- -- the event table already limits the join.
161
- SELECT experience_title, step_title, count(*)
162
- FROM events
163
- WHERE project_id = 'your-project-id'
164
- GROUP BY experience_title, step_title
165
- ```
166
-
167
- See [Schema, reference tables](/reference/pickedql/schema#steps-experiences-projects) for the full
168
- column list and the join keys.
169
-
170
- ## Related
171
-
172
- - [About PickedQL](/explanation/how-pickedql-works) — what the layer expands for you.
173
- - [Schema](/reference/pickedql/schema)
174
- - [Analytics queries](/how-to/analytics)
@@ -1,103 +0,0 @@
1
- ---
2
- type: reference
3
- layout: docs
4
- ---
5
-
6
- # Dimension columns
7
-
8
- Every data source has dimension columns. The `metrics` table holds them directly. On
9
- `events` and on `features`, PickedQL adds the `LEFT JOIN` that it needs when you
10
- point at one. You write no join.
11
-
12
- ## The dimensions
13
-
14
- | Source | Columns |
15
- |---|---|
16
- | `dim_variant` | `variant_type`, `ab_feature_name`, `ab_feature_value` |
17
- | `dim_device` | `device_category`, `browser_name`, `browser_version`, `os_name`, `os_version`, `platform` |
18
- | `dim_geo` | `country_code`, `country_name`, `region`, `city` |
19
- | `dim_utm` | `utm_source`, `utm_medium`, `utm_campaign`, `utm_term`, `utm_content` |
20
- | `dim_product` | `product_name`, `product_category`, `product_page` |
21
- | `steps` | `step_title` |
22
- | `experiences` | `experience_title` |
23
- | `projects` | `project_name`, `project_timezone` |
24
-
25
- :::warning
26
- `dim_variant` describes whether the visitor is a known user. It does **not** hold the variants
27
- of your feature flags. To count the visitors in one variant, use
28
- [`feature_users`](/reference/pickedql/virtual-functions#feature-functions-on-features-and-on-events).
29
- :::
30
-
31
- The `steps`, `experiences`, and `projects` sources are reference tables, and they come
32
- from the operational database. PickedQL joins them onto `events` and `fact_events`
33
- when you point at one of their analyst-facing columns. Each one **also** needs its own
34
- tenant filter when you query it directly:
35
-
36
- | Source | The tenant filter that it needs |
37
- |---|---|
38
- | `steps`, `experiences` | `WHERE project_id = '<project_id>'` |
39
- | `projects` | `WHERE id = '<project_id>'`, because the `id` of the row is the project ID |
40
-
41
- PickedQL also puts a tenant equality in the `ON` clause of each join that it adds.
42
- Examples are `AND st.project_id = '<project_id>'` and `AND pr.id = '<project_id>'`.
43
- ClickHouse then reads part of the dimension table and not all of it. PickedQL puts
44
- the test in `ON` and not in `WHERE`, because a test in `WHERE` would change a
45
- `LEFT JOIN` into an inner join.
46
-
47
- Each analyst-facing column name carries a prefix, such as `step_title` and
48
- `project_name`. The prefix stops a collision between two sources. Both `steps.title`
49
- and `experiences.title` are there, and you point at them as `step_title` and
50
- `experience_title`.
51
-
52
- ```sql
53
- -- Group the events by experience and by step name.
54
- -- PickedQL joins both `experiences` and `steps` for you.
55
- SELECT experience_title, step_title, count(*)
56
- FROM events
57
- WHERE project_id = 'your-project-id'
58
- GROUP BY experience_title, step_title
59
- ```
60
-
61
- An automatic join also works inside a subquery and inside a common table expression.
62
- Point at a dimension column where you need it, and PickedQL adds the `LEFT JOIN` at
63
- that level:
64
-
65
- ```sql
66
- -- Dimension columns inside a common table expression.
67
- WITH per_step AS (
68
- SELECT step_title, count(*) AS n
69
- FROM events
70
- WHERE project_id = 'your-project-id'
71
- GROUP BY step_title
72
- )
73
- SELECT * FROM per_step ORDER BY n DESC
74
-
75
- -- Dimension columns inside a nested query.
76
- SELECT step_title, n FROM (
77
- SELECT step_title, count(*) AS n FROM events
78
- WHERE project_id = 'your-project-id'
79
- GROUP BY step_title
80
- ) sub
81
- ```
82
-
83
- ## Native event columns
84
-
85
- These columns are on `events` directly, and they need no join:
86
-
87
- `event_type`, `interaction_type`, `experience_id`, `step_id`, `event_id`, `user_canonical_id`, `session_id`, `client_local_date`, `is_purchase`, `is_cart_add`, `event_meta`.
88
-
89
- Two of them take a name from the SDK. A filter on a name that does not exist gives an
90
- empty result set and not an error:
91
-
92
- | Column | The values that it holds |
93
- |---|---|
94
- | `event_type` | The name of the event, such as `step_enter` or `cart_add`. [Analytics events](/reference/sdk/analytics-events) names every one, together with the name of each custom event of your own. |
95
- | `interaction_type` | The label of the element behind the event. It falls back to `event_type` when the event has no element, so it is **not** the list of interaction types. [Analytics events](/reference/sdk/analytics-events) describes both. |
96
-
97
- ## Related
98
-
99
- - [About PickedQL](/explanation/how-pickedql-works) — why you write no join.
100
- - [Data sources](/reference/pickedql/data-sources)
101
- - [Analytics events](/reference/sdk/analytics-events) — every `event_type` value, and the
102
- contexts behind these columns.
103
- - [Analytics queries](/how-to/analytics)
@@ -1,64 +0,0 @@
1
- ---
2
- type: reference
3
- layout: docs
4
- ---
5
-
6
- # Filters
7
-
8
- Add a `WHERE` clause in the usual way. Every query must hold a `project_id` filter.
9
- PickedQL reads that filter and checks that you have permission for the project.
10
- PickedQL rejects a query with no `project_id` filter.
11
-
12
- ```sql
13
- -- A range of dates.
14
- SELECT control_users() FROM metrics
15
- WHERE project_id = 'your-project-id'
16
- AND project_local_date BETWEEN '2026-03-01' AND '2026-03-31'
17
-
18
- -- By experience.
19
- SELECT step_enter_users() FROM events
20
- WHERE project_id = 'your-project-id'
21
- AND experience_id = 'my-experience'
22
- GROUP BY step_id
23
-
24
- -- Combined filters
25
- SELECT control_users(), variant_users() FROM metrics
26
- WHERE project_id = 'your-project-id'
27
- AND project_local_date >= '2026-03-01'
28
- AND experience_id = 'my-experience'
29
- AND device_category = 'Mobile'
30
- ```
31
-
32
- :::warning
33
- Each query can only filter on a single `project_id`. Queries that reference multiple projects will be rejected.
34
- :::
35
-
36
- ## Reference tables, each with its own tenant filter
37
-
38
- A query against a reference table needs its own tenant filter. The reference tables
39
- are `steps`, `experiences`, and `projects`. The filter makes sure that you see only
40
- the rows of a project that you can reach:
41
-
42
- | Source | Tenant filter |
43
- |---|---|
44
- | `steps`, `experiences` | `WHERE project_id = '<project_id>'` |
45
- | `projects` | `WHERE id = '<project_id>'` (the row's `id` IS the project id) |
46
-
47
- ```sql
48
- -- All experiences for one project
49
- SELECT id, title FROM experiences WHERE project_id = 'your-project-id'
50
-
51
- -- All steps for one project
52
- SELECT id, title FROM steps WHERE project_id = 'your-project-id'
53
-
54
- -- Metadata for one project
55
- SELECT id, name, timezone FROM projects WHERE id = 'your-project-id'
56
- ```
57
-
58
- The small lookup tables (`dim_variant`, `dim_device`, `dim_geo`, `dim_utm`, `dim_product`) are still exempt — they contain no tenant data.
59
-
60
- ## Related
61
-
62
- - [Virtual functions](/reference/pickedql/virtual-functions) — the functions that take a
63
- filter.
64
- - [Analytics queries](/how-to/analytics)
@@ -1,18 +0,0 @@
1
- ---
2
- type: reference
3
- layout: docs
4
- ---
5
-
6
- # PickedQL
7
-
8
- PickedQL is a SQL query language for your Picked analytics data. Write short SQL with
9
- a virtual table and a virtual function. PickedQL expands them into a full query, and
10
- it adds the joins and the A/B test aggregations for you.
11
-
12
- ## Related
13
-
14
- - [About PickedQL](/explanation/how-pickedql-works) — what the layer expands, and why a
15
- tenant filter is required.
16
- - [Analytics queries](/how-to/analytics) — worked examples.
17
- - [Data sources](/reference/pickedql/data-sources) — every table.
18
- - [Filters](/reference/pickedql/filtering) — the filter string a virtual function takes.