@picked/client 0.0.101-next.1 → 0.0.101-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/README.md +34 -158
- package/dist/{api-DThEBKPu.cjs → api-9o_emCM5.cjs} +1 -1
- package/dist/{api-DcXndm41.js → api-BbQt8aW3.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/esm/index.js +2 -2
- package/dist/esm/plugins/dynamic-experiences/index.js +2 -2
- package/dist/esm/server/index.js +2 -2
- package/dist/{plugin-DA34qpbe.cjs → plugin-I8_6ncy_.cjs} +1 -1
- package/dist/{plugin-BZPx7WhX.js → plugin-uZJ45vK6.js} +2 -2
- package/dist/{preview-unavailable-sDBBJFrE.cjs → preview-unavailable-BUNxTYLe.cjs} +1 -1
- package/dist/{preview-unavailable-Bg8UuQeR.js → preview-unavailable-BYFD2a58.js} +1 -1
- package/dist/{provider-BkN7A93w.cjs → provider-Bzi_Kb-n.cjs} +1 -1
- package/dist/{provider-DRNHPacW.js → provider-CQKp0iUJ.js} +1 -1
- package/package.json +5 -5
- package/dist/docs/_root.css +0 -101
- package/dist/docs/explanation/conditions-and-the-logic-engine.md +0 -94
- package/dist/docs/explanation/content-references.md +0 -99
- package/dist/docs/explanation/feature-flag-allocation.md +0 -218
- package/dist/docs/explanation/how-picked-works.md +0 -124
- package/dist/docs/explanation/how-pickedql-works.md +0 -76
- package/dist/docs/explanation/pages-and-flows.md +0 -64
- package/dist/docs/explanation/the-content-model.md +0 -87
- package/dist/docs/explanation/the-two-apis.md +0 -68
- package/dist/docs/explanation/why-server-side-rendering.md +0 -76
- package/dist/docs/explanation/workspaces-and-versions.md +0 -71
- package/dist/docs/how-to/add-a-step-field-or-action.md +0 -43
- package/dist/docs/how-to/analytics/index.md +0 -316
- package/dist/docs/how-to/archive-or-delete-a-workspace.md +0 -46
- package/dist/docs/how-to/authenticate-the-cli.md +0 -101
- package/dist/docs/how-to/authenticate-with-a-magic-link.md +0 -47
- package/dist/docs/how-to/authenticate-with-a-password.md +0 -59
- package/dist/docs/how-to/authenticate-with-an-api-key.md +0 -51
- package/dist/docs/how-to/authenticate-with-oauth.md +0 -40
- package/dist/docs/how-to/build-a-flow.md +0 -93
- package/dist/docs/how-to/call-an-external-api-from-a-workflow.md +0 -102
- package/dist/docs/how-to/connect-the-mcp-server.md +0 -46
- package/dist/docs/how-to/create-a-content-entry.md +0 -48
- package/dist/docs/how-to/create-a-project.md +0 -29
- package/dist/docs/how-to/create-an-experience.md +0 -42
- package/dist/docs/how-to/create-and-revoke-an-api-key.md +0 -42
- package/dist/docs/how-to/debug-with-the-chrome-extension.md +0 -57
- package/dist/docs/how-to/define-a-page-layout.md +0 -46
- package/dist/docs/how-to/fill-and-publish-a-page.md +0 -66
- package/dist/docs/how-to/install-the-gtm-template.md +0 -84
- package/dist/docs/how-to/install-the-sdk.md +0 -93
- package/dist/docs/how-to/install-the-vite-plugin.md +0 -69
- package/dist/docs/how-to/invite-and-remove-members.md +0 -35
- package/dist/docs/how-to/point-one-entry-at-another.md +0 -61
- package/dist/docs/how-to/preview-a-workspace.md +0 -28
- package/dist/docs/how-to/publish-a-workspace.md +0 -30
- package/dist/docs/how-to/read-a-feature-flag.md +0 -113
- package/dist/docs/how-to/read-a-referenced-entry.md +0 -109
- package/dist/docs/how-to/register-a-component.md +0 -55
- package/dist/docs/how-to/register-an-action-handler.md +0 -85
- package/dist/docs/how-to/register-an-api-that-uses-oauth2.md +0 -107
- package/dist/docs/how-to/render-a-step-form.md +0 -131
- package/dist/docs/how-to/render-an-unpublished-preview.md +0 -41
- package/dist/docs/how-to/retry-a-failed-call-with-a-loop.md +0 -81
- package/dist/docs/how-to/reuse-a-section.md +0 -53
- package/dist/docs/how-to/reuse-a-step-field-or-action.md +0 -28
- package/dist/docs/how-to/roll-back-a-published-version.md +0 -26
- package/dist/docs/how-to/run-an-ab-test.md +0 -49
- package/dist/docs/how-to/run-code-on-a-form-submission.md +0 -125
- package/dist/docs/how-to/server-render-a-page.md +0 -81
- package/dist/docs/how-to/set-a-content-security-policy.md +0 -32
- package/dist/docs/how-to/set-up-mfa.md +0 -113
- package/dist/docs/how-to/switch-workspaces.md +0 -122
- package/dist/docs/how-to/upload-and-use-an-asset.mdx +0 -73
- package/dist/docs/how-to/validate-a-field.md +0 -52
- package/dist/docs/how-to/wait-for-an-action-response.md +0 -182
- package/dist/docs/how-to/write-a-condition.md +0 -45
- package/dist/docs/how-to/write-a-predicate.md +0 -60
- package/dist/docs/index.md +0 -59
- package/dist/docs/reference/dashboard/actions.mdx +0 -56
- package/dist/docs/reference/dashboard/api-keys.mdx +0 -38
- package/dist/docs/reference/dashboard/conditions.mdx +0 -42
- package/dist/docs/reference/dashboard/content/asset-library.mdx +0 -63
- package/dist/docs/reference/dashboard/content/blocks.mdx +0 -57
- package/dist/docs/reference/dashboard/content/content-entries.mdx +0 -95
- package/dist/docs/reference/dashboard/content/models.mdx +0 -108
- package/dist/docs/reference/dashboard/content/pages.mdx +0 -61
- package/dist/docs/reference/dashboard/experiences.mdx +0 -51
- package/dist/docs/reference/dashboard/external-apis.md +0 -169
- package/dist/docs/reference/dashboard/features.mdx +0 -154
- package/dist/docs/reference/dashboard/fields.mdx +0 -106
- package/dist/docs/reference/dashboard/flow-builder/canvas.mdx +0 -58
- package/dist/docs/reference/dashboard/flow-builder/condition-builder.md +0 -57
- package/dist/docs/reference/dashboard/flow-builder/keyboard-shortcuts.md +0 -72
- package/dist/docs/reference/dashboard/flow-builder/nodes.md +0 -63
- package/dist/docs/reference/dashboard/labels.md +0 -321
- package/dist/docs/reference/dashboard/lead-search.md +0 -224
- package/dist/docs/reference/dashboard/projects.mdx +0 -44
- package/dist/docs/reference/dashboard/reports.mdx +0 -43
- package/dist/docs/reference/dashboard/steps.mdx +0 -37
- package/dist/docs/reference/dashboard/team-management.md +0 -29
- package/dist/docs/reference/dashboard/workflow-runs.md +0 -142
- package/dist/docs/reference/dashboard/workflow-templates.md +0 -182
- package/dist/docs/reference/dashboard/workflow-test-runs.md +0 -77
- package/dist/docs/reference/dashboard/workspace-versioning.mdx +0 -30
- package/dist/docs/reference/dashboard/workspaces.mdx +0 -76
- package/dist/docs/reference/delivery-api/experience-content.md +0 -152
- package/dist/docs/reference/delivery-api/index.md +0 -45
- package/dist/docs/reference/delivery-api/preview-caching-crawling.md +0 -79
- package/dist/docs/reference/delivery-api/project-config.md +0 -65
- package/dist/docs/reference/delivery-api/workspace-schema.md +0 -107
- package/dist/docs/reference/glossary.md +0 -201
- package/dist/docs/reference/management-api/authentication.md +0 -87
- package/dist/docs/reference/management-api/authorization-and-scopes.md +0 -291
- package/dist/docs/reference/management-api/error-handling.md +0 -232
- package/dist/docs/reference/management-api/pagination.md +0 -192
- package/dist/docs/reference/pickedql/data-sources.md +0 -174
- package/dist/docs/reference/pickedql/dimensions.md +0 -103
- package/dist/docs/reference/pickedql/filtering.md +0 -64
- package/dist/docs/reference/pickedql/index.md +0 -18
- package/dist/docs/reference/pickedql/schema.md +0 -172
- package/dist/docs/reference/pickedql/virtual-functions.md +0 -248
- package/dist/docs/reference/sdk/actions.md +0 -154
- package/dist/docs/reference/sdk/analytics-events.md +0 -453
- package/dist/docs/reference/sdk/conditions.md +0 -147
- package/dist/docs/reference/sdk/content-security-policy.md +0 -21
- package/dist/docs/reference/sdk/content.md +0 -253
- package/dist/docs/reference/sdk/experiences.md +0 -51
- package/dist/docs/reference/sdk/features.md +0 -256
- package/dist/docs/reference/sdk/fields.md +0 -255
- package/dist/docs/reference/sdk/index.md +0 -68
- package/dist/docs/reference/sdk/plugins/create-experience.md +0 -123
- package/dist/docs/reference/sdk/plugins/dynamic-experiences.md +0 -74
- package/dist/docs/reference/sdk/plugins/index.md +0 -29
- package/dist/docs/reference/sdk/plugins/window-object.md +0 -25
- package/dist/docs/reference/sdk/predicates.md +0 -43
- package/dist/docs/reference/sdk/ssr/index.md +0 -33
- package/dist/docs/reference/sdk/ssr/rendering-and-hydration.md +0 -103
- package/dist/docs/reference/sdk/ssr/serialize.md +0 -80
- package/dist/docs/reference/sdk/ssr/slots-and-placements.md +0 -113
- package/dist/docs/reference/sdk/steps.md +0 -86
- package/dist/docs/reference/sdk/type-generation.md +0 -265
- package/dist/docs/reference/tools/chrome-extension.md +0 -16
- package/dist/docs/reference/tools/cli.md +0 -292
- package/dist/docs/reference/tools/image-optimisation-service.md +0 -104
- package/dist/docs/reference/tools/mcp.md +0 -136
- package/dist/docs/reference/tools/vite-plugin.md +0 -163
- package/dist/docs/tutorials/first-api-call.md +0 -235
- package/dist/docs/tutorials/first-experience-in-the-dashboard.mdx +0 -143
- package/dist/docs/tutorials/first-experience.mdx +0 -254
- package/dist/docs/tutorials/first-server-rendered-page.mdx +0 -186
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: how-to
|
|
3
|
-
layout: docs
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# How to register an API that uses OAuth2
|
|
7
|
-
|
|
8
|
-
This guide shows you how to let a workflow call an API whose access tokens expire, such as
|
|
9
|
-
Zoho CRM. You need a client ID and a client secret from the provider. For the refresh token
|
|
10
|
-
grant, you also need a refresh token.
|
|
11
|
-
|
|
12
|
-
Picked keeps the credential, gets an access token from the provider, and sends the token
|
|
13
|
-
with each request. Picked gets a new token before the old token expires.
|
|
14
|
-
|
|
15
|
-
## 1. Make a refresh token in Zoho
|
|
16
|
-
|
|
17
|
-
Do this step for Zoho CRM only. For another provider, get the credential from the
|
|
18
|
-
provider's documentation.
|
|
19
|
-
|
|
20
|
-
1. Open the Zoho API console for the region of your Zoho account.
|
|
21
|
-
2. Add a client of the type `Self Client`.
|
|
22
|
-
3. Make a grant code with the scopes that the workflow needs, such as
|
|
23
|
-
`ZohoCRM.modules.leads.CREATE`.
|
|
24
|
-
4. Send a `POST` request to the token URL of your region, such as
|
|
25
|
-
`https://accounts.zoho.com.au/oauth/v2/token`. Put the parameters in the form body, not
|
|
26
|
-
in the URL. The parameters are `grant_type=authorization_code`, `client_id`,
|
|
27
|
-
`client_secret`, and `code` with the grant code. The grant code expires soon, so do this
|
|
28
|
-
step immediately.
|
|
29
|
-
5. Keep the `refresh_token` from the answer.
|
|
30
|
-
|
|
31
|
-
:::warning
|
|
32
|
-
Make the refresh token as a Zoho user that only Picked uses. Zoho keeps 20 refresh tokens
|
|
33
|
-
for each user and client. When you make one more, Zoho stops the oldest refresh token. That
|
|
34
|
-
token can be the token that Picked uses.
|
|
35
|
-
:::
|
|
36
|
-
|
|
37
|
-
## 2. Register the external API
|
|
38
|
-
|
|
39
|
-
1. Open **Integrations**.
|
|
40
|
-
2. Choose **Configure external APIs**.
|
|
41
|
-
3. Choose **New external API**.
|
|
42
|
-
4. For Zoho CRM, set **Preset** to the region of your Zoho account. The preset sets the
|
|
43
|
-
**Display name**, the **Origin**, the **Credential** and the settings of the OAuth2
|
|
44
|
-
credential. Then go to step 10. If **Preset** does not show your region, do steps 5 to 9.
|
|
45
|
-
5. Enter a **Display name**.
|
|
46
|
-
6. Enter the **Origin**, such as `https://www.zohoapis.com.au`.
|
|
47
|
-
7. Set **Credential** to **OAuth2 credential**.
|
|
48
|
-
8. Enter the **Token URL** from the provider's documentation. Do not put a secret in the
|
|
49
|
-
token URL.
|
|
50
|
-
9. Set the **Grant**, the **Client authentication** and the **Header scheme** from the
|
|
51
|
-
provider's documentation.
|
|
52
|
-
10. Enter the **Client ID**.
|
|
53
|
-
11. Enter the **Client secret**.
|
|
54
|
-
12. For the refresh token grant, enter the **Refresh token**.
|
|
55
|
-
13. Choose **Register external API**.
|
|
56
|
-
|
|
57
|
-
The client secret and the refresh token are write-only. After you save them, Picked shows
|
|
58
|
-
only that they are stored.
|
|
59
|
-
|
|
60
|
-
## 3. Add a credential to an external API that you registered
|
|
61
|
-
|
|
62
|
-
1. Open the external API.
|
|
63
|
-
2. Choose **Use an OAuth2 credential**.
|
|
64
|
-
3. For Zoho CRM, set **Preset** to the region of your Zoho account. For another provider,
|
|
65
|
-
do steps 8 and 9 of section 2.
|
|
66
|
-
4. Do steps 10 to 12 of section 2.
|
|
67
|
-
5. Choose **Save credential**.
|
|
68
|
-
|
|
69
|
-
The credential replaces the authorization header of the external API.
|
|
70
|
-
|
|
71
|
-
## 4. Refresh only for an expired token
|
|
72
|
-
|
|
73
|
-
Some APIs answer 401 for an error that a new token does not correct. To get a new token only
|
|
74
|
-
for an expired token:
|
|
75
|
-
|
|
76
|
-
1. Open the external API.
|
|
77
|
-
2. Choose **Edit OAuth2 credential**.
|
|
78
|
-
3. In **401 rule: response body path**, enter the path of the error code in the 401 answer,
|
|
79
|
-
such as `code`. Put a dot between the parts of the path, for example `data.0.code`.
|
|
80
|
-
4. In **401 rule: values**, enter the error codes that show an expired token, such as
|
|
81
|
-
`INVALID_TOKEN`.
|
|
82
|
-
5. Choose **Save credential**.
|
|
83
|
-
|
|
84
|
-
The Zoho CRM preset sets this rule for you.
|
|
85
|
-
|
|
86
|
-
## 5. Replace a refresh token that the provider rejected
|
|
87
|
-
|
|
88
|
-
When the provider rejects the credential, the external API page shows the reason in **Last
|
|
89
|
-
refresh failure**. Each call fails with `credential_rejected` until you correct the
|
|
90
|
-
credential.
|
|
91
|
-
|
|
92
|
-
1. Make a new refresh token.
|
|
93
|
-
2. Open the external API.
|
|
94
|
-
3. Choose **Edit OAuth2 credential**.
|
|
95
|
-
4. Enter the new **Refresh token**.
|
|
96
|
-
5. Choose **Save credential**.
|
|
97
|
-
|
|
98
|
-
Leave the **Client secret** empty to keep the stored client secret. If you change the
|
|
99
|
-
**Token URL**, the **Client ID** or the **Client authentication**, enter the client secret
|
|
100
|
-
and the refresh token again.
|
|
101
|
-
|
|
102
|
-
## Related
|
|
103
|
-
|
|
104
|
-
- [External APIs](/reference/dashboard/external-apis#oauth2-credential) — every setting of
|
|
105
|
-
an OAuth2 credential, and when Picked gets a new token.
|
|
106
|
-
- [How to call an external API from a workflow](/how-to/call-an-external-api-from-a-workflow)
|
|
107
|
-
— the node that sends the request.
|
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: how-to
|
|
3
|
-
layout: docs
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# How to render a step form
|
|
7
|
-
|
|
8
|
-
This guide shows you how to render the fields of the active step and let a visitor submit
|
|
9
|
-
them.
|
|
10
|
-
|
|
11
|
-
## 1. Put the steps in a router
|
|
12
|
-
|
|
13
|
-
`StepRouter` watches the step state and activates the `Step` whose `id` matches.
|
|
14
|
-
|
|
15
|
-
:::code-group
|
|
16
|
-
|
|
17
|
-
```tsx [React]
|
|
18
|
-
import { StepRouter, Step } from '@picked/react/router'
|
|
19
|
-
|
|
20
|
-
function MyExperience() {
|
|
21
|
-
return (
|
|
22
|
-
<StepRouter>
|
|
23
|
-
<Step id="welcome">
|
|
24
|
-
<WelcomeScreen />
|
|
25
|
-
</Step>
|
|
26
|
-
<Step id="contact">
|
|
27
|
-
<ContactForm />
|
|
28
|
-
</Step>
|
|
29
|
-
</StepRouter>
|
|
30
|
-
)
|
|
31
|
-
}
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
```svelte [Svelte]
|
|
35
|
-
<script lang="ts">
|
|
36
|
-
import { StepRouter, Step } from '@picked/svelte/router'
|
|
37
|
-
</script>
|
|
38
|
-
|
|
39
|
-
<StepRouter>
|
|
40
|
-
<Step id="welcome">
|
|
41
|
-
<WelcomeScreen />
|
|
42
|
-
</Step>
|
|
43
|
-
<Step id="contact">
|
|
44
|
-
<ContactForm />
|
|
45
|
-
</Step>
|
|
46
|
-
</StepRouter>
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
:::
|
|
50
|
-
|
|
51
|
-
:::note
|
|
52
|
-
A router must hold every Step, even when there is only one Step.
|
|
53
|
-
:::
|
|
54
|
-
|
|
55
|
-
## 2. Render the fields
|
|
56
|
-
|
|
57
|
-
Bind `form.props` to your `<form>` element and map over the fields.
|
|
58
|
-
|
|
59
|
-
:::code-group
|
|
60
|
-
|
|
61
|
-
```tsx [React]
|
|
62
|
-
import { useStep, useStoreGlobal } from '@picked/react/hooks'
|
|
63
|
-
|
|
64
|
-
function StepForm() {
|
|
65
|
-
const { fields, form } = useStep()
|
|
66
|
-
const currentFields = useStoreGlobal(fields)
|
|
67
|
-
const isSubmitting = useStoreGlobal(form.submitting)
|
|
68
|
-
|
|
69
|
-
return (
|
|
70
|
-
<form {...form.props}>
|
|
71
|
-
{currentFields.map((field) => (
|
|
72
|
-
<div key={field.id}>
|
|
73
|
-
<label htmlFor={field.id}>{field.label}</label>
|
|
74
|
-
<input
|
|
75
|
-
id={field.id}
|
|
76
|
-
name={field.id}
|
|
77
|
-
value={field.value ?? ''}
|
|
78
|
-
onChange={field.onChange}
|
|
79
|
-
onBlur={field.onBlur}
|
|
80
|
-
/>
|
|
81
|
-
{field.error && field.touched && <p className="error">{field.error.userMessage}</p>}
|
|
82
|
-
</div>
|
|
83
|
-
))}
|
|
84
|
-
<button type="submit" disabled={isSubmitting}>Continue</button>
|
|
85
|
-
</form>
|
|
86
|
-
)
|
|
87
|
-
}
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
```svelte [Svelte]
|
|
91
|
-
<script lang="ts">
|
|
92
|
-
import { getStep } from '@picked/svelte/hooks'
|
|
93
|
-
|
|
94
|
-
const { fields, form } = getStep()
|
|
95
|
-
const isSubmitting = form.submitting
|
|
96
|
-
</script>
|
|
97
|
-
|
|
98
|
-
<form {...form.props}>
|
|
99
|
-
{#each $fields as field}
|
|
100
|
-
<div>
|
|
101
|
-
<label for={field.id}>{field.label}</label>
|
|
102
|
-
<input
|
|
103
|
-
id={field.id}
|
|
104
|
-
name={field.id}
|
|
105
|
-
value={field.value ?? ''}
|
|
106
|
-
onchange={field.onChange}
|
|
107
|
-
onblur={field.onBlur}
|
|
108
|
-
/>
|
|
109
|
-
{#if field.error && field.touched}
|
|
110
|
-
<p class="error">{field.error.userMessage}</p>
|
|
111
|
-
{/if}
|
|
112
|
-
</div>
|
|
113
|
-
{/each}
|
|
114
|
-
<button type="submit" disabled={$isSubmitting}>Continue</button>
|
|
115
|
-
</form>
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
:::
|
|
119
|
-
|
|
120
|
-
The SDK checks a field on blur, and not while the visitor types.
|
|
121
|
-
|
|
122
|
-
## 3. Load a large step lazily
|
|
123
|
-
|
|
124
|
-
Pass a dynamic import to the `component` prop of `<Step>`. The SDK does not load the
|
|
125
|
-
content until that step becomes active.
|
|
126
|
-
|
|
127
|
-
## Related
|
|
128
|
-
|
|
129
|
-
- [How to run code on a form submission](/how-to/run-code-on-a-form-submission) — the
|
|
130
|
-
callbacks.
|
|
131
|
-
- [SDK steps](/reference/sdk/steps) — the `StepContext` shape.
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: how-to
|
|
3
|
-
layout: docs
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# How to render an unpublished preview
|
|
7
|
-
|
|
8
|
-
This guide shows you how to render draft content on your server. Your server cannot read
|
|
9
|
-
the query string of the browser, so you must pass the token yourself.
|
|
10
|
-
|
|
11
|
-
## 1. Get the token
|
|
12
|
-
|
|
13
|
-
The management API holds the preview token of a workspace in the `previewToken` field. The
|
|
14
|
-
preview action in the dashboard also makes one for you.
|
|
15
|
-
|
|
16
|
-
## 2. Read the config with the token
|
|
17
|
-
|
|
18
|
-
```bash
|
|
19
|
-
curl "https://api.picked.app/api/v1/projects/proj_123?preview_token=<token>"
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
A preview response returns `versionId: null`. An invalid token returns `401`.
|
|
23
|
-
|
|
24
|
-
## 3. Pass the same token to `serialize()`
|
|
25
|
-
|
|
26
|
-
```ts
|
|
27
|
-
const snapshot = await serialize(client, {
|
|
28
|
-
projectConfig,
|
|
29
|
-
attributes: { location: { pathname: '/promo' } },
|
|
30
|
-
previewToken,
|
|
31
|
-
})
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
Use the same token for both requests. The configuration and the content then come from the same
|
|
35
|
-
preview.
|
|
36
|
-
|
|
37
|
-
## Related
|
|
38
|
-
|
|
39
|
-
- [About the two APIs](/explanation/the-two-apis) — how a preview stays out of the search
|
|
40
|
-
index.
|
|
41
|
-
- [Preview, cache, and crawlers](/reference/delivery-api/preview-caching-crawling).
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: how-to
|
|
3
|
-
layout: docs
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# How to retry a failed call with a loop
|
|
7
|
-
|
|
8
|
-
This guide shows you how to make a workflow send a request again after the request fails.
|
|
9
|
-
The workflow waits before each new try. It stops after a number of tries that you set.
|
|
10
|
-
|
|
11
|
-
You need a workflow with an **External API** node first. Refer to
|
|
12
|
-
[How to call an external API from a workflow](/how-to/call-an-external-api-from-a-workflow).
|
|
13
|
-
|
|
14
|
-
## The loop
|
|
15
|
-
|
|
16
|
-
A loop is a path of edges that goes back to a node that the run reached before. This loop
|
|
17
|
-
has three nodes:
|
|
18
|
-
|
|
19
|
-
| Node | Function |
|
|
20
|
-
| ------------------- | ------------------------------------------------ |
|
|
21
|
-
| External API `send` | Sends the request. |
|
|
22
|
-
| Condition `check` | Decides if the workflow sends the request again. |
|
|
23
|
-
| Sleep `pause` | Waits before the next try. |
|
|
24
|
-
|
|
25
|
-
When you save a workflow, Picked refuses a loop that does not have a sleep node and a
|
|
26
|
-
condition node on it. Picked also refuses an edge from a node to the same node.
|
|
27
|
-
|
|
28
|
-
## 1. Connect the error exit to a condition
|
|
29
|
-
|
|
30
|
-
1. Open the workflow.
|
|
31
|
-
2. Choose **Add condition** on the error exit of `send`.
|
|
32
|
-
3. In the rule of `check`, test `{{ nodes.send.error.retryable }}`.
|
|
33
|
-
4. Connect the `false` exit of `check` to the nodes that record the failure.
|
|
34
|
-
|
|
35
|
-
`check` runs only when the call fails. The rule can then read the error of the last try.
|
|
36
|
-
|
|
37
|
-
## 2. Add the sleep node
|
|
38
|
-
|
|
39
|
-
1. Choose **Add sleep** on the `true` exit of `check`.
|
|
40
|
-
2. Set **Wait for** to the time between two tries.
|
|
41
|
-
3. Connect the exit of `pause` to the input of `send`.
|
|
42
|
-
|
|
43
|
-
The editor shows a loop as an edge that goes back to `send`.
|
|
44
|
-
|
|
45
|
-
## 3. Set the number of tries
|
|
46
|
-
|
|
47
|
-
Each node in the loop runs one time for each try. A run can visit one node a maximum
|
|
48
|
-
number of times. This number is the visit cap of the workflow.
|
|
49
|
-
|
|
50
|
-
1. Open the workflow settings.
|
|
51
|
-
2. Set **Visit cap** to a number from 1 to 100. If you do not set it, the visit cap is 10.
|
|
52
|
-
|
|
53
|
-
A node can get to the visit cap. If the run then gets to the node again, the run stops.
|
|
54
|
-
The run shows `Failed` with the code `loop_limit_reached`.
|
|
55
|
-
|
|
56
|
-
To stop the loop before the visit cap, test `current.visit` in the rule of `check`.
|
|
57
|
-
Its value is the number of the visit to `check`. This is also the number of failed tries.
|
|
58
|
-
This rule tries a maximum of 3 times:
|
|
59
|
-
|
|
60
|
-
```json
|
|
61
|
-
{
|
|
62
|
-
"and": [{ "var": "nodes.send.error.retryable" }, { "<": ["{{ current.visit }}", 3] }]
|
|
63
|
-
}
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
With this rule, the run continues on the `false` exit of `check` after 3 failures.
|
|
67
|
-
|
|
68
|
-
## 4. Read the result
|
|
69
|
-
|
|
70
|
-
A node reads the last visit of another node. After the loop, `{{ nodes.send.status }}`
|
|
71
|
-
gives the status of the last try.
|
|
72
|
-
|
|
73
|
-
The **Tasks** card of the run shows each visit as a task. Refer to the
|
|
74
|
-
[Workflow runs reference](/reference/dashboard/workflow-runs#tasks).
|
|
75
|
-
|
|
76
|
-
## Related
|
|
77
|
-
|
|
78
|
-
- [Workflow runs](/reference/dashboard/workflow-runs) — the tasks of each visit, and the
|
|
79
|
-
visit cap.
|
|
80
|
-
- [Workflow templates](/reference/dashboard/workflow-templates) — the data that a node
|
|
81
|
-
reads in a loop.
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: how-to
|
|
3
|
-
layout: docs
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# How to reuse a section
|
|
7
|
-
|
|
8
|
-
This guide shows you how to define a common structure one time and use it in more than
|
|
9
|
-
one Model.
|
|
10
|
-
|
|
11
|
-
## 1. Create the section
|
|
12
|
-
|
|
13
|
-
1. Click **Pages** in the sidebar.
|
|
14
|
-
2. Click **Page Sections**.
|
|
15
|
-
3. Click **New block**.
|
|
16
|
-
4. Enter a **Name** and a **Key**.
|
|
17
|
-
5. Add your fields.
|
|
18
|
-
6. Click **Create block**.
|
|
19
|
-
|
|
20
|
-
The **Category** is **Section** already, because you opened the list from **Page
|
|
21
|
-
Sections**.
|
|
22
|
-
|
|
23
|
-
## 2. Accept the section in a Model
|
|
24
|
-
|
|
25
|
-
1. Open a page layout or a step layout.
|
|
26
|
-
2. Add a **Page Sections** field to the schema.
|
|
27
|
-
3. Click **Save**.
|
|
28
|
-
|
|
29
|
-
The field now accepts any Block of the Section category. Make the field repeatable to
|
|
30
|
-
build a page from a list of sections.
|
|
31
|
-
|
|
32
|
-
If you want one section at a fixed place instead of a list, add a **Content block** field.
|
|
33
|
-
Set its **Block category** to the **Section** category.
|
|
34
|
-
|
|
35
|
-
## 3. Choose the section in an entry
|
|
36
|
-
|
|
37
|
-
1. Open a content entry that uses the Model.
|
|
38
|
-
2. Find the field that you added.
|
|
39
|
-
3. Choose your Block.
|
|
40
|
-
4. Fill in the fields of the Block.
|
|
41
|
-
5. Click **Save**.
|
|
42
|
-
|
|
43
|
-
:::warning
|
|
44
|
-
An edit to a Block does not migrate the entries that use it. Check each affected content
|
|
45
|
-
entry again, and correct every field error before you publish.
|
|
46
|
-
:::
|
|
47
|
-
|
|
48
|
-
## Related
|
|
49
|
-
|
|
50
|
-
- [About the content model](/explanation/the-content-model) — why a schema change does not
|
|
51
|
-
migrate your data.
|
|
52
|
-
- [Blocks](/reference/dashboard/content/blocks) — the reference.
|
|
53
|
-
- [Models](/reference/dashboard/content/models) — every field type.
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: how-to
|
|
3
|
-
layout: docs
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# How to reuse a step, a field, or an action
|
|
7
|
-
|
|
8
|
-
This guide shows you how to use one step, field, action, or condition in more than one
|
|
9
|
-
flow. All four belong to the project, and not to the experience that you made them in.
|
|
10
|
-
|
|
11
|
-
## Steps
|
|
12
|
-
|
|
13
|
-
1. Open the flow builder for the second experience.
|
|
14
|
-
2. Find the step, the action, or the condition in the library on the left.
|
|
15
|
-
3. Drag it onto the canvas, or onto a step node for a field.
|
|
16
|
-
|
|
17
|
-
The same one now appears in both flows.
|
|
18
|
-
|
|
19
|
-
:::warning
|
|
20
|
-
A change to the options applies at every place that uses it. Check the other flows before
|
|
21
|
-
you change a shared step, field, action, or condition.
|
|
22
|
-
:::
|
|
23
|
-
|
|
24
|
-
## Related
|
|
25
|
-
|
|
26
|
-
- [Steps](/reference/dashboard/steps) — the step options.
|
|
27
|
-
- [Fields](/reference/dashboard/fields) — the field options.
|
|
28
|
-
- [Actions](/reference/dashboard/actions) — the action options.
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: how-to
|
|
3
|
-
layout: docs
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# How to roll back a published version
|
|
7
|
-
|
|
8
|
-
This guide shows you how to make an earlier published version live again. Your current
|
|
9
|
-
draft does not change.
|
|
10
|
-
|
|
11
|
-
## Steps
|
|
12
|
-
|
|
13
|
-
1. Open **Publish history** from the project sidebar.
|
|
14
|
-
2. Find the version that you want to restore.
|
|
15
|
-
3. Click **Restore**.
|
|
16
|
-
4. Read the diff preview. It compares the current live version against the one that you
|
|
17
|
-
chose.
|
|
18
|
-
5. Click **Restore this version** to confirm.
|
|
19
|
-
|
|
20
|
-
The restored version is live immediately.
|
|
21
|
-
|
|
22
|
-
## Related
|
|
23
|
-
|
|
24
|
-
- [About workspaces and versions](/explanation/workspaces-and-versions) — why a roll-back
|
|
25
|
-
changes no data.
|
|
26
|
-
- [Publish history](/reference/dashboard/workspace-versioning) — the version list.
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: how-to
|
|
3
|
-
layout: docs
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# How to run an A/B test
|
|
7
|
-
|
|
8
|
-
This guide shows you how to split your traffic with a feature flag and read the result in
|
|
9
|
-
your application.
|
|
10
|
-
|
|
11
|
-
Read [About feature flag allocation](/explanation/feature-flag-allocation) first. The
|
|
12
|
-
point at which you read the feature flag decides when a visitor enters the test.
|
|
13
|
-
|
|
14
|
-
## 1. Create the feature flag
|
|
15
|
-
|
|
16
|
-
1. Open your project.
|
|
17
|
-
2. Click **Feature flags** in the sidebar.
|
|
18
|
-
3. Click **New feature flag**.
|
|
19
|
-
4. Enter a name.
|
|
20
|
-
5. Click **Create feature flag**.
|
|
21
|
-
|
|
22
|
-
You cannot change the key after you create the feature flag.
|
|
23
|
-
|
|
24
|
-
## 2. Set the allocation
|
|
25
|
-
|
|
26
|
-
Open the detail page of the feature flag and set these controls:
|
|
27
|
-
|
|
28
|
-
1. Turn **Enabled** on. A feature flag that is off allocates nobody.
|
|
29
|
-
2. Set **Weight** to the percentage of visitors that you want in the test.
|
|
30
|
-
3. Enter a **Description** that says what the feature flag tests.
|
|
31
|
-
|
|
32
|
-
## 3. Read the feature flag in your application
|
|
33
|
-
|
|
34
|
-
See [How to read a feature flag](/how-to/read-a-feature-flag). Read it at the point where
|
|
35
|
-
the decision matters, and not at startup.
|
|
36
|
-
|
|
37
|
-
## 4. Change the weight later
|
|
38
|
-
|
|
39
|
-
1. Change **Weight** on the detail page.
|
|
40
|
-
2. Increment the version.
|
|
41
|
-
|
|
42
|
-
The new weight then applies to a visitor with a cached decision. Leave the version as it
|
|
43
|
-
is to apply the new weight only to a visitor who is not allocated yet.
|
|
44
|
-
|
|
45
|
-
## Related
|
|
46
|
-
|
|
47
|
-
- [About feature flag allocation](/explanation/feature-flag-allocation) — why two feature
|
|
48
|
-
flags at the same weight give four groups, not two.
|
|
49
|
-
- [Feature flags](/reference/dashboard/features) — the controls.
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: how-to
|
|
3
|
-
layout: docs
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# How to run code on a form submission
|
|
7
|
-
|
|
8
|
-
This guide shows you how to act on a step submission. Pass your callbacks to `useStep()`
|
|
9
|
-
in React, or to `getStep()` in Svelte.
|
|
10
|
-
|
|
11
|
-
## What the SDK does on submit
|
|
12
|
-
|
|
13
|
-
1. It collects the field values from the HTML form.
|
|
14
|
-
2. It runs each `onBeforeSubmit` callback, one after another.
|
|
15
|
-
3. It checks each required field and each validation rule.
|
|
16
|
-
4. It commits the responses to the experience state.
|
|
17
|
-
5. It fires `form_submit_success` or `form_submit_error` on the event bus.
|
|
18
|
-
6. It runs your `onSuccess` or `onError` callback.
|
|
19
|
-
7. It moves to the next step.
|
|
20
|
-
|
|
21
|
-
## Change the data before it is stored
|
|
22
|
-
|
|
23
|
-
:::code-group
|
|
24
|
-
|
|
25
|
-
```tsx [React]
|
|
26
|
-
const { form } = useStep({
|
|
27
|
-
onBeforeSubmit: async (data) => ({
|
|
28
|
-
...data,
|
|
29
|
-
'email-address': String(data['email-address']).toLowerCase(),
|
|
30
|
-
}),
|
|
31
|
-
})
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
```svelte [Svelte]
|
|
35
|
-
<script lang="ts">
|
|
36
|
-
const { form } = getStep({
|
|
37
|
-
onBeforeSubmit: async (data) => ({
|
|
38
|
-
...data,
|
|
39
|
-
'email-address': String(data['email-address']).toLowerCase(),
|
|
40
|
-
}),
|
|
41
|
-
})
|
|
42
|
-
</script>
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
:::
|
|
46
|
-
|
|
47
|
-
:::warning
|
|
48
|
-
An `onBeforeSubmit` callback that throws aborts the submit before the SDK commits
|
|
49
|
-
anything, and the step does not advance. Use it for a transform and for a check. Put a
|
|
50
|
-
side effect, such as an analytics call, in `onSuccess`.
|
|
51
|
-
:::
|
|
52
|
-
|
|
53
|
-
## Act on the outcome
|
|
54
|
-
|
|
55
|
-
:::code-group
|
|
56
|
-
|
|
57
|
-
```tsx [React]
|
|
58
|
-
const { form } = useStep({
|
|
59
|
-
onSuccess: ({ data }) => analytics.track('lead_captured', data),
|
|
60
|
-
onError: (errors) => console.error('Validation errors:', errors),
|
|
61
|
-
})
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
```svelte [Svelte]
|
|
65
|
-
<script lang="ts">
|
|
66
|
-
const { form } = getStep({
|
|
67
|
-
onSuccess: ({ data }) => analytics.track('lead_captured', data),
|
|
68
|
-
onError: (errors) => console.error('Validation errors:', errors),
|
|
69
|
-
})
|
|
70
|
-
</script>
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
:::
|
|
74
|
-
|
|
75
|
-
A callback belongs to the component that passes it, and the SDK releases it when that
|
|
76
|
-
component unmounts. An `onSuccess` callback that throws cannot stop the flow. The SDK
|
|
77
|
-
reports the failure as `form_submit_callback_error`.
|
|
78
|
-
|
|
79
|
-
## Choose the next step yourself
|
|
80
|
-
|
|
81
|
-
Call `stopNavigation()` inside `onSuccess`, then move where you want:
|
|
82
|
-
|
|
83
|
-
:::code-group
|
|
84
|
-
|
|
85
|
-
```tsx [React]
|
|
86
|
-
const experience = useExperience()
|
|
87
|
-
|
|
88
|
-
const { form } = useStep({
|
|
89
|
-
onSuccess: ({ data, stopNavigation }) => {
|
|
90
|
-
stopNavigation()
|
|
91
|
-
if (data['plan-type'] === 'enterprise') {
|
|
92
|
-
experience.goToStepById('enterprise-contact')
|
|
93
|
-
} else {
|
|
94
|
-
experience.goToNextStep()
|
|
95
|
-
}
|
|
96
|
-
},
|
|
97
|
-
})
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
```svelte [Svelte]
|
|
101
|
-
<script lang="ts">
|
|
102
|
-
const experience = getExperience()
|
|
103
|
-
|
|
104
|
-
const { form } = getStep({
|
|
105
|
-
onSuccess: ({ data, stopNavigation }) => {
|
|
106
|
-
stopNavigation()
|
|
107
|
-
if (data['plan-type'] === 'enterprise') {
|
|
108
|
-
experience.goToStepById('enterprise-contact')
|
|
109
|
-
} else {
|
|
110
|
-
experience.goToNextStep()
|
|
111
|
-
}
|
|
112
|
-
},
|
|
113
|
-
})
|
|
114
|
-
</script>
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
:::
|
|
118
|
-
|
|
119
|
-
`goToStepById()` takes a step `id`. `goToStepByKey()` takes the key of the step. When no
|
|
120
|
-
step matches, the call does nothing.
|
|
121
|
-
|
|
122
|
-
## Related
|
|
123
|
-
|
|
124
|
-
- [How to render a step form](/how-to/render-a-step-form).
|
|
125
|
-
- [SDK steps](/reference/sdk/steps) — the `form` object.
|