23 "note": "The store's own address lives in the general settings group as woocommerce_store_address / _address_2 / _city / _postcode / woocommerce_default_country. Two traps: the REST index advertises only the PARAMETERIZED form /wc/v3/settings/(?P<group>...), so the group must be read directly; and the WooCommerce consumer key 401s here while the WordPress application password succeeds. See rp-source-wordpress's SKILL.md."
34 "decision": "A site-wide singleton, applied at the setup gate as configuration -- not a per-record import. Permission SITE_PROPERTIES.UPDATE_BUSINESS_CONTACT, scope SCOPE.DC-SITEPROP.MANAGE-BUSINESS-CONTACT. Read back with GET /site-properties/v4/properties, which is a separate call because the update returns an empty body."
44 "summary": "`fields.paths[]` is destructive in one direction: a property NAMED in the mask but ABSENT from `businessContact` is CLEARED. Migrating only an address therefore means sending paths ['address'] and nothing more -- adding 'email','phone','fax' to be thorough wipes contact details the merchant may already have entered by hand. Build the mask from the payload's own keys. Wix's own documented example is itself unsafe to copy: it lists 'businessSchedule' in paths while sending none."
49 "summary": "Wix takes `country` (ISO 3166-1 alpha-2) and `state` as separate fields. WooCommerce packs both into one setting: `woocommerce_default_country` is either `IL` or `COUNTRY:STATE` (e.g. `US:CA`). Split on the colon -- the same encoding a WooCommerce shipping zone's `state`-type location uses, so shipping-build.js already carries the parse. Sending `US:CA` as `country` does not error; it just stores a country code that matches nothing."
54 "summary": "The object has separate `street` and `streetNumber` fields, which invites splitting the source's single address line. Do not. WooCommerce's `woocommerce_store_address` is one free-text field with no structure guarantee -- some shops put the number first, some last, some have no number at all (a store address can be a street name only). Put the whole source line in `street`, leave `streetNumber` empty, and let the merchant correct it. A wrong split is worse than no split: it looks deliberate."
59 "summary": "`zip` is capped at 20 characters; WooCommerce's `woocommerce_store_postcode` is unbounded free text. Guard the length rather than letting the API reject the whole write for one long field."
64 "summary": "The response body is `{}`. A 200 proves the request was accepted, not that the address is stored as intended -- and given the clearing behaviour above, a call can succeed while having wiped a sibling field. Always follow a write with GET /site-properties/v4/properties and compare what came back. CONFIRMED LIVE 2026-09-01: an address-only write returned {} and the follow-up read showed the address stored exactly as sent, with the site's other contact fields untouched."
69 "summary": "`coordinates` and `googleFormattedAddress` are real fields with no WooCommerce counterpart. Omit them rather than geocoding: a migration that silently invents a latitude/longitude is asserting a precision the source never had. Wix resolves display formatting itself."
70 }
71 ],
72 "mappingGuidance": [
73 "Field map: woocommerce_store_address -> street (whole line, unparsed); woocommerce_store_address_2 -> apartmentNumber; woocommerce_store_city -> city; woocommerce_store_postcode -> zip (truncate-guard at 20); woocommerce_default_country -> country, plus state when the value is COUNTRY:STATE. Set isPhysical true -- a shop's registered address is a real place. Omit coordinates and googleFormattedAddress.",
74 "Send `fields.paths` built from the keys actually present on the payload, never a fixed list. See this file's first pitfall; it is the one mistake here that destroys data rather than failing loudly.",
75 "This is the site's OWN address. It is NOT a pickup address, and must never be used as one without a human confirming it -- a shop's registered address and the place customers collect from are routinely different (they can sit in different towns). ecom/pickup-location may OFFER this value as a default to confirm; it may not adopt it.",
76 "Apply at the setup gate with the other configuration, and read back afterwards. An absent business address on the destination is the normal starting state, not evidence of a failed earlier write."
77 ],
78 "setupRequirements": [],
79 "objectPageException": "Site Properties is modelled as a property stream with per-group update methods rather than as a fetchable object with its own '…-object' reference page; the API-reference tree exposes Update Business Contact / Profile / Schedule / Consent Policy and a single Get Properties read, with no object page for BusinessContactData. The field shape here is taken from the Update Business Contact method schema.",
89 "note": "Site Properties as the single source of truth for the site's public business information"
90 },
91 {
92 "type": "live-verification",
93 "path": "anonymized-live-verification",
94 "note": "GET /site-properties/v4/properties on a fresh site returned only locale/currency/timezone with no business address key present"
95 },
96 {
97 "type": "live-run",
98 "path": "anonymized-live-verification",
99 "note": "2026-09-01: a site whose business address was entirely blank (street/city/zip empty, isPhysical false) was populated by an address-only update. Read-back matched the payload field for field; email and phone were absent before and after, confirming the derived field mask cleared nothing."
100 }
101 ],
102 "notes": "Authored 2026-09-01 to close an unowned gap: nothing in the pipeline had ever written a business address, so every migrated site published with the field empty, and ecom/pickup-location needed an address with no target entity to point at. Write path VERIFIED LIVE the same day against a site whose address was blank."