Skip to content

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.

Internal nameEnglishDerivation condition (placement.auto.anchor)Typical scenarios
complexComplexAny non-label, non-float anchor (product page / cart / footer / etc.)Trust badges / coupons / button groups — most cases
floatingFloatingfloat_top / float_bottom / float_left / float_rightViewport-edge floating quick links / icons
labelLabelplacement.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"
Aspectcomplexfloatinglabel
Mount mechanismDOM cascade (per auto-placement 65-theme matrix)body child + position:fixedProduct image host (collection card / PDP main image)
Component countMultiple (content[] arbitrary tree)Multiple1 label_chip item (audit-enforced)
Container fieldsFull containerFull container + floatOffsetLabelChip-specific fields
Editor ContentPanelComponent list (multi-component tree)Component listAnchorPicker + single chip editor
Display tab dimensionsAll 9 + UTMAll 9 + UTM9 + scope (PDP / Cards / Both)

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:

  1. manifest filter (frontend) — after picking a placement, the template list auto-filters to compatible presets
  2. server validate (backend) — submission re-validates placement × template compatibility on the server; incompatible payloads are rejected

The lifecycle state machine is essentially the same across the three types (pending / published / unpublished / scheduled / expired / hidden / error / custom), but trigger conditions differ:

  • error triggers 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)