@wix/agent-skills 1.18.0 → 1.18.2
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/package.json +1 -1
- package/skills/wix-app/SKILL.md +4 -4
- package/skills/wix-app/references/APP_VALIDATION.md +7 -33
- package/skills/wix-app/references/DASHBOARD_PAGE.md +18 -14
- package/skills/wix-app/references/EDITOR_REACT_COMPONENT.md +75 -92
- package/skills/wix-app/references/WIX_PATTERNS_DOCS.md +23 -26
- package/skills/wix-app/references/dashboard-page/COLLECTION_TOOLKIT.md +7 -6
- package/skills/wix-app/references/dashboard-page/ENTITY_PAGE_TOOLKIT.md +71 -4
- package/skills/wix-app/references/dashboard-page/PATTERNS_BUNDLE_READING.md +67 -7
- package/skills/wix-app/references/editor-react-component/ACCESSIBILITY.md +1 -1
- package/skills/wix-app/references/editor-react-component/ANIMATED-COMPONENTS.md +9 -6
- package/skills/wix-app/references/editor-react-component/COMPONENT-CONTRACT.md +59 -89
- package/skills/wix-app/references/editor-react-component/COMPONENT-PREVIEW.md +23 -4
- package/skills/wix-app/references/editor-react-component/CSS-GUIDELINES.md +29 -14
- package/skills/wix-base44-connector/SKILL.md +168 -48
- package/skills/wix-base44-connector/scripts/{utils.js → utils.cjs} +69 -48
- package/skills/wix-docs/SKILL.md +109 -111
- package/skills/wix-docs/references/API_SPEC_SEARCH.md +35 -23
- package/skills/wix-docs/references/CALLING.md +91 -0
- package/skills/wix-docs/references/EXTRACTING.md +5 -3
- package/skills/wix-headless/references/DOC_DISCOVERY.md +9 -3
- package/skills/wix-headless/references/inline-recipes/setup-forms.md +57 -10
- package/skills/wix-manage/SKILL.md +106 -92
- package/skills/wix-manage/references/dashboard-navigation/routes.json +12 -52
- package/skills/wix-manage/references/ecommerce/shipping/ecom-shipping-api.md +0 -2
- package/skills/wix-manage/references/forms/create-form.md +272 -184
- package/skills/wix-manage/references/forms/forms-dashboard-navigation.md +13 -10
- package/skills/wix-manage/references/forms/update-form.md +122 -0
- package/skills/wix-manage/references/media/generate-image-with-ai.md +86 -0
- package/skills/wix-manage/references/seo/manage-content-plan.md +247 -0
- package/skills/wix-manage/references/seo/manage-seo-tags.md +59 -6
- package/skills/wix-manage/references/stores/change-store-currency.md +10 -0
- package/skills/wix-manage/references/stores/create-product-catalog-v3.md +16 -1
- package/skills/wix-manage/references/stores/update-product-with-options.md +9 -0
- package/skills/wix-vibe-headless/SKILL.md +17 -18
- package/skills/wix-vibe-headless/install/pin-agents-md.cjs +1 -1
- package/skills/wix-vibe-headless/platforms/base44-ecom-light-seed-with-install.md +118 -0
- package/skills/wix-vibe-headless/platforms/base44-ecom-light-seed.md +55 -62
- package/skills/wix-vibe-headless/platforms/base44-ecom-light.md +31 -29
- package/skills/wix-vibe-headless/platforms/base44.md +12 -5
- package/skills/wix-vibe-headless/platforms/generic.md +13 -12
- package/skills/wix-vibe-headless/references/blog/INSTRUCTIONS.md +4 -13
- package/skills/wix-vibe-headless/references/blog/seed/SEED.md +4 -8
- package/skills/wix-vibe-headless/references/blog/seed/{seed-blog.js → seed-blog.cjs} +2 -3
- package/skills/wix-vibe-headless/references/bookings/INSTRUCTIONS.md +5 -14
- package/skills/wix-vibe-headless/references/bookings/seed/SEED.md +5 -9
- package/skills/wix-vibe-headless/references/bookings/seed/{seed-bookings.js → seed-bookings.cjs} +2 -2
- package/skills/wix-vibe-headless/references/bookings/seed/{seed-rentals.js → seed-rentals.cjs} +3 -3
- package/skills/wix-vibe-headless/references/cms/INSTRUCTIONS.md +1 -1
- package/skills/wix-vibe-headless/references/cms/seed/SEED.md +2 -2
- package/skills/wix-vibe-headless/references/events/INSTRUCTIONS.md +4 -13
- package/skills/wix-vibe-headless/references/events/seed/SEED.md +3 -7
- package/skills/wix-vibe-headless/references/events/seed/{seed-events.js → seed-events.cjs} +2 -2
- package/skills/wix-vibe-headless/references/forms/INSTRUCTIONS.md +24 -7
- package/skills/wix-vibe-headless/references/forms/seed/SEED.md +91 -17
- package/skills/wix-vibe-headless/references/members/INSTRUCTIONS.md +4 -13
- package/skills/wix-vibe-headless/references/members/seed/SEED.md +2 -3
- package/skills/wix-vibe-headless/references/portfolio/INSTRUCTIONS.md +4 -13
- package/skills/wix-vibe-headless/references/portfolio/app/components/ProjectMedia.jsx +1 -1
- package/skills/wix-vibe-headless/references/portfolio/seed/SEED.md +3 -7
- package/skills/wix-vibe-headless/references/portfolio/seed/{seed-portfolio.js → seed-portfolio.cjs} +2 -2
- package/skills/wix-vibe-headless/references/pricing-plans/INSTRUCTIONS.md +5 -14
- package/skills/wix-vibe-headless/references/pricing-plans/app/components/OrderCard.jsx +1 -1
- package/skills/wix-vibe-headless/references/pricing-plans/seed/SEED.md +3 -7
- package/skills/wix-vibe-headless/references/pricing-plans/seed/{seed-pricing-plans.js → seed-pricing-plans.cjs} +2 -2
- package/skills/wix-vibe-headless/references/restaurants/INSTRUCTIONS.md +5 -15
- package/skills/wix-vibe-headless/references/restaurants/seed/SEED.md +3 -7
- package/skills/wix-vibe-headless/references/restaurants/seed/{seed-restaurants.js → seed-restaurants.cjs} +2 -2
- package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +359 -327
- package/skills/wix-vibe-headless/references/storefront/app/context/CartContext.jsx +1 -0
- package/skills/wix-vibe-headless/references/storefront/app/hooks/useProductDetail.js +2 -2
- package/skills/wix-vibe-headless/references/storefront/app/hooks/useShop.js +63 -78
- package/skills/wix-vibe-headless/references/storefront/app/rest/wix-store-catalog.js +59 -43
- package/skills/wix-vibe-headless/references/storefront/seed/SEED.md +46 -10
- package/skills/wix-vibe-headless/references/storefront/seed/{seed-store.js → seed-store.cjs} +163 -25
- package/skills/wix-vibe-headless/references/storefront/app/pages/Shop.jsx +0 -75
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: "Forms Dashboard Navigation"
|
|
3
|
-
description: "Builds direct links to Wix Forms dashboard pages on manage.wix.com
|
|
3
|
+
description: "Builds direct links to Wix Forms dashboard pages on manage.wix.com. The paths are not guessable and appear in no API reference, so take them from here: under `https://manage.wix.com/dashboard/{metaSiteId}/`, the forms list is `wix-forms`, a form's builder is `wix-forms/form/{formId}`, and that form's submissions are `wix-forms/form/{formId}/submissions` — there is no site-wide submissions page, and nothing lives under `contacts/forms`, `forms`, `form-builder` or `wix-forms-and-payments` (the legacy app). Also standalone forms, and each Forms entity paired with its read API so you can fetch one and hand back a 'view it in your dashboard' link."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Forms Dashboard Navigation
|
|
@@ -9,36 +9,39 @@ Build direct links into the Wix Forms pages of a site's dashboard. For the gener
|
|
|
9
9
|
|
|
10
10
|
## Main Pages
|
|
11
11
|
|
|
12
|
+
**Never goess or answer a Forms dashboard-link request from memory** because the routes below are the only correct ones.
|
|
13
|
+
|
|
12
14
|
| Page | URL after `/dashboard/{metaSiteId}/` | What it manages |
|
|
13
15
|
|---|---|---|
|
|
14
16
|
| Forms list | `wix-forms` | All forms on the site |
|
|
15
17
|
| Form builder | `wix-forms/form/{formId}` | Edit a specific form (fields, rules, submit settings) |
|
|
18
|
+
| Submissions | `wix-forms/form/{formId}/submissions` | That form's submissions table |
|
|
16
19
|
| Standalone form | `wix-forms/standalone-form` | Create a standalone form (has its own shareable page, not embedded in a site page) |
|
|
17
|
-
| Submissions | `wix-forms-and-payments/submissions` | Submissions table across forms |
|
|
18
|
-
| Templates | `wix-forms-and-payments/templates` | Create a form from a template |
|
|
19
|
-
| Forms settings | `wix-forms-and-payments/settings` | Forms-level settings |
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
**Every Forms page is under `wix-forms`** — the namespace **Wix Forms (New)** `225dd912-7dea-4738-8688-4b8c6955ffc2` registers, the app that owns the Form Schemas v4 API. A `wix-forms-and-payments/...` path belongs to the legacy **Wix Forms (Old)** app `14ce1214-b278-a7e4-1373-00cebd1bef7c`: don't build one, and never install or target that app (see [Create Form](./create-form.md) § Silent breakers).
|
|
22
|
+
|
|
23
|
+
**Submissions are per form**, hanging off that form's builder path — there is no site-wide submissions page to link to. With no `{formId}` in hand, link the forms list and let the owner pick.
|
|
22
24
|
|
|
23
|
-
Entity-specific links (`{formId}`)
|
|
25
|
+
Entity-specific links (`{formId}`) take the entity's ID as a path segment, and query params can follow. The dashboard appends its own view state to the submissions URL — `folder` (a JSON-encoded breadcrumb), `sort` (e.g. `createdDate+desc`) and `selectedColumns` (a comma-separated list of field **`target`**s) — none of which you need to construct: the bare path opens the table with the owner's defaults.
|
|
24
26
|
|
|
25
27
|
## Pairing Entities with Their Read APIs
|
|
26
28
|
|
|
27
|
-
Fetch the entity via REST, then link the matching dashboard page. All calls use `https://www.wixapis.com` with an `Authorization` header. Dashboard forms
|
|
29
|
+
Fetch the entity via REST, then link the matching dashboard page. All calls use `https://www.wixapis.com` with an `Authorization` header. Dashboard forms live in the **`wix.form_app.form`** namespace — every Forms call that takes a namespace, as a query parameter or inside a filter, takes that exact value.
|
|
28
30
|
|
|
29
31
|
| Entity | Read API | Dashboard link |
|
|
30
32
|
|---|---|---|
|
|
31
33
|
| Form | `GET /form-schema-service/v4/forms` · `POST /form-schema-service/v4/forms/query` · `GET /form-schema-service/v4/forms/{formId}` | `wix-forms/form/{formId}` (edit) or `wix-forms` (list) |
|
|
32
|
-
| Submission | `POST /form-submission/v4/submissions/namespace/query` (filter must
|
|
34
|
+
| Submission | `POST /form-submission-service/v4/submissions/namespace/query` (the filter must carry `"namespace": "wix.form_app.form"`) · `GET /form-submission-service/v4/submissions/{submissionId}` | `wix-forms/form/{formId}/submissions` — the `formId` comes off the submission |
|
|
33
35
|
|
|
34
36
|
Example — after creating a form, hand back its links:
|
|
35
37
|
|
|
36
38
|
```
|
|
37
39
|
Created "Contact Form".
|
|
38
40
|
Edit it here: https://manage.wix.com/dashboard/{metaSiteId}/wix-forms/form/{formId}
|
|
39
|
-
See submissions: https://manage.wix.com/dashboard/{metaSiteId}/wix-forms
|
|
41
|
+
See submissions: https://manage.wix.com/dashboard/{metaSiteId}/wix-forms/form/{formId}/submissions
|
|
40
42
|
```
|
|
41
43
|
|
|
42
44
|
## Notes
|
|
43
45
|
|
|
44
|
-
- Creating forms via the [Create Form](./create-form.md) recipe (Form Schemas API) makes them appear in the forms list above.
|
|
46
|
+
- Creating forms via the [Create Form](./create-form.md) recipe (Form Schemas API) makes them appear in the forms list above — **but only when the form was created under the `wix.form_app.form` namespace with Wix Forms (New) installed.** A form created under any other namespace is reachable over the API and completely absent from these pages.
|
|
47
|
+
- **Before handing back a `wix-forms/form/{formId}` link, confirm the form actually renders**: `GET https://www.wixapis.com/form-schema-service/v4/forms/{formId}/summary` must return a non-empty `formSummary.fields` whose count matches every input field. An empty summary means the owner will open this link to a blank form (Create Form, STEP 3).
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "Update Form"
|
|
3
|
+
description: "Changes a Wix form that already exists, with Form Schemas v4 `PATCH` — add a field to my form, add a dropdown, make a field required or optional, rename a label, reorder or retire a question. Covers reading the form back for its `revision` (and the required `namespace` query parameter), the whole-form body that a `PATCH` needs, the wholesale `formFields` replace that silently soft-deletes anything you omit, changing a field's component type in place, retiring a field that already has submissions, and the read-back that proves what was stored. Use whenever the form exists and the request changes what it collects; use Create Form when there is no form yet."
|
|
4
|
+
---
|
|
5
|
+
# RECIPE: Update a Wix Form
|
|
6
|
+
|
|
7
|
+
> **Standard call shape (every curl below).** The `<AUTH>` placeholder is shorthand for `Authorization: Bearer <TOKEN>` only. Body-bearing requests also need `Content-Type: application/json`. Send `wix-site-id: <SITE_ID>` when the token is account-scoped.
|
|
8
|
+
|
|
9
|
+
Change what a form collects — **add a field, relabel one, tighten a rule, reorder, retire one** — on a form that already exists. **Composing the field itself is not here**: [About Form Fields](https://dev.wix.com/docs/api-reference/crm/forms/form-schemas/about-form-fields) owns the `identifier` / `inputType` / `componentType` table and the options/enum shapes, and [Create Form](./create-form.md) § Silent breakers apply to an added field exactly as to a created one.
|
|
10
|
+
|
|
11
|
+
**A `PATCH`, never a delete-and-recreate.** An update keeps the `formId` everything downstream already holds — a frontend binding, an automation, a saved dashboard view — and spends no slot against the site's form cap.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## The call
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# 1 · read the form back: you need its current revision, and every field you intend to keep
|
|
19
|
+
curl -X GET \
|
|
20
|
+
'https://www.wixapis.com/form-schema-service/v4/forms?namespace=wix.form_app.form&formIds={formId}' \
|
|
21
|
+
-H 'Authorization: <AUTH>'
|
|
22
|
+
|
|
23
|
+
# 2 · send that form back with your change applied
|
|
24
|
+
curl -X PATCH \
|
|
25
|
+
'https://www.wixapis.com/form-schema-service/v4/forms/{formId}' \
|
|
26
|
+
-H 'Content-Type: application/json' \
|
|
27
|
+
-H 'Authorization: <AUTH>' \
|
|
28
|
+
-d '{ "form": {
|
|
29
|
+
"id": "{formId}",
|
|
30
|
+
"revision": "<the revision you just read>",
|
|
31
|
+
"name": "<the form name>",
|
|
32
|
+
"namespace": "wix.form_app.form",
|
|
33
|
+
"formFields": [ ...every field, with your change applied... ],
|
|
34
|
+
"steps": [ ...every step, with the layout item for a new field... ]
|
|
35
|
+
} }'
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
- **⚠️ `namespace` is a REQUIRED query parameter on the read, and this is what a revise run trips over.** Without it the read returns `400 namespace has size 0, expected 10 or more, namespace must not be empty` — a violation naming a *field*, so it reads like a body problem. Fix the call, don't reshape the payload. (The filter on `POST .../v4/forms/query` needs it too.)
|
|
39
|
+
- **The read-back is the body.** Apply your change to what the `GET` returned and send that as `form`. `namespace` is **immutable** and travels along; **there is no `fieldMask`**, and no `revision` outside `form` — inventing either is a silent partial write.
|
|
40
|
+
- **⚠️ Append to `formFields`; never rebuild the entries you read.** `[...form.formFields, newField]` works. Mapping the array to "clean up" each field — dropping `fieldType`, re-shaping an options block — fails with `fieldType cannot be provided with any these fields: input_options, display_options` on **every** field at once. The read-back's field objects are already a valid write shape: pass them through untouched and touch only the one field you are changing.
|
|
41
|
+
- **`formFields` is replaced wholesale.** Wix: *"Any field that's missing from the array you send is moved to `deletedFormFields`, so resend every field you want to keep."* Same for `steps[].layout` — miss an item and that field goes unplaced, which renders empty. Drops are recoverable from `deletedFormFields`, but nothing announces them.
|
|
42
|
+
- **A stale `revision` is rejected** — re-`GET` and re-apply; never guess or increment it.
|
|
43
|
+
- **Plan caps apply to an added field.** `Field count reached its limit of N` on a `PATCH` is the site's premium cap: reduce or upgrade, with the choice put to the user ([Create Form](./create-form.md) § Plan caps). Never split the form across schemas to dodge it.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Adding a field
|
|
48
|
+
|
|
49
|
+
**Start by reading [About Form Fields](https://dev.wix.com/docs/api-reference/crm/forms/form-schemas/about-form-fields) § Field types and § Choice fields** for the field kind you're adding: it gives the `identifier` / `inputType` / `componentType` triple — take all three from one row, and note that a dropdown or radio is `inputType: "STRING"` — plus the options/enum shape and the GUID every option needs. [Create Form](./create-form.md) § Choice fields carries a complete dropdown body to copy. Composing a field from memory is what turns one `PATCH` into eight.
|
|
50
|
+
|
|
51
|
+
Then four things are yours to generate:
|
|
52
|
+
|
|
53
|
+
- **`id`** — a fresh lowercase GUID (`uuidgen | tr 'A-Z' 'a-z'`), unique in the form.
|
|
54
|
+
- **`target`** — the immutable submission key, unique across the form: snake_case plus a short random suffix (`job_industry_7f2b`). **A duplicate `target` is accepted and silently stores nothing** for every field but one.
|
|
55
|
+
- **one GUID per choice option** — `options[]` each need their own, exactly like the field's; a readable slug is rejected ([Create Form](./create-form.md) § Choice fields). Generate them with `uuidgen`, never by hand.
|
|
56
|
+
- **the choices, declared twice** — every option needs `id` + `value` + `label`, and `validation.enum` must list every one of those `value`s. **An empty `validation` is a free-text field, not a dropdown**; the general "always include `validation`, even as `{}`" rule does not apply here, and getting it wrong is accepted with a `200`.
|
|
57
|
+
- **the layout item** — append to `steps[<n>].layout.large.items`, mirroring into `medium` / `small` if the form has them:
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{ "fieldId": "<the new field's id>", "row": <next row>, "column": 0, "width": 12, "height": 1 }
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
A field missing from the layout isn't dropped, but it sorts last and has no defined position in the owner's builder. To place it mid-form, insert at that `row` and bump every item at or after it — `row` restarts at 0 in each step.
|
|
64
|
+
|
|
65
|
+
**A choice field's `identifier` is its kind** — `DROPDOWN`, `RADIO_GROUP`, `CHECKBOX_GROUP`, `TAGS` — never `TEXT_INPUT`, which is accepted and stored as a plain text input ([Create Form](./create-form.md) § Choice fields).
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## The other changes
|
|
70
|
+
|
|
71
|
+
| Change | How |
|
|
72
|
+
|---|---|
|
|
73
|
+
| Label, placeholder, options, validation, order | Patch them and stop — nothing downstream needs updating |
|
|
74
|
+
| A field's component type, in place | Send that field with the **choice `identifier`** and only the new options block; leaving `textInputOptions` beside `dropdownOptions` reads back as the text-input fallback |
|
|
75
|
+
| Retire a field the form has submissions for | Set `hidden: true` — "hidden from submitters": the field stops rendering, and the submissions already collected under it keep their meaning. Dropping it from the array soft-deletes it instead |
|
|
76
|
+
| Remove a field added by mistake this run | Drop it from `formFields`; it lands on `deletedFormFields` |
|
|
77
|
+
| Rename a `target` | **Never.** It is the storage key, so a rename orphans every submission already collected under the old one. Change the *label* instead |
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Verify — an update regresses a form exactly as a create can
|
|
82
|
+
|
|
83
|
+
**A `200` on the `PATCH` proves the body parsed, nothing about what was stored.** Read the form back, every time:
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
GET https://www.wixapis.com/form-schema-service/v4/forms?namespace=wix.form_app.form&formIds={formId}
|
|
87
|
+
GET https://www.wixapis.com/form-schema-service/v4/forms/{formId}/summary
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Assert on that read-back, not on the `PATCH` response:
|
|
91
|
+
|
|
92
|
+
- the changed field is there, carrying the `identifier` and `componentType` you sent — **a choice field with a non-empty `options[]`**, which is where a dropdown that degraded to a text input shows up;
|
|
93
|
+
- every field you meant to keep is still present, and every `inputOptions.required` still reads back as sent;
|
|
94
|
+
- `formSummary.fields` still holds one entry per input field — that is what the owner's dashboard renders.
|
|
95
|
+
|
|
96
|
+
Then hand back the dashboard links ([Forms Dashboard Navigation](./forms-dashboard-navigation.md)): the form builder at `wix-forms/form/{formId}`, and that form's submissions at `wix-forms/form/{formId}/submissions`. New submissions carry the new field; past ones don't.
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Troubleshooting
|
|
101
|
+
|
|
102
|
+
| Error / symptom | Cause | Fix |
|
|
103
|
+
|---|---|---|
|
|
104
|
+
| `400 namespace has size 0, expected 10 or more` / `namespace must not be empty` on a read | The `namespace` **query parameter** was omitted — it is required on every listing read, and the violation naming a field makes it look like a body problem | Add `?namespace=wix.form_app.form` to the read; leave the payload alone |
|
|
105
|
+
| `fieldType cannot be provided with any these fields: input_options, display_options` — on every field | The read-back's `formFields` were re-mapped or "cleaned" before sending | Send the fields exactly as read and append the new one: `[...form.formFields, newField]` |
|
|
106
|
+
| `inputType enum must be in [UNKNOWN_INPUT_TYPE, STRING, NUMBER, …]` | An invented `inputType` such as `ENUM` (with an `enumOptions` block) for a choice field | A dropdown or radio is `inputType: "STRING"` with `stringOptions.componentType`; multi choice is `ARRAY` |
|
|
107
|
+
| The `PATCH` is rejected for a `revision` mismatch | Someone (or an earlier call) updated the form since your read | Re-`GET` and re-apply the change; never increment the revision yourself |
|
|
108
|
+
| Fields that were on the form are gone after the update | `formFields` was sent partial — the omitted fields moved to `deletedFormFields` | Re-send them in a further `PATCH`, from `deletedFormFields` in the read-back; always send the whole array |
|
|
109
|
+
| Surviving fields render empty for the owner | `steps[].layout` was sent without their items | Re-send every layout item, including `SUBMIT_BUTTON`'s; re-verify with `/summary` |
|
|
110
|
+
| The added dropdown/radio reads back as a text input with `textInputOptions` | `identifier` was `TEXT_INPUT` rather than the choice kind — `componentType` alone doesn't route the renderer | Set `identifier` to the choice kind and re-send. Deleting and re-adding the field with the same `identifier` reproduces it ([Create Form](./create-form.md) § Choice fields) |
|
|
111
|
+
| The update lands but the field never appears in submissions | The new field shares a `target` with an existing one — the server keeps one and the rest store nothing | Give it a unique `target` and `PATCH` again |
|
|
112
|
+
| `Field count reached its limit of N` | The site's premium field cap, counting `INPUT` fields | Reduce, or put the upgrade choice to the user ([Create Form](./create-form.md) § Plan caps) |
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Related Documentation
|
|
117
|
+
|
|
118
|
+
- [Create Form](./create-form.md) — composing fields, the identifier table, choice fields, the layout rules, plan caps
|
|
119
|
+
- [Forms Dashboard Navigation](./forms-dashboard-navigation.md) — the builder and submissions links to hand back
|
|
120
|
+
- [Update Form](https://dev.wix.com/docs/api-reference/crm/forms/form-schemas/update-form) — the `PATCH` contract and its replace semantics
|
|
121
|
+
- [Form object](https://dev.wix.com/docs/api-reference/crm/forms/form-schemas/form-object) — `revision`, `hidden`, `deletedFormFields`, `steps[].layout`
|
|
122
|
+
- [About Form Fields](https://dev.wix.com/docs/api-reference/crm/forms/form-schemas/about-form-fields) — every field-level rule
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "Generate an Image with AI"
|
|
3
|
+
description: Generates an image from a text prompt with the Wix AI APIs (Runware). Returns a short-lived URL that must be imported to be kept — importing is Upload Media to Wix's job, and this recipe hands off to it. Covers choosing a model and its cost/latency/content-filter trade-off, the accepted output sizes, per-model batching limits, the AI credit each call spends, and why a content refusal arrives as a success response with no image.
|
|
4
|
+
---
|
|
5
|
+
# RECIPE: Generate an Image with AI
|
|
6
|
+
|
|
7
|
+
For an image the user does not have. An image they supplied — an attachment or a public URL — is uploaded instead: [Upload Media to Wix](upload-media-to-wix.md).
|
|
8
|
+
|
|
9
|
+
**API reference:** [About the Wix AI APIs](https://dev.wix.com/docs/api-reference/articles/ai-tools/ai-apis/about-the-wix-ai-apis), *Generating images* — endpoint, auth, and the full model table. Developer Preview, so confirm the contract there.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## AI credits
|
|
14
|
+
|
|
15
|
+
Each call spends roughly **one AI credit**, billed to the site owner, or to the Wix user who installed the calling app. `numberResults: n` spends n. Importing is free.
|
|
16
|
+
|
|
17
|
+
Generate one image per entity that needs one, and say how many a run will generate before starting it. Regenerate only when the user asks.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Step 1: Generate
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
curl -X POST 'https://www.wixapis.com/runwareschemaless/v1/request' \
|
|
25
|
+
-H 'Content-Type: application/json' \
|
|
26
|
+
-H 'Authorization: <AUTH>' \
|
|
27
|
+
-H 'wix-site-id: <METASITE_ID>' \
|
|
28
|
+
-d '[{
|
|
29
|
+
"taskType": "imageInference",
|
|
30
|
+
"taskUUID": "3f8c1e42-9b7a-4d16-8a5e-2c0f7b9d4e11",
|
|
31
|
+
"outputType": "URL",
|
|
32
|
+
"outputFormat": "PNG",
|
|
33
|
+
"positivePrompt": "a ceramic pour-over coffee dripper on a walnut counter, morning light",
|
|
34
|
+
"width": 1024,
|
|
35
|
+
"height": 1024,
|
|
36
|
+
"model": "runware:400@1",
|
|
37
|
+
"numberResults": 1
|
|
38
|
+
}]'
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
| Parameter | Value |
|
|
42
|
+
|---|---|
|
|
43
|
+
| `taskUUID` | A real UUIDv4. Anything else returns `400 invalidTaskUUID` |
|
|
44
|
+
| `width` / `height` | `1024×1024` (square — products, services, menu items), `1376×768` (16:9 hero), `1200×896` (4:3 editorial). Free-form sizes return 400 |
|
|
45
|
+
| `model` | See below |
|
|
46
|
+
| `numberResults` | `1` |
|
|
47
|
+
|
|
48
|
+
Omit `steps` and `CFGScale`: Runware accepts them, other models return `400 unsupportedParameter`.
|
|
49
|
+
|
|
50
|
+
### Models
|
|
51
|
+
|
|
52
|
+
| `model` | Latency | Content filter |
|
|
53
|
+
|---|---|---|
|
|
54
|
+
| `runware:400@1` | ~5s | Loosest — the default |
|
|
55
|
+
| `google:4@2` | ~25s | Medium, best fidelity |
|
|
56
|
+
| `bfl:5@1` | — | Strictest; refuses trademark-ish prompts |
|
|
57
|
+
|
|
58
|
+
Any Runware-supported model works — the reference's *Suggested models* table has the current AIR IDs.
|
|
59
|
+
|
|
60
|
+
### Read the response
|
|
61
|
+
|
|
62
|
+
```json
|
|
63
|
+
{ "data": [ { "imageURL": "https://im.runware.ai/image/ws/2/ii/<id>.png" } ] }
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**A refusal is a success response with no `imageURL`** — test for the field, not the status. On a refusal, reword the prompt or switch model, and report the image as not created.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Step 2: Import
|
|
71
|
+
|
|
72
|
+
`imageURL` expires, so import it as it lands. [Upload Media to Wix](upload-media-to-wix.md) owns that endpoint and its `PENDING` / `READY` rules; pass the `imageURL` as `url` and `image/png` as `mimeType`.
|
|
73
|
+
|
|
74
|
+
The result is the returned `file.id` / `file.url` — permanent, and what an entity field takes.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Batches
|
|
79
|
+
|
|
80
|
+
`runware:400@1` and `bfl:5@1` take several tasks in one body. `google:4@2` returns 504 at three or more, so fire parallel single-task requests for it.
|
|
81
|
+
|
|
82
|
+
Failure is per image: attach the ones that succeeded, create the rest of the entities text-only, and name which entities have no image and why. A failed image stays missing rather than being swapped for another.
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
For JavaScript callers there is an SDK path — `generateImage()` from the Vercel AI SDK with `runware.image(...)` from `@wix/ai`: [Set up the Wix AI SDK](https://dev.wix.com/docs/api-reference/articles/ai-tools/ai-apis/set-up-the-wix-ai-sdk).
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "Generate and Read a Wix Site's Content Plan"
|
|
3
|
+
description: Generate an SEO content plan and read its blog post topics, or troubleshoot an existing content plan flow stuck at KEYWORD_RESEARCH while polling GetContentPlanFlow. Use this recipe for both generation and stalled-flow questions: it explains the intentional pause, the Create Content Plan release request, missing flow IDs, and the exact public API paths and response fields.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Generate and Read a Wix Site's Content Plan
|
|
7
|
+
|
|
8
|
+
## Choose the request path before calling an API
|
|
9
|
+
|
|
10
|
+
For a request to **generate a new plan**, follow the generation sequence below.
|
|
11
|
+
For a request about an **existing flow**, use this branch instead; do not start
|
|
12
|
+
the generation sequence or make a discovery call to look for the flow.
|
|
13
|
+
|
|
14
|
+
`KEYWORD_RESEARCH` is an intentional pause, even after ten minutes. Explain
|
|
15
|
+
that Create Content Plan (step 3) releases the existing flow; do not cancel it
|
|
16
|
+
or trigger a replacement just because it is parked.
|
|
17
|
+
First check whether the conversation or a prior response contains the actual
|
|
18
|
+
`contentPlanFlowId`:
|
|
19
|
+
|
|
20
|
+
- **Missing ID:** Explain the intentional pause and ask for the existing flow
|
|
21
|
+
ID. End the turn without making a status or release call. You can name the
|
|
22
|
+
release endpoint, `POST https://www.wixapis.com/promote/seo/v1/create-content-plan`,
|
|
23
|
+
but do not execute an example request. Placeholder text such as
|
|
24
|
+
`<YOUR_FLOW_ID>` is never an API argument.
|
|
25
|
+
- **Known ID:** Use that actual flow UUID in the step 3 request's
|
|
26
|
+
`contentPlanFlowId` field to release the existing flow when requested.
|
|
27
|
+
|
|
28
|
+
For example, when the user reports a flow parked at `KEYWORD_RESEARCH` but
|
|
29
|
+
provides only a site ID, the next action is a reply, not an API call:
|
|
30
|
+
|
|
31
|
+
> That status is an intentional pause. Create Content Plan releases the
|
|
32
|
+
> existing flow. Please send the content plan flow ID from your trigger or
|
|
33
|
+
> status response so I can use it in the release request.
|
|
34
|
+
|
|
35
|
+
The user's reported status is enough to explain the pause; checking it first
|
|
36
|
+
requires the very flow ID that is missing. A site ID is not a flow ID, even
|
|
37
|
+
though both have UUID format.
|
|
38
|
+
Do not guess a collection endpoint to discover the active flow.
|
|
39
|
+
|
|
40
|
+
The complete status URL is
|
|
41
|
+
`https://www.wixapis.com/promote/seo/v1/content-plan-flows/{contentPlanFlowId}`.
|
|
42
|
+
Use this exact public base path and substitute the known ID. Do not call
|
|
43
|
+
`GET /content-plan-flows` without an ID or construct a URL from a service name.
|
|
44
|
+
|
|
45
|
+
Trigger, poll, release, poll, read. That is the full loop. The API is
|
|
46
|
+
asynchronous — generation takes minutes — and the flow **parks at
|
|
47
|
+
`KEYWORD_RESEARCH` until you explicitly release it**.
|
|
48
|
+
|
|
49
|
+
All paths are relative to `https://www.wixapis.com/promote/seo/v1`.
|
|
50
|
+
The API selects the site from the caller's authorization context.
|
|
51
|
+
Writing requires the **Manage SEO Settings** permission.
|
|
52
|
+
|
|
53
|
+
For a generation request, the only writes in this workflow are Trigger and
|
|
54
|
+
Create Content Plan. Do not update the site's business profile, name,
|
|
55
|
+
description, categories, or publication state to try to accelerate generation.
|
|
56
|
+
Those are separate tasks requiring the user's actual data and authorization.
|
|
57
|
+
`CREATED` can persist while work is queued; it does not justify setup changes
|
|
58
|
+
or extra discovery calls. Continue checking the same flow without modifying
|
|
59
|
+
the site.
|
|
60
|
+
|
|
61
|
+
Keep every call scoped to the site the user selected. If site context cannot
|
|
62
|
+
be resolved, report the lookup failure and request clarification; do not
|
|
63
|
+
substitute another available site or change its business information. Missing
|
|
64
|
+
context is not proof that the selected site does not exist or belongs to a
|
|
65
|
+
different account. Say that its context could not be retrieved; do not claim
|
|
66
|
+
that the user's site ID is invalid or offer replacement sites. Likewise, unmet
|
|
67
|
+
prerequisites do not authorize switching sites or inventing business data.
|
|
68
|
+
|
|
69
|
+
## Polling without losing progress
|
|
70
|
+
|
|
71
|
+
Treat each numbered step below as a separate API execution, not sections of
|
|
72
|
+
one script. Even a loop capped at 60 polls can outlive the execution timeout
|
|
73
|
+
and lose the returned flow ID. A polling script must issue one GET and return
|
|
74
|
+
`{ contentPlanFlowId, status }` immediately; decide the next action after that
|
|
75
|
+
response. Never embed the trigger, polling loops, release, and candidate read
|
|
76
|
+
in a single execution. Trigger and release are mutations: if the client asks
|
|
77
|
+
whether an execution changes data, identify them as writes, not read-only.
|
|
78
|
+
|
|
79
|
+
Generation waits on an external process. Do not put the entire generation in
|
|
80
|
+
one long-running function, an unbounded `while` loop, or a busy-wait. Trigger
|
|
81
|
+
once and return the flow ID immediately. Use separate, bounded status checks
|
|
82
|
+
for the same ID so each response is visible and you can act on its status.
|
|
83
|
+
A status check is one GET, not a loop that waits for a terminal state.
|
|
84
|
+
Use the client's supported waiting mechanism between checks; do not assume
|
|
85
|
+
that timers or sleep functions exist inside an API execution sandbox.
|
|
86
|
+
|
|
87
|
+
Continue across status checks while the flow is progressing. At
|
|
88
|
+
`KEYWORD_RESEARCH`, release it immediately once, then keep checking that same
|
|
89
|
+
flow until `SUCCESS` and read its candidates. Do not keep polling the parked
|
|
90
|
+
state instead of releasing it, or stop with only a promise to finish later.
|
|
91
|
+
If the client cannot continue waiting, report the flow ID and last observed
|
|
92
|
+
status honestly; that is an incomplete generation, not success.
|
|
93
|
+
|
|
94
|
+
## The exact call sequence
|
|
95
|
+
|
|
96
|
+
### 1. Trigger
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
POST /content-plan-flows/trigger
|
|
100
|
+
{}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Returns `{ "contentPlanFlowId": "..." }`. Return this response and end this
|
|
104
|
+
execution here. Save the ID in the conversation before making any status
|
|
105
|
+
request. Do not append step 2 to the trigger script.
|
|
106
|
+
|
|
107
|
+
### 2. Poll until KEYWORD_RESEARCH
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
GET /content-plan-flows/{contentPlanFlowId}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Execute this GET once and return its response. This execution contains no
|
|
114
|
+
`for`/`while` loop and no timer. Repeat it as a separate call when another
|
|
115
|
+
status check is needed. Keep the response compact: flow ID and status suffice.
|
|
116
|
+
|
|
117
|
+
The response is `{ "contentPlanFlow": { "id": "...", "status": "..." } }`.
|
|
118
|
+
Read `contentPlanFlow.status`, not a top-level `status`. A missing status is a
|
|
119
|
+
response-shape problem: inspect the response instead of silently looping.
|
|
120
|
+
`CREATED` alone does not identify a missing prerequisite. If the flow remains
|
|
121
|
+
there without progressing, report the stalled flow ID and observed status; do
|
|
122
|
+
not invent a missing business category or description.
|
|
123
|
+
Always send the trigger's ID when following this generation. The documented
|
|
124
|
+
omitted-ID behavior selects a previous successful flow, not the active flow;
|
|
125
|
+
it is not a way to discover the ID of a parked flow.
|
|
126
|
+
See [Get Content Plan Flow](https://dev.wix.com/docs/api-reference/business-management/seo/content-plan-content-plan-flow-v1/get-content-plan-flow).
|
|
127
|
+
|
|
128
|
+
Typical status progression: `CREATED` → `SITE_ANALYSIS` → `KEYWORD_RESEARCH`. Check every
|
|
129
|
+
few seconds using the bounded approach above. Completion time varies.
|
|
130
|
+
|
|
131
|
+
**Stop polling and act on these terminal states:**
|
|
132
|
+
- `PENDING_REQUIREMENTS` — the site has unmet prerequisites, such as missing
|
|
133
|
+
business location information. Identify the actual missing prerequisite from
|
|
134
|
+
available evidence; do not assume category or description is the cause.
|
|
135
|
+
Report what needs completing and do not repeatedly trigger new flows.
|
|
136
|
+
- `FAIL` — the pipeline failed. Trigger a new flow to retry.
|
|
137
|
+
- `CANCELED` — someone canceled the flow.
|
|
138
|
+
|
|
139
|
+
### 3. Release the flow
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
POST /create-content-plan
|
|
143
|
+
{ "contentPlanFlowId": "..." }
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
This advances the flow past `KEYWORD_RESEARCH`. Check `success` in the
|
|
147
|
+
response. If `false`, read `message`.
|
|
148
|
+
|
|
149
|
+
**Without this call the flow waits forever.**
|
|
150
|
+
|
|
151
|
+
### 4. Poll until SUCCESS
|
|
152
|
+
|
|
153
|
+
Same single-GET execution as step 2, returning after each check. Status walks
|
|
154
|
+
`CONTENT_PLAN` → `SUCCESS`. Read candidates in a subsequent execution after
|
|
155
|
+
observing `SUCCESS`.
|
|
156
|
+
|
|
157
|
+
### 5. Read the briefs
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
GET /content-plan-flows/{contentPlanFlowId}/blog-post-candidates
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Returns `{ "blogPostCandidates": [...] }`. Each candidate's brief fields are
|
|
164
|
+
nested under `briefData`, not at the candidate's top level. Map them directly:
|
|
165
|
+
|
|
166
|
+
```js
|
|
167
|
+
const topics = response.blogPostCandidates.map(candidate => ({
|
|
168
|
+
id: candidate.id,
|
|
169
|
+
title: candidate.briefData?.h1Title,
|
|
170
|
+
keyword: candidate.briefData?.keyword,
|
|
171
|
+
mainKeyword: candidate.briefData?.mainKeyword,
|
|
172
|
+
supportingPageUrl: candidate.briefData?.pageUrl
|
|
173
|
+
}));
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
`pageUrl` identifies the existing site page the proposed post supports; it is
|
|
177
|
+
not the URL of a newly published blog post. Generation creates briefs, not
|
|
178
|
+
published posts. Do not read `candidate.title`, `candidate.keyword`, or
|
|
179
|
+
`candidate.pageUrl`, or infer missing data from those nonexistent top-level
|
|
180
|
+
fields. If a nested field is absent, report it as unavailable and inspect the
|
|
181
|
+
raw candidate before making another request. Report the actual returned
|
|
182
|
+
titles and available keywords/supporting page URLs. Do not invent briefs or
|
|
183
|
+
claim completion from the release response.
|
|
184
|
+
See [List Blog Post Candidates](https://dev.wix.com/docs/api-reference/business-management/seo/content-plan-blog-post-candidate-v1/list-blog-post-candidates).
|
|
185
|
+
|
|
186
|
+
### Present the result
|
|
187
|
+
|
|
188
|
+
Start with the flow ID, observed `SUCCESS` status, and returned candidate count.
|
|
189
|
+
Use a compact table with one row per topic: suggested title, target keyword,
|
|
190
|
+
main keyword, and supporting page URL. Include the actual returned URL as a
|
|
191
|
+
link; do not merely say that each brief contains a URL. Avoid repeating SEO
|
|
192
|
+
titles and descriptions unless requested. If the answer must be shortened,
|
|
193
|
+
label the displayed subset and total explicitly instead of claiming to show all
|
|
194
|
+
topics. These are AI-generated suggestions; do not promise rankings or traffic.
|
|
195
|
+
Assess the returned topics before recommending them: if they are repetitive,
|
|
196
|
+
mostly restate the site name, or lack a clear connection to the site's business,
|
|
197
|
+
say so plainly. Successful generation does not establish editorial quality.
|
|
198
|
+
Still show the actual results; do not silently replace weak titles with invented
|
|
199
|
+
ones or call them optimized without evidence. Explain what business context
|
|
200
|
+
would help assess or refine them, without modifying the site's settings.
|
|
201
|
+
|
|
202
|
+
## Editing keywords (optional)
|
|
203
|
+
|
|
204
|
+
After step 2, before or after step 3, read the keywords:
|
|
205
|
+
|
|
206
|
+
```
|
|
207
|
+
GET /content-plan-keyword-research-items
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Edit one keyword (field-masked, only `keyword` and `main_keyword` writable):
|
|
211
|
+
|
|
212
|
+
```
|
|
213
|
+
PATCH /keyword-research-items/{itemId}
|
|
214
|
+
{
|
|
215
|
+
"keywordResearchId": "...",
|
|
216
|
+
"item": { "id": "...", "keyword": "new keyword" },
|
|
217
|
+
"fieldMask": "keyword"
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
**Copy-on-write:** the response may carry a different `keywordResearchId`.
|
|
222
|
+
Always use the one from the response for the next write. Edits are not
|
|
223
|
+
durable across generations.
|
|
224
|
+
|
|
225
|
+
## What this recipe adds over the docs
|
|
226
|
+
|
|
227
|
+
The published reference documents each method. This recipe adds:
|
|
228
|
+
|
|
229
|
+
1. **The parking gate.** The docs say `KEYWORD_RESEARCH` is a status. This
|
|
230
|
+
recipe says: the flow stops there until you call Create Content Plan.
|
|
231
|
+
Without that call, polling runs forever.
|
|
232
|
+
|
|
233
|
+
2. **PENDING_REQUIREMENTS handling.** This explicit status signals unmet
|
|
234
|
+
prerequisites. Report it and identify the missing requirement only from
|
|
235
|
+
evidence; do not infer it from a queued `CREATED` status or fill in business
|
|
236
|
+
information on the user's behalf.
|
|
237
|
+
|
|
238
|
+
3. **Copy-on-write on keyword edits.** The `keywordResearchId` can change
|
|
239
|
+
on the first write. Use the one from the response.
|
|
240
|
+
|
|
241
|
+
## Do not
|
|
242
|
+
|
|
243
|
+
- Poll forever without calling Create Content Plan (step 3).
|
|
244
|
+
- Read candidates before `SUCCESS`.
|
|
245
|
+
- Retry after `PENDING_REQUIREMENTS`.
|
|
246
|
+
- Ask for a site ID.
|
|
247
|
+
- Retry after a 403 — the caller lacks **Manage SEO Settings**.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: "Manage a Wix Site's SEO Tags"
|
|
3
|
-
description: Read and update
|
|
3
|
+
description: Read and update SEO titles and tags at the right level. For "change my site's SEO title", clarify homepage, specific page, or page-type pattern before discovery or writes; site-level tags accept meta tags only, never titles. Discover item IDs and pattern variables, read before every full-replace write, and report resolved tags with their sources.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Manage a Wix Site's SEO Tags
|
|
@@ -38,6 +38,21 @@ Match the user's request to the level that owns the change:
|
|
|
38
38
|
| "All my product/blog/event pages should be titled like X" — a convention for every item of a page type | Pattern | **SEO Patterns** |
|
|
39
39
|
| "Change the title of this page/product/post" — one specific item | Item | **Item SEO Tags** |
|
|
40
40
|
|
|
41
|
+
**Site SEO Tags accepts meta tags only** (including site-level social image
|
|
42
|
+
and robots settings). Never send `title`, `link`, or `script` tags to
|
|
43
|
+
`PATCH /site-seo-tags`. Use Item SEO Tags for a specific page's title, or
|
|
44
|
+
SEO Patterns for a page-type title convention. See the
|
|
45
|
+
[Site SEO Tags object](https://dev.wix.com/docs/api-reference/business-management/seo/site-seo-tags-v1/site-seo-tags-object).
|
|
46
|
+
|
|
47
|
+
If the user says "change my site's SEO title" without identifying a page or
|
|
48
|
+
page type, ask whether they mean the homepage, another specific page, or a
|
|
49
|
+
page-type title convention. Ask immediately after reading this recipe; do not make discovery or schema
|
|
50
|
+
queries until scope is clear. For an explicit
|
|
51
|
+
homepage request, discover its actual ID; never assume an ID such as `home`.
|
|
52
|
+
Use Item SEO Tags with `STATIC_PAGE`, read its current tags, and merge the title
|
|
53
|
+
into the complete set. Follow the static-page publication rules below.
|
|
54
|
+
Do not substitute `og:title` for the requested SEO title.
|
|
55
|
+
|
|
41
56
|
Work at the level that matches the change. Writing the same title onto many
|
|
42
57
|
items is the same outcome as one pattern and much harder to undo. If the user's
|
|
43
58
|
words fit more than one level, ask one short question before writing. An
|
|
@@ -84,7 +99,38 @@ No request body. Returns `itemSeoTags` with `tags`, `resolvedTags`,
|
|
|
84
99
|
|
|
85
100
|
### List Item SEO Tags — `GET /item-seo-tags/{itemType}?paging.limit=100`
|
|
86
101
|
|
|
87
|
-
No request body. Returns `
|
|
102
|
+
No request body. Returns `itemSeoTags[]` and `pagingMetadata` with cursors.
|
|
103
|
+
`itemSeoTagsList` is not a response field. Each array entry is an Item SEO Tags
|
|
104
|
+
object directly, not a wrapper: read `entry.itemId`, `entry.tags`, and
|
|
105
|
+
`entry.resolvedTags`, not `entry.itemSeoTags`. Use `itemId` as the path ID;
|
|
106
|
+
`id` is a composite identifier and `hostPageId` is not the item identifier.
|
|
107
|
+
|
|
108
|
+
For static-page discovery, call this with `STATIC_PAGE`. Example response:
|
|
109
|
+
|
|
110
|
+
```json
|
|
111
|
+
{
|
|
112
|
+
"itemSeoTags": [
|
|
113
|
+
{
|
|
114
|
+
"itemType": "STATIC_PAGE",
|
|
115
|
+
"itemId": "<page-id>",
|
|
116
|
+
"tags": [],
|
|
117
|
+
"resolvedTags": [
|
|
118
|
+
{ "tag": { "type": "title", "children": "Home | Studio Shop" },
|
|
119
|
+
"source": "TAG_SOURCE_DEFAULT_PATTERN" }
|
|
120
|
+
]
|
|
121
|
+
}
|
|
122
|
+
],
|
|
123
|
+
"pagingMetadata": { "hasNext": false }
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Inspect the returned page identities and resolved tags to identify the requested
|
|
128
|
+
page, then Get that exact `itemId` before writing. If the response does not
|
|
129
|
+
unambiguously identify it, ask the user to identify the page. Do not interpret
|
|
130
|
+
a missing response field as an empty page list, assume the first entry is the
|
|
131
|
+
homepage, or create/update a pattern as a fallback for a missing page. A
|
|
132
|
+
single-page request never authorizes changing all pages of its type.
|
|
133
|
+
See [List Item SEO Tags](https://dev.wix.com/docs/api-reference/business-management/seo/item-seo-tags-v1/list-item-seo-tags).
|
|
88
134
|
|
|
89
135
|
### Set Site SEO Tags — `PATCH /site-seo-tags`
|
|
90
136
|
|
|
@@ -255,8 +301,9 @@ issue another Get — the write response is the confirmation.
|
|
|
255
301
|
- **Calling List Item SEO Tags expecting product names.** List returns IDs
|
|
256
302
|
and tags, not names. Use Search Products to find the ID by name first.
|
|
257
303
|
- **Retrying a 400 with a different request shape without checking why.** A 400
|
|
258
|
-
|
|
259
|
-
|
|
304
|
+
can mean the target level is wrong, not just the shape. Read the validation
|
|
305
|
+
message and check the level rules first. Compare against the shapes in this
|
|
306
|
+
recipe, fix the mismatch, send once. Three retries with guessed shapes is three wasted calls.
|
|
260
307
|
|
|
261
308
|
Tags can currently be written only for the site's primary language: leave
|
|
262
309
|
`language` unset on every write. There is no revision checking — the last write
|
|
@@ -298,12 +345,18 @@ success.
|
|
|
298
345
|
- **`UNSUPPORTED_ITEM_TYPE`:** the error message lists the item types the API
|
|
299
346
|
supports; use it to redirect the request rather than retrying blindly.
|
|
300
347
|
- **`ITEM_NOT_FOUND`:** re-discover the item ID; do not guess a new one.
|
|
348
|
+
- **Unsupported site-level tag / `FIELD_NOT_ALLOWED`:** a rejected `title`,
|
|
349
|
+
`link`, or `script` is a wrong-level error, not a nesting or field-mask error.
|
|
350
|
+
Do not retry it at site level or silently drop the requested tag. Clarify the
|
|
351
|
+
target if needed, then use the appropriate item or pattern API. Get that
|
|
352
|
+
target's current tags before merging and writing; never reuse the site's
|
|
353
|
+
tags as the new target's complete set. A rejected write saved no changes.
|
|
301
354
|
- **Invalid tags:** tags are validated before anything is saved, so nothing
|
|
302
355
|
changed; fix the tag and resend the same complete set.
|
|
303
356
|
- **`400` on a request you built from this recipe:** compare the request you
|
|
304
357
|
sent against the shapes in this recipe's "REST request and response shapes"
|
|
305
|
-
section. Fix the mismatch — a wrong
|
|
306
|
-
`fieldMask` sent as an array instead of a string — and send again. Never
|
|
358
|
+
section and the wrong-level recovery rule above. Fix the mismatch — a wrong
|
|
359
|
+
nesting level, a missing wrapper key, or `fieldMask` sent as an array instead of a string — and send again. Never
|
|
307
360
|
resend the same shape, and never walk through variations hoping one is
|
|
308
361
|
accepted.
|
|
309
362
|
- **Setting tags for `EVENTS_PAGE` items:** not supported yet, although reading
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "Change Store Currency"
|
|
3
|
+
description: "Changes the store's payment currency through Site Properties and explains delayed currency updates in catalog responses."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Change Store Currency
|
|
7
|
+
|
|
8
|
+
Use the [Site Properties currency recipe](https://dev.wix.com/docs/api-reference/business-management/site-properties/skills/change-payment-currency-site-properties.md) to set the requested payment currency and read it back. Confirm the change with the user before updating it.
|
|
9
|
+
|
|
10
|
+
Catalog product responses may temporarily show the previous currency after carts and checkout use the new one. Allow time for propagation, then recheck.
|