@picked/client 0.0.71-next.1 → 0.0.71-next.3
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/.tsbuildinfo +1 -1
- package/dist/{api-CH2FNa6S.cjs → api-CnjBi6JG.cjs} +1 -1
- package/dist/{api-CgqRvuKL.js → api-vBVGLtvU.js} +1 -1
- package/dist/cjs/index.js +2 -2
- package/dist/cjs/plugins/dynamic-experiences/index.js +1 -1
- package/dist/cjs/server/index.js +1 -1
- package/dist/docs/explanation/conditions-and-the-logic-engine.md +94 -0
- package/dist/docs/explanation/feature-flag-allocation.md +176 -0
- package/dist/docs/explanation/how-picked-works.md +102 -0
- package/dist/docs/explanation/how-pickedql-works.md +76 -0
- package/dist/docs/explanation/pages-and-flows.md +64 -0
- package/dist/docs/explanation/the-content-model.md +77 -0
- package/dist/docs/explanation/the-two-apis.md +68 -0
- package/dist/docs/explanation/why-server-side-rendering.md +76 -0
- package/dist/docs/explanation/workspaces-and-versions.md +71 -0
- package/dist/docs/how-to/add-a-step-field-or-action.md +43 -0
- package/dist/docs/{pickedql/examples.md → how-to/analytics/index.md} +19 -6
- package/dist/docs/how-to/archive-or-delete-a-workspace.md +46 -0
- package/dist/docs/how-to/authenticate-with-a-magic-link.md +40 -0
- package/dist/docs/how-to/authenticate-with-a-password.md +51 -0
- package/dist/docs/how-to/authenticate-with-an-api-key.md +51 -0
- package/dist/docs/how-to/authenticate-with-oauth.md +40 -0
- package/dist/docs/{flow-builder/building-flows.md → how-to/build-a-flow.md} +13 -9
- package/dist/docs/how-to/connect-the-mcp-server.md +38 -0
- package/dist/docs/how-to/create-a-project.md +29 -0
- package/dist/docs/how-to/create-an-experience.md +42 -0
- package/dist/docs/how-to/create-and-revoke-an-api-key.md +37 -0
- package/dist/docs/how-to/debug-with-the-chrome-extension.md +57 -0
- package/dist/docs/how-to/define-a-page-layout.md +39 -0
- package/dist/docs/how-to/fill-and-publish-a-page.md +50 -0
- package/dist/docs/{gtm-template.md → how-to/install-the-gtm-template.md} +9 -3
- package/dist/docs/how-to/install-the-sdk.md +68 -0
- package/dist/docs/how-to/install-the-vite-plugin.md +56 -0
- package/dist/docs/how-to/invite-and-remove-members.md +34 -0
- package/dist/docs/how-to/preview-a-workspace.md +28 -0
- package/dist/docs/how-to/publish-a-workspace.md +30 -0
- package/dist/docs/how-to/read-a-feature-flag.md +101 -0
- package/dist/docs/how-to/register-a-component.md +55 -0
- package/dist/docs/how-to/register-an-action-handler.md +67 -0
- package/dist/docs/how-to/render-a-step-form.md +132 -0
- package/dist/docs/how-to/render-an-unpublished-preview.md +41 -0
- package/dist/docs/how-to/reuse-a-section.md +37 -0
- package/dist/docs/how-to/reuse-a-step-field-or-action.md +28 -0
- package/dist/docs/how-to/roll-back-a-published-version.md +26 -0
- package/dist/docs/how-to/run-an-ab-test.md +49 -0
- package/dist/docs/how-to/run-code-on-a-form-submission.md +125 -0
- package/dist/docs/how-to/server-render-a-page.md +81 -0
- package/dist/docs/how-to/set-a-content-security-policy.md +32 -0
- package/dist/docs/how-to/set-up-mfa.md +69 -0
- package/dist/docs/how-to/upload-and-use-an-asset.mdx +73 -0
- package/dist/docs/how-to/validate-a-field.md +52 -0
- package/dist/docs/how-to/write-a-condition.md +45 -0
- package/dist/docs/how-to/write-a-predicate.md +60 -0
- package/dist/docs/index.md +41 -70
- package/dist/docs/reference/dashboard/actions.mdx +53 -0
- package/dist/docs/{api-keys.mdx → reference/dashboard/api-keys.mdx} +7 -15
- package/dist/docs/reference/dashboard/conditions.mdx +42 -0
- package/dist/docs/reference/dashboard/content/asset-library.mdx +63 -0
- package/dist/docs/{content → reference/dashboard/content}/content-entries.mdx +11 -3
- package/dist/docs/{content → reference/dashboard/content}/layouts.mdx +11 -35
- package/dist/docs/reference/dashboard/content/pages.mdx +35 -0
- package/dist/docs/reference/dashboard/content/sections.mdx +28 -0
- package/dist/docs/{experiences.mdx → reference/dashboard/experiences.mdx} +9 -16
- package/dist/docs/{features.mdx → reference/dashboard/features.mdx} +26 -41
- package/dist/docs/{fields.mdx → reference/dashboard/fields.mdx} +26 -20
- package/dist/docs/{flow-builder/overview.mdx → reference/dashboard/flow-builder/canvas.mdx} +8 -13
- package/dist/docs/{flow-builder → reference/dashboard/flow-builder}/condition-builder.md +5 -13
- package/dist/docs/{flow-builder → reference/dashboard/flow-builder}/keyboard-shortcuts.md +7 -1
- package/dist/docs/{flow-builder → reference/dashboard/flow-builder}/nodes.md +10 -3
- package/dist/docs/reference/dashboard/projects.mdx +44 -0
- package/dist/docs/reference/dashboard/reports.mdx +43 -0
- package/dist/docs/reference/dashboard/steps.mdx +37 -0
- package/dist/docs/{team-management.md → reference/dashboard/team-management.md} +5 -22
- package/dist/docs/{workspace-versioning.mdx → reference/dashboard/workspace-versioning.mdx} +6 -10
- package/dist/docs/reference/dashboard/workspaces.mdx +76 -0
- package/dist/docs/{delivery-api → reference/delivery-api}/experience-content.md +11 -4
- package/dist/docs/reference/delivery-api/index.md +45 -0
- package/dist/docs/{delivery-api → reference/delivery-api}/preview-caching-crawling.md +12 -5
- package/dist/docs/{delivery-api → reference/delivery-api}/project-config.md +11 -4
- package/dist/docs/reference/glossary.md +173 -0
- package/dist/docs/reference/management-api/authentication.md +74 -0
- package/dist/docs/{api → reference/management-api}/authorization-and-scopes.md +10 -3
- package/dist/docs/{api → reference/management-api}/error-handling.md +9 -3
- package/dist/docs/{api → reference/management-api}/pagination.md +6 -0
- package/dist/docs/{pickedql → reference/pickedql}/data-sources.md +16 -9
- package/dist/docs/{pickedql → reference/pickedql}/dimensions.md +7 -0
- package/dist/docs/{pickedql → reference/pickedql}/filtering.md +7 -0
- package/dist/docs/reference/pickedql/index.md +18 -0
- package/dist/docs/{pickedql → reference/pickedql}/schema.md +13 -6
- package/dist/docs/{pickedql → reference/pickedql}/virtual-functions.md +7 -0
- package/dist/docs/reference/sdk/actions.md +30 -0
- package/dist/docs/{sdk → reference/sdk}/conditions.md +8 -1
- package/dist/docs/reference/sdk/content-security-policy.md +21 -0
- package/dist/docs/reference/sdk/experiences.md +51 -0
- package/dist/docs/{sdk → reference/sdk}/features.md +30 -117
- package/dist/docs/{sdk → reference/sdk}/fields.md +10 -88
- package/dist/docs/reference/sdk/index.md +68 -0
- package/dist/docs/{sdk → reference/sdk}/plugins/create-experience.md +10 -22
- package/dist/docs/reference/sdk/plugins/dynamic-experiences.md +26 -0
- package/dist/docs/reference/sdk/plugins/index.md +29 -0
- package/dist/docs/{sdk → reference/sdk}/plugins/window-object.md +6 -0
- package/dist/docs/reference/sdk/predicates.md +43 -0
- package/dist/docs/reference/sdk/ssr/index.md +33 -0
- package/dist/docs/{sdk → reference/sdk}/ssr/rendering-and-hydration.md +4 -63
- package/dist/docs/{sdk → reference/sdk}/ssr/serialize.md +6 -33
- package/dist/docs/{sdk → reference/sdk}/ssr/slots-and-placements.md +7 -1
- package/dist/docs/reference/sdk/steps.md +87 -0
- package/dist/docs/reference/tools/chrome-extension.md +16 -0
- package/dist/docs/{image-optimisation-service.md → reference/tools/image-optimisation-service.md} +8 -0
- package/dist/docs/{mcp.md → reference/tools/mcp.md} +5 -45
- package/dist/docs/{vite-plugin.md → reference/tools/vite-plugin.md} +8 -38
- package/dist/docs/{api/index.md → tutorials/first-api-call.md} +27 -15
- package/dist/docs/tutorials/first-experience-in-the-dashboard.mdx +143 -0
- package/dist/docs/tutorials/first-experience.mdx +255 -0
- package/dist/docs/tutorials/first-server-rendered-page.mdx +186 -0
- package/dist/esm/index.js +468 -426
- package/dist/esm/plugins/dynamic-experiences/index.js +2 -2
- package/dist/esm/server/index.js +1 -1
- package/dist/{plugin-DCW-tnjO.cjs → plugin-CSmD1gPl.cjs} +1 -1
- package/dist/{plugin-D2UqFikQ.js → plugin-GOTtoDlC.js} +1 -1
- package/dist/types/entities/feature/feature.d.ts +25 -2
- package/dist/types/entities/feature/feature.d.ts.map +1 -1
- package/dist/types/picked.d.ts +2 -1
- package/dist/types/picked.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/docs/actions.mdx +0 -98
- package/dist/docs/api/authentication.md +0 -403
- package/dist/docs/chrome-extension.md +0 -68
- package/dist/docs/conditions.mdx +0 -72
- package/dist/docs/content/asset-library.mdx +0 -124
- package/dist/docs/content/pages.mdx +0 -82
- package/dist/docs/content/sections.mdx +0 -44
- package/dist/docs/delivery-api/index.md +0 -53
- package/dist/docs/guides/build-a-personalized-page.mdx +0 -161
- package/dist/docs/pickedql/index.md +0 -54
- package/dist/docs/projects.mdx +0 -44
- package/dist/docs/reports.mdx +0 -20
- package/dist/docs/sdk/actions.md +0 -82
- package/dist/docs/sdk/content-security-policy.md +0 -33
- package/dist/docs/sdk/experiences.md +0 -64
- package/dist/docs/sdk/feature-allocation.md +0 -161
- package/dist/docs/sdk/index.md +0 -98
- package/dist/docs/sdk/plugins/dynamic-experiences.md +0 -84
- package/dist/docs/sdk/plugins/index.md +0 -9
- package/dist/docs/sdk/predicates.md +0 -128
- package/dist/docs/sdk/ssr/index.md +0 -79
- package/dist/docs/sdk/steps.md +0 -479
- package/dist/docs/steps.mdx +0 -53
- package/dist/docs/workspaces.mdx +0 -133
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
layout: docs
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# Chrome Extension
|
|
6
|
-
|
|
7
|
-
The extension for the Picked Developer Tools adds a Picked panel to Chrome DevTools.
|
|
8
|
-
Use the panel to check and debug your Picked integration on any page that runs the
|
|
9
|
-
SDK.
|
|
10
|
-
|
|
11
|
-

|
|
12
|
-
|
|
13
|
-
## Installation
|
|
14
|
-
|
|
15
|
-
Install the extension from the
|
|
16
|
-
[Chrome Web Store](https://chromewebstore.google.com/detail/picked-developer-tools/nimmdamgnhlhdpngnalkpmnleebngidh).
|
|
17
|
-
|
|
18
|
-
## Setup
|
|
19
|
-
|
|
20
|
-
Add the `svelteDevtoolsPlugin` to your Picked client. The extension then connects to
|
|
21
|
-
the SDK.
|
|
22
|
-
|
|
23
|
-
```typescript
|
|
24
|
-
import { createPicked } from '@picked/client'
|
|
25
|
-
import { svelteDevtoolsPlugin } from '@picked/svelte/plugins/devtools'
|
|
26
|
-
|
|
27
|
-
const picked = createPicked({
|
|
28
|
-
projectId: 'your-project-id',
|
|
29
|
-
plugins: [
|
|
30
|
-
svelteDevtoolsPlugin(),
|
|
31
|
-
],
|
|
32
|
-
})
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
## Custom Tools
|
|
36
|
-
|
|
37
|
-
You can extend the Developer Tools with your own tools for one project. They appear
|
|
38
|
-
under a **Custom Tools** tab.
|
|
39
|
-
|
|
40
|
-
Each tool is a framework-adapted component. Write it with the same
|
|
41
|
-
`adaptReactComponent` or `adaptSvelteComponent` helper that you already use. You can
|
|
42
|
-
therefore build the tool in the framework of your application.
|
|
43
|
-
|
|
44
|
-
The tool receives the live Picked client, exactly as an experience component does. In
|
|
45
|
-
React, use `usePicked()`. In Svelte, use `getPicked()`. A tool can read client state
|
|
46
|
-
and call client methods.
|
|
47
|
-
|
|
48
|
-
```typescript
|
|
49
|
-
import { createPicked } from '@picked/client'
|
|
50
|
-
import { adaptReactComponent } from '@picked/react'
|
|
51
|
-
import { svelteDevtoolsPlugin } from '@picked/svelte/plugins/devtools'
|
|
52
|
-
import MyTool from './MyTool'
|
|
53
|
-
|
|
54
|
-
const picked = createPicked({
|
|
55
|
-
projectId: 'your-project-id',
|
|
56
|
-
plugins: [
|
|
57
|
-
svelteDevtoolsPlugin({
|
|
58
|
-
customTools: [{ id: 'my-tool', label: 'My Tool', component: adaptReactComponent(MyTool) }],
|
|
59
|
-
}),
|
|
60
|
-
],
|
|
61
|
-
})
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
Svelte renders the Developer Tools shell, so you must also register the framework of
|
|
65
|
-
your tool on the client. A React application needs `reactFrameworkPlugin` for the
|
|
66
|
-
tool, together with the Svelte framework and `svelteDevtoolsPlugin` for the shell.
|
|
67
|
-
When the framework of a tool is not registered, the tab of that tool shows a warning
|
|
68
|
-
and no content.
|
package/dist/docs/conditions.mdx
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
layout: docs
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
import { Screenshot } from '../../components/Screenshot'
|
|
6
|
-
|
|
7
|
-
# Conditions
|
|
8
|
-
|
|
9
|
-
A condition evaluates a rule and splits the flow into two paths. One path is for a
|
|
10
|
-
true result, the other for a false result.
|
|
11
|
-
|
|
12
|
-
<Screenshot
|
|
13
|
-
route="/{orgSlug}/{projectId}/workspaces/{workspaceId}/conditions"
|
|
14
|
-
alt="The conditions list for a workspace on the Picked dashboard"
|
|
15
|
-
/>
|
|
16
|
-
|
|
17
|
-
## Create a condition
|
|
18
|
-
|
|
19
|
-
1. Open your project.
|
|
20
|
-
2. Click **Conditions** in the sidebar.
|
|
21
|
-
3. Click **New Condition**.
|
|
22
|
-
4. Enter a name and a key.
|
|
23
|
-
5. Click **Create**.
|
|
24
|
-
|
|
25
|
-
## Set up a condition
|
|
26
|
-
|
|
27
|
-
**Name**: The name that the dashboard shows. Your visitors do not see it.
|
|
28
|
-
|
|
29
|
-
**Key**: The identifier for your application. You set it once and you cannot change
|
|
30
|
-
it. Your visitors do not see it.
|
|
31
|
-
|
|
32
|
-
## Define the rule
|
|
33
|
-
|
|
34
|
-
Choose a condition node in the flow builder to open its inspector. The **Logic**
|
|
35
|
-
section holds a visual [condition builder](/flow-builder/condition-builder).
|
|
36
|
-
|
|
37
|
-
The condition builder lets you write a rule with AND groups and OR groups. Each rule
|
|
38
|
-
compares a data source against an operator and a value.
|
|
39
|
-
|
|
40
|
-
### Data sources
|
|
41
|
-
|
|
42
|
-
**Responses** — the values that your visitors send through form fields. An example is
|
|
43
|
-
a check of whether a visitor entered one email domain, or chose one option.
|
|
44
|
-
|
|
45
|
-
**Actions** — the actions that ran during the flow.
|
|
46
|
-
|
|
47
|
-
**Feature flags** — the state of each feature flag in your project. Branch on whether
|
|
48
|
-
Picked allocates a visitor to a flag.
|
|
49
|
-
|
|
50
|
-
**Location** — the parts of the current page URL of the visitor. These are the
|
|
51
|
-
pathname, the search parameters, the hostname, and the hash. An example is content
|
|
52
|
-
that changes with the page that the visitor is on.
|
|
53
|
-
|
|
54
|
-
### Example
|
|
55
|
-
|
|
56
|
-
To take a branch on the country that a visitor chooses:
|
|
57
|
-
|
|
58
|
-
1. Add a rule: **Responses → country** equals `US`.
|
|
59
|
-
2. The green path, for a true result, handles a visitor in the US. The red path, for
|
|
60
|
-
a false result, handles every other visitor.
|
|
61
|
-
|
|
62
|
-
To join more than one rule, create an AND group or an OR group and add the rules
|
|
63
|
-
inside it.
|
|
64
|
-
|
|
65
|
-
## Branches
|
|
66
|
-
|
|
67
|
-
In the flow builder, a condition node has two output handles. The green handle, for a
|
|
68
|
-
true result, leads to the path for a match. The red handle, for a false result, leads
|
|
69
|
-
to the other path.
|
|
70
|
-
|
|
71
|
-
You can chain conditions. Connect the output of one condition to the input of another
|
|
72
|
-
to build a decision tree.
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
layout: docs
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
import { Screenshot } from '../../../components/Screenshot'
|
|
6
|
-
|
|
7
|
-
# Asset Library
|
|
8
|
-
|
|
9
|
-
The Asset Library holds the files that your content points at. These are images,
|
|
10
|
-
video, documents, and HTML.
|
|
11
|
-
|
|
12
|
-
<Screenshot
|
|
13
|
-
route="/{orgSlug}/{projectId}/assets"
|
|
14
|
-
alt="The asset library on the Picked dashboard"
|
|
15
|
-
/>
|
|
16
|
-
|
|
17
|
-
## Upload and control your assets
|
|
18
|
-
|
|
19
|
-
The Asset Library is a project-level store. Upload a file, then point at it from any
|
|
20
|
-
Content Entry in the project.
|
|
21
|
-
|
|
22
|
-
- **Size limit:** 50 MB for each file.
|
|
23
|
-
- **Allowed types:** an image in PNG, JPEG, WebP, AVIF, GIF, or SVG. A video in MP4
|
|
24
|
-
or WebM. A common document format. HTML, as `text/html`.
|
|
25
|
-
|
|
26
|
-
Picked rejects a file of another type. It also rejects a file above the size limit.
|
|
27
|
-
|
|
28
|
-
## Reference an asset from a field
|
|
29
|
-
|
|
30
|
-
Two field types point at an item in the library:
|
|
31
|
-
|
|
32
|
-
- An **Asset** field points at an image, a video, or a document.
|
|
33
|
-
- An **HTML asset** field takes a `.html` file from your library.
|
|
34
|
-
|
|
35
|
-
Add the field to a [layout](/content/layouts). Then choose an item from the library
|
|
36
|
-
when you fill in the [Content Entry](/content/content-entries).
|
|
37
|
-
|
|
38
|
-
## Pick an asset
|
|
39
|
-
|
|
40
|
-
Every Asset field opens the same picker. Click **Choose file** to open it. On a field
|
|
41
|
-
with a value already, click **Replace**. The modal has two tabs: **Library**, where
|
|
42
|
-
you browse the assets that are there, and **Upload**, where you add a new file.
|
|
43
|
-
|
|
44
|
-
<Screenshot
|
|
45
|
-
route="/{orgSlug}/{projectId}/design-systems/new"
|
|
46
|
-
wait='button:has-text("Upload file")'
|
|
47
|
-
click='button:has-text("Upload file")'
|
|
48
|
-
selector="[role=dialog]"
|
|
49
|
-
alt="The asset picker modal on the Picked dashboard, with the Library tab, its search box, its type filter, and its Sort by menu"
|
|
50
|
-
renderWidth={1072}
|
|
51
|
-
renderHeight={790}
|
|
52
|
-
/>
|
|
53
|
-
|
|
54
|
-
### Search, filter, and sort
|
|
55
|
-
|
|
56
|
-
The Library tab has three controls that make a large asset list smaller. The server
|
|
57
|
-
applies each one across the whole library, and not only across the assets that it
|
|
58
|
-
loaded already:
|
|
59
|
-
|
|
60
|
-
- **Search:** narrows the list by file name while you type.
|
|
61
|
-
- **Type filter:** narrows the list to one media type. The choices are All types,
|
|
62
|
-
Images, Video, Audio, Documents, and Archive files.
|
|
63
|
-
- **Sort by:** orders the list by the Name or by the Date uploaded, each one
|
|
64
|
-
ascending or descending.
|
|
65
|
-
|
|
66
|
-
:::note
|
|
67
|
-
The results come one page at a time. Click **Load more** at the bottom of the list to
|
|
68
|
-
read the next page.
|
|
69
|
-
:::
|
|
70
|
-
|
|
71
|
-
### Choose one asset or several
|
|
72
|
-
|
|
73
|
-
The picker changes with the number of assets that the field takes:
|
|
74
|
-
|
|
75
|
-
- A field that holds one asset shows a **radio** indicator next to each row. The
|
|
76
|
-
Asset field of a layout and the guidance file of a design system both do this. A
|
|
77
|
-
new choice replaces the current asset.
|
|
78
|
-
- A place that takes several assets at once shows a **checkbox** indicator. The
|
|
79
|
-
detail panel then also shows a count of what you chose. The Files tab of a
|
|
80
|
-
workbench does this.
|
|
81
|
-
|
|
82
|
-
The detail panel on the right shows the kind, the dimensions, the size, and the
|
|
83
|
-
upload date of the asset that you chose.
|
|
84
|
-
|
|
85
|
-
### Open an asset in a new tab
|
|
86
|
-
|
|
87
|
-
Each row has an **Open in new tab** control, and so does the detail panel of the
|
|
88
|
-
asset that you chose. It links to the full detail page of the asset, and your choice
|
|
89
|
-
in the picker stays as it is.
|
|
90
|
-
|
|
91
|
-
:::tip
|
|
92
|
-
Use this to check an asset again before you choose it. You can see the full-size
|
|
93
|
-
preview and every version that somebody uploaded.
|
|
94
|
-
:::
|
|
95
|
-
|
|
96
|
-
## HTML assets
|
|
97
|
-
|
|
98
|
-
Upload a `.html` file and point at it from an **HTML asset** field. Picked then scans
|
|
99
|
-
the file. The scan is advisory: it helps you, and it never stops you. It
|
|
100
|
-
reports findings about speed, about search rank, and about accessibility, so that you
|
|
101
|
-
can improve the file before you publish it:
|
|
102
|
-
|
|
103
|
-
- **File size:** a warning at 100 KB, and a stronger one at 250 KB.
|
|
104
|
-
- **Inline images:** a note when inline `base64` image data adds about 50 KB or more.
|
|
105
|
-
- **Image dimensions:** an image with no width and no height. Such an image can move
|
|
106
|
-
the content around it while the page loads.
|
|
107
|
-
- **Lazy load:** an image with no `loading="lazy"` attribute.
|
|
108
|
-
- **Link safety:** an external link with `target="_blank"` and no `rel="noopener"`.
|
|
109
|
-
- **Link search rank:** an external link with no `rel="nofollow"`.
|
|
110
|
-
- **Accessibility:** a pass by `axe-core`. It covers alt text, heading order,
|
|
111
|
-
contrast, and more.
|
|
112
|
-
|
|
113
|
-
Every finding is advisory. You can always upload the file as it is.
|
|
114
|
-
|
|
115
|
-
## How assets are served
|
|
116
|
-
|
|
117
|
-
Picked serves each asset from a sandboxed storage origin. That origin is separate
|
|
118
|
-
from the trusted origin of your application. HTML therefore comes from its own
|
|
119
|
-
origin, so a document that you upload runs in isolation and cannot reach the page
|
|
120
|
-
that holds it.
|
|
121
|
-
|
|
122
|
-
An [Experience Content](/delivery-api/experience-content) response can hold an HTML
|
|
123
|
-
asset. The response then carries the content of that asset, and the SDK renders it
|
|
124
|
-
with no second request to storage.
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
layout: docs
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
import { Screenshot } from '../../../components/Screenshot'
|
|
6
|
-
|
|
7
|
-
# Pages
|
|
8
|
-
|
|
9
|
-
A Page is a standalone, server-rendered experience backed by CMS content, built for SEO-critical landing pages.
|
|
10
|
-
|
|
11
|
-
<Screenshot
|
|
12
|
-
route="/{orgSlug}/{projectId}/workspaces/{workspaceId}/experiences"
|
|
13
|
-
alt="The experiences list, where Pages and Flows are created on the Picked dashboard"
|
|
14
|
-
/>
|
|
15
|
-
|
|
16
|
-
## Pages and flows
|
|
17
|
-
|
|
18
|
-
Picked has two experience kinds:
|
|
19
|
-
|
|
20
|
-
| Experience | What it is | Use it for |
|
|
21
|
-
| --- | --- | --- |
|
|
22
|
-
| **Page** | A standalone experience that your server renders from a Content Entry. | A landing page or a campaign page where the search rank matters, and any content that a crawler must see. |
|
|
23
|
-
| **Flow** | An interactive experience of more than one step, which the browser renders. | A quiz, a survey, a product finder, and onboarding of more than one step. |
|
|
24
|
-
|
|
25
|
-
Choose a **Page** when the content must be in the HTML from your server, for a search
|
|
26
|
-
engine and for a social preview. Choose a **Flow** when the value is in the
|
|
27
|
-
interaction, and a browser render is acceptable. See
|
|
28
|
-
[Experiences](/experiences) for the wider picture.
|
|
29
|
-
|
|
30
|
-
## How a page fits together
|
|
31
|
-
|
|
32
|
-
Four pieces back every Page:
|
|
33
|
-
|
|
34
|
-
1. A **Page Layout** defines the shape: the fields a page can hold. See [Page & Step Layouts](/content/layouts).
|
|
35
|
-
2. A **Content Entry** fills that shape with real data. See [Content Entries](/content/content-entries).
|
|
36
|
-
3. A **Page** binds one entry so the SDK can render it.
|
|
37
|
-
4. The **SDK** fetches the entry and renders it on your server. See [Server-Side Rendering](/sdk/ssr).
|
|
38
|
-
|
|
39
|
-
A layout defines the shape, a content entry fills it with data, a Page binds an entry so the SDK can render it. Step Layouts do the same for individual Steps inside a Flow.
|
|
40
|
-
|
|
41
|
-
```
|
|
42
|
-
Author (dashboard) -> Publish -> Delivery API (config + content)
|
|
43
|
-
-> serialize() on server -> Provider seeds client -> ExperienceSlot renders -> hydrate
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
## Create a page
|
|
47
|
-
|
|
48
|
-
1. Open your project.
|
|
49
|
-
2. Choose a workspace.
|
|
50
|
-
3. Click **Experiences** in the sidebar.
|
|
51
|
-
4. Click **New Experience**.
|
|
52
|
-
5. Choose the **Page** type.
|
|
53
|
-
6. Choose a **Page Layout**. The layout sets which fields the page holds.
|
|
54
|
-
7. Click **Create**.
|
|
55
|
-
|
|
56
|
-
A Content Entry is created and linked to the page on its first save, so the page always has somewhere to store its data.
|
|
57
|
-
|
|
58
|
-
## Edit page content
|
|
59
|
-
|
|
60
|
-
The Page editor has two tabs. The **Properties** tab holds the content of the page.
|
|
61
|
-
The **Settings** tab holds its name, its condition, and its layout. Fill in the
|
|
62
|
-
fields on the **Properties** tab. The inspector on the right edits the field that you
|
|
63
|
-
choose, and the preview panel shows the page while it fills in.
|
|
64
|
-
|
|
65
|
-
## Change or remove the layout
|
|
66
|
-
|
|
67
|
-
Use the change-layout control on the **Settings** tab to move the page to another
|
|
68
|
-
Page Layout. When you unlink a layout, Picked separates the Content Entry from the
|
|
69
|
-
page. It deletes no entry, but the page then has no content to render until you
|
|
70
|
-
attach a layout again.
|
|
71
|
-
|
|
72
|
-
## Validate and publish
|
|
73
|
-
|
|
74
|
-
An invalid field shows an error next to it while you edit, so that you can correct it
|
|
75
|
-
before you publish. When the page is valid, publish the workspace to make it live.
|
|
76
|
-
That makes the version that the Delivery API serves to an anonymous reader.
|
|
77
|
-
|
|
78
|
-
## Render a page
|
|
79
|
-
|
|
80
|
-
The SDK renders a published Page on your server. See the
|
|
81
|
-
[Build a Personalized Page](/guides/build-a-personalized-page) guide for the full
|
|
82
|
-
steps, and [Server-Side Rendering](/sdk/ssr) for the SDK reference.
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
layout: docs
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
import { Screenshot } from '../../../components/Screenshot'
|
|
6
|
-
|
|
7
|
-
# Sections
|
|
8
|
-
|
|
9
|
-
Sections are reusable schema fragments you embed inside layouts, so common structures such as a hero or a feature list are defined once.
|
|
10
|
-
|
|
11
|
-
<Screenshot
|
|
12
|
-
route="/{orgSlug}/{projectId}/workspaces/{workspaceId}/blocks"
|
|
13
|
-
alt="The sections list in the schema builder on the Picked dashboard"
|
|
14
|
-
/>
|
|
15
|
-
|
|
16
|
-
## What a section is
|
|
17
|
-
|
|
18
|
-
A Section is a reusable schema fragment with its own **Key**. A
|
|
19
|
-
[layout](/content/layouts) gives its shape to a whole Page or Step. A Section is a
|
|
20
|
-
part that you put into one or more layouts. Define the shape one time, then reuse it
|
|
21
|
-
everywhere.
|
|
22
|
-
|
|
23
|
-
## Create a section
|
|
24
|
-
|
|
25
|
-
1. Open your workspace.
|
|
26
|
-
2. Click **Sections** in the sidebar.
|
|
27
|
-
3. Click **New Section**.
|
|
28
|
-
4. Enter a name and a **Key**. The Key is a unique, stable identifier. Your SDK code
|
|
29
|
-
and your API calls both use it.
|
|
30
|
-
5. Add your fields.
|
|
31
|
-
6. Save.
|
|
32
|
-
|
|
33
|
-
## Use a section in a layout
|
|
34
|
-
|
|
35
|
-
Add a **Section** field to a Page Layout or a Step Layout. Point that field at the
|
|
36
|
-
Section that you want. The layout then carries the fields of the Section at every
|
|
37
|
-
place where that field appears. A Content Entry from the layout fills in the fields
|
|
38
|
-
of the Section in the same way as every other field.
|
|
39
|
-
|
|
40
|
-
## Change a section
|
|
41
|
-
|
|
42
|
-
An edit to a Section does not migrate the entries that use it. After you change a
|
|
43
|
-
Section, check each affected [Content Entry](/content/content-entries) again. Correct
|
|
44
|
-
every field error before you publish.
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
layout: docs
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# Delivery API
|
|
6
|
-
|
|
7
|
-
The Delivery API is a public REST API. It is read-only, and it serves the published
|
|
8
|
-
options of your project together with your page content. It is separate from the
|
|
9
|
-
GraphQL management API.
|
|
10
|
-
|
|
11
|
-
## The Delivery API and the management API
|
|
12
|
-
|
|
13
|
-
Picked has two HTTP APIs. Use the one that fits your work:
|
|
14
|
-
|
|
15
|
-
| | Delivery API | Management API |
|
|
16
|
-
| --- | --- | --- |
|
|
17
|
-
| Style | REST | GraphQL |
|
|
18
|
-
| Access | Public, anonymous | Authenticated |
|
|
19
|
-
| Operations | Read-only | Read and write |
|
|
20
|
-
| Use it to | Serve published options and content to your application | Control your projects, experiences, and content |
|
|
21
|
-
|
|
22
|
-
The [API Reference](/api) covers the management API. This section covers the Delivery
|
|
23
|
-
API.
|
|
24
|
-
|
|
25
|
-
## Base URL and versioning
|
|
26
|
-
|
|
27
|
-
All Delivery API routes are versioned under `/api/v1`:
|
|
28
|
-
|
|
29
|
-
```
|
|
30
|
-
https://api.picked.app/api/v1
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
## Published content and preview content
|
|
34
|
-
|
|
35
|
-
Each endpoint serves two surfaces:
|
|
36
|
-
|
|
37
|
-
- **Published** content is anonymous. Anybody can read your published options and
|
|
38
|
-
your published content.
|
|
39
|
-
- **Preview** content needs a `preview_token` query parameter. With it you can render
|
|
40
|
-
an unpublished draft before you make it live.
|
|
41
|
-
|
|
42
|
-
The management API holds the preview token of a workspace in the `previewToken`
|
|
43
|
-
field. The preview action in the dashboard also makes one for you.
|
|
44
|
-
|
|
45
|
-
## Endpoints
|
|
46
|
-
|
|
47
|
-
| Endpoint | Description |
|
|
48
|
-
| --- | --- |
|
|
49
|
-
| [Project Config](/delivery-api/project-config) | `GET /api/v1/projects/:projectId` returns the published options of the project, with the content link of each step. |
|
|
50
|
-
| [Experience Content](/delivery-api/experience-content) | `GET /api/v1/projects/:projectId/experiences/:id/content` returns the Content Entries of an experience. |
|
|
51
|
-
|
|
52
|
-
Both endpoints share some behaviour. See
|
|
53
|
-
[Preview, cache, and crawlers](/delivery-api/preview-caching-crawling).
|
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
layout: docs
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
import { Screenshot } from '../../../components/Screenshot'
|
|
6
|
-
|
|
7
|
-
# Build a Personalized Page
|
|
8
|
-
|
|
9
|
-
Build a personalized landing page with Picked: model it in the dashboard, publish it, and render it server-side in your app.
|
|
10
|
-
|
|
11
|
-
## What you will build
|
|
12
|
-
|
|
13
|
-
A standalone landing page where the search rank matters. Its content lives in the
|
|
14
|
-
Picked CMS, and your server renders it. You describe the shape of the page one time,
|
|
15
|
-
fill it with content, and publish it. Your server then reads it and renders it in
|
|
16
|
-
React or in Svelte. These are the stages, from the first draft to a hydrated page:
|
|
17
|
-
|
|
18
|
-
```
|
|
19
|
-
Author (dashboard) -> Publish -> Delivery API (config + content)
|
|
20
|
-
-> serialize() on server -> Provider seeds client -> ExperienceSlot renders -> hydrate
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
## Model a page layout
|
|
24
|
-
|
|
25
|
-
A [Page Layout](/content/layouts) defines the fields your page can hold.
|
|
26
|
-
|
|
27
|
-
1. Open your workspace.
|
|
28
|
-
2. Click **Models** in the sidebar.
|
|
29
|
-
3. Click **New Model**.
|
|
30
|
-
4. Choose **Page Layout**.
|
|
31
|
-
5. Enter a name and a **Key**, for example `page-hero`. The Key is a unique, stable
|
|
32
|
-
identifier. Your SDK code and your API calls both use it.
|
|
33
|
-
6. Add three fields: a **Single-line text** field `title`, a **Markdown** field
|
|
34
|
-
`body`, and an **Asset** field `image`.
|
|
35
|
-
7. Save the layout.
|
|
36
|
-
|
|
37
|
-
<Screenshot
|
|
38
|
-
route="/{orgSlug}/{projectId}/workspaces/{workspaceId}/models"
|
|
39
|
-
alt="A page layout in the schema builder on the Picked dashboard"
|
|
40
|
-
/>
|
|
41
|
-
|
|
42
|
-
See [Page & Step Layouts](/content/layouts) for every field type.
|
|
43
|
-
|
|
44
|
-
## Create and fill the page
|
|
45
|
-
|
|
46
|
-
1. Click **Experiences** in the sidebar.
|
|
47
|
-
2. Click **New Experience**.
|
|
48
|
-
3. Choose the **Page** type.
|
|
49
|
-
4. Choose your `page-hero` layout.
|
|
50
|
-
5. On the **Properties** tab, fill in `title`, `body`, and `image`. On the first save,
|
|
51
|
-
Picked creates a [Content Entry](/content/content-entries) and links it to the
|
|
52
|
-
page.
|
|
53
|
-
6. Correct every field error.
|
|
54
|
-
7. Publish the workspace to make the page live.
|
|
55
|
-
|
|
56
|
-
See [Pages](/content/pages) for the full editor reference.
|
|
57
|
-
|
|
58
|
-
## Fetch the config and content
|
|
59
|
-
|
|
60
|
-
Your server reads two things from the [Delivery API](/delivery-api). The first is the
|
|
61
|
-
options of the project, which give the experiences and the steps. The second is the
|
|
62
|
-
content of the experience that matches.
|
|
63
|
-
|
|
64
|
-
```bash
|
|
65
|
-
# 1. The project options: find the steps and their content links.
|
|
66
|
-
curl https://api.picked.app/api/v1/projects/proj_123
|
|
67
|
-
|
|
68
|
-
# 2. The experience content: the entry data of the page.
|
|
69
|
-
curl https://api.picked.app/api/v1/projects/proj_123/experiences/exp_123/content
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
In practice you fetch the config, then let `serialize()` fetch the content for you. See [Project Config](/delivery-api/project-config) and [Experience Content](/delivery-api/experience-content).
|
|
73
|
-
|
|
74
|
-
## Render server-side and hydrate
|
|
75
|
-
|
|
76
|
-
On the server, create a per-request client, call `serialize()` to produce a snapshot, render your app, and embed the snapshot. On the client, seed from the snapshot and hydrate.
|
|
77
|
-
|
|
78
|
-
```ts
|
|
79
|
-
// `server.ts`
|
|
80
|
-
import { createClient } from '@picked/client'
|
|
81
|
-
import { serialize } from '@picked/client/server'
|
|
82
|
-
|
|
83
|
-
const client = createClient(options)
|
|
84
|
-
const snapshot = await serialize(client, {
|
|
85
|
-
projectConfig,
|
|
86
|
-
attributes: { location: { pathname: url.pathname } },
|
|
87
|
-
})
|
|
88
|
-
// Render your app, then embed `snapshot` in the HTML response.
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
Render `<ExperienceSlot name="page" />` inside the provider, and register the component the Page maps to (here, `CMSPage`):
|
|
92
|
-
|
|
93
|
-
:::code-group
|
|
94
|
-
|
|
95
|
-
```tsx [React]
|
|
96
|
-
import type { CreateClientOptions } from '@picked/client'
|
|
97
|
-
import { dynamicExperiencesPlugin } from '@picked/client/plugins/dynamic-experiences'
|
|
98
|
-
import { adaptReactComponent, ExperienceSlot, PickedProvider } from '@picked/react'
|
|
99
|
-
import { reactFrameworkPlugin } from '@picked/react/plugins/framework'
|
|
100
|
-
import { useStepContent } from '@picked/react/hooks'
|
|
101
|
-
|
|
102
|
-
function CMSPage() {
|
|
103
|
-
const content = useStepContent()
|
|
104
|
-
const title = typeof content?.title === 'string' ? content.title : ''
|
|
105
|
-
return <h1>{title}</h1>
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
const options = {
|
|
109
|
-
projectId: 'proj_123',
|
|
110
|
-
components: { CMSPage: adaptReactComponent(CMSPage) },
|
|
111
|
-
plugins: [reactFrameworkPlugin({ components: {} }), dynamicExperiencesPlugin()],
|
|
112
|
-
} satisfies CreateClientOptions
|
|
113
|
-
|
|
114
|
-
export function Page({ snapshot }) {
|
|
115
|
-
return (
|
|
116
|
-
<PickedProvider options={options} snapshot={snapshot}>
|
|
117
|
-
<ExperienceSlot name="page" />
|
|
118
|
-
</PickedProvider>
|
|
119
|
-
)
|
|
120
|
-
}
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
```svelte [Svelte]
|
|
124
|
-
<script lang="ts">
|
|
125
|
-
import type { CreateClientOptions } from '@picked/client'
|
|
126
|
-
import { dynamicExperiencesPlugin } from '@picked/client/plugins/dynamic-experiences'
|
|
127
|
-
import { adaptSvelteComponent, ExperienceSlot, setPickedContext } from '@picked/svelte'
|
|
128
|
-
import { svelteFrameworkPlugin } from '@picked/svelte/plugins/framework'
|
|
129
|
-
import CMSPage from './CMSPage.svelte'
|
|
130
|
-
|
|
131
|
-
const { snapshot } = $props()
|
|
132
|
-
|
|
133
|
-
const options = {
|
|
134
|
-
projectId: 'proj_123',
|
|
135
|
-
components: { CMSPage: adaptSvelteComponent(CMSPage) },
|
|
136
|
-
plugins: [svelteFrameworkPlugin({ components: {} }), dynamicExperiencesPlugin()],
|
|
137
|
-
} satisfies CreateClientOptions
|
|
138
|
-
|
|
139
|
-
setPickedContext({ options, snapshot })
|
|
140
|
-
</script>
|
|
141
|
-
|
|
142
|
-
<ExperienceSlot name="page" />
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
:::
|
|
146
|
-
|
|
147
|
-
The provider seeds synchronously, so the server HTML and the client's first paint match, then the SDK hydrates. See [Server-Side Rendering](/sdk/ssr) for the full reference.
|
|
148
|
-
|
|
149
|
-
## Verify SEO
|
|
150
|
-
|
|
151
|
-
Confirm the page is crawlable end to end:
|
|
152
|
-
|
|
153
|
-
1. Read the response from your server. Use `curl`, or the view-source command of
|
|
154
|
-
your browser.
|
|
155
|
-
2. Check that the HTML holds your `title` and your `body`, and that it is not an
|
|
156
|
-
empty shell.
|
|
157
|
-
3. Check that the content endpoint answers an anonymous request.
|
|
158
|
-
4. Check that it returns your entry data.
|
|
159
|
-
|
|
160
|
-
A crawler can read a published Delivery API response. A preview URL is disallowed.
|
|
161
|
-
See [Preview, cache, and crawlers](/delivery-api/preview-caching-crawling).
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
layout: docs
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# PickedQL
|
|
6
|
-
|
|
7
|
-
PickedQL is a SQL query language for your Picked analytics data. Write short SQL with
|
|
8
|
-
a virtual table and a virtual function. PickedQL expands them into a full query, and
|
|
9
|
-
it adds the joins and the A/B test aggregations for you.
|
|
10
|
-
|
|
11
|
-
## Quick start
|
|
12
|
-
|
|
13
|
-
```sql
|
|
14
|
-
-- How many users are in the control group, and how many in the variant group?
|
|
15
|
-
SELECT control_users(), variant_users()
|
|
16
|
-
FROM metrics
|
|
17
|
-
WHERE project_id = 'your-project-id'
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
PickedQL maps each table and adds each dimension join for you. You write short SQL
|
|
21
|
-
that a person can read, and PickedQL does the rest.
|
|
22
|
-
|
|
23
|
-
## How PickedQL works
|
|
24
|
-
|
|
25
|
-
1. **Virtual table expansion**: a table name such as `metrics` maps to the data
|
|
26
|
-
tables below it.
|
|
27
|
-
2. **Virtual function expansion**: a short function such as `control_users()` expands
|
|
28
|
-
to a full aggregate expression.
|
|
29
|
-
3. **Automatic dimension joins**: PickedQL adds a `LEFT JOIN` when you point at a
|
|
30
|
-
dimension column, such as `device_category` or `country_code`. You write no join.
|
|
31
|
-
4. **Tenant isolation**: every query must hold a tenant filter in the `WHERE` clause.
|
|
32
|
-
That filter is `project_id` for most tables. The `projects` table uses `id`
|
|
33
|
-
instead, because the `id` of the row is the project ID. PickedQL reads the filter
|
|
34
|
-
and checks that you have permission for that project.
|
|
35
|
-
5. **SQL passthrough**: standard SQL works next to a virtual function. This includes
|
|
36
|
-
`CASE WHEN`, a window function, and a subquery.
|
|
37
|
-
|
|
38
|
-
## Best practices
|
|
39
|
-
|
|
40
|
-
- **Use `metrics` for a dashboard**: data that PickedQL aggregates first is much
|
|
41
|
-
faster than raw events for a standard report.
|
|
42
|
-
- **Use `events` to go deeper**: raw event data lets you build any breakdown or
|
|
43
|
-
funnel that you want.
|
|
44
|
-
- **Use `experience_journey` for a sankey chart or a funnel chart**: one line of SQL
|
|
45
|
-
returns `source, target, users`. PickedQL builds the eight common table expressions
|
|
46
|
-
for you. Those remove the duplicates, rank the top paths, and call `lagInFrame`.
|
|
47
|
-
Pass your parameters in the `WHERE` clause.
|
|
48
|
-
- **Write no JOIN**: PickedQL adds each one when you point at a dimension column.
|
|
49
|
-
- **Group by any dimension**: add a dimension column to `SELECT` and to `GROUP BY`.
|
|
50
|
-
PickedQL adds the join that it needs.
|
|
51
|
-
- **Read the reference tables for no cost**: use `step_title`, `experience_title`, and
|
|
52
|
-
`project_name` directly in an `events` query. PickedQL joins the `steps`,
|
|
53
|
-
`experiences`, and `projects` reference tables for you.
|
|
54
|
-
|