Widget types
Widgets come in three types based on behavior. Type is not a merchant-selected field — it’s derived from Placement — picking an anchor decides the type.
The three types
Section titled “The three types”| Internal name | English | Derivation condition (placement.auto.anchor) | Typical scenarios |
|---|---|---|---|
complex | Complex | Any non-label, non-float anchor (product page / cart / footer / etc.) | Trust badges / coupons / button groups — most cases |
floating | Floating | float_top / float_bottom / float_left / float_right | Viewport-edge floating quick links / icons |
label | Label | placement.auto.anchor === "label" | Product image overlay (small chip on product images) |
Derivation via the getWidgetType(config) helper:
getWidgetType(config): anchor = config.placement.auto.anchor if (anchor === "label") return "label" if (isFloatAnchor(anchor)) return "floating" return "complex"Type-specific characteristics
Section titled “Type-specific characteristics”| Aspect | complex | floating | label |
|---|---|---|---|
| Mount mechanism | DOM cascade (per auto-placement 65-theme matrix) | body child + position:fixed | Product image host (collection card / PDP main image) |
| Component count | Multiple (content[] arbitrary tree) | Multiple | 1 label_chip item (audit-enforced) |
| Container fields | Full container | Full container + floatOffset | LabelChip-specific fields |
| Editor ContentPanel | Component list (multi-component tree) | Component list | AnchorPicker + single chip editor |
| Display tab dimensions | All 9 + UTM | All 9 + UTM | 9 + scope (PDP / Cards / Both) |
Cross-type switching: hidden prohibition
Section titled “Cross-type switching: hidden prohibition”The editor does not allow switching anchor between label and non-label. Reasons:
- label widget’s components are forced to 1
label_chip - complex / floating components are arbitrary trees
- The two schemas are incompatible; auto-migration risks data loss
Server-side guards: widget-type-derived-audit.mjs + server-side widget type lock detection (with D1 transient retry). PR / save with cross-type payload is rejected.
To change type → rebuild a new widget (cross-type duplicate is also disallowed).
Wizard’s template ↔ widget type double enforcement
Section titled “Wizard’s template ↔ widget type double enforcement”To prevent “merchant picks ‘Product image overlay’ placement then chooses ‘Badge group’ template (incompatible)”, the wizard enforces compatibility at two layers:
- manifest filter (frontend) — after picking a placement, the template list auto-filters to compatible presets
- server validate (backend) — submission re-validates placement × template compatibility on the server; incompatible payloads are rejected
Lifecycle relationship
Section titled “Lifecycle relationship”The lifecycle state machine is essentially the same across the three types (pending / published / unpublished / scheduled / expired / hidden / error / custom), but trigger conditions differ:
errortriggers vary by type (e.g. label fails to find a theme selector)- floating rarely triggers DOM-related
error(doesn’t depend on cascade — self-contained surface)