Anchors and cascade table
Merchant view: 7 cards
Section titled “Merchant view: 7 cards”| Card | Data-layer anchor / mode | Behavior |
|---|---|---|
| Product page | auto_product | Mounts near product page ATC (system picks specific position) |
| Footer | auto_above_footer / auto_below_footer | Two buttons within the card, choose one |
| Floating Icons | float_top / float_bottom / float_left / float_right | 4 edges within the card |
| Cart Drawer | auto_cart_drawer | Mounts to cart drawer |
| Cart Page | auto_cart | Mounts to cart page |
| Custom Position | mode: "manual" | Merchant places via manual block in theme editor |
| Product image overlay | auto.anchor: "label" | Product image overlay (Label widget) |
Data layer = 9 MVP anchor values (5 sentinels + 4 float edges) + label, UI folded into 6 + 1 = 7 cards.
Cascade table
Section titled “Cascade table”auto_* sentinels try DOM selectors in cascade order; the first match mounts:
AUTO_CASCADE_BY_ANCHOR = { auto_product: ["below_add_to_cart", "below_price", "below_gallery"], auto_cart: ["cart_top"], auto_cart_drawer: ["drawer_top"], auto_above_footer: ["above_footer"], auto_below_footer: ["below_footer"], auto_footer: ["footer_top"], // legacy, backward compat}Cascade order = “most stable Shopify platform feature” to “most theme-specific selector”. auto_product puts ATC first because form[action*="/cart/add"] is the most reliable cross-theme contract.
Float anchors don’t go through cascade — directly body child + position:fixed (self-contained surface).
Complete anchor list (incl. internal)
Section titled “Complete anchor list (incl. internal)”Merchant-selectable: see “7 cards” above.
Internal cascade-only anchors (schema-legal, old widgets storing them still work, but editor UI doesn’t surface them):
| Anchor key | Meaning |
|---|---|
below_price | Below price |
below_add_to_cart | Below ATC button |
below_gallery | Below product gallery |
above_price | Above price |
above_add_to_cart | Above ATC button |
below_title | Below product title |
above_title | Above product title |
below_description | Below product description |
cart_top | Cart top |
drawer_top | Cart drawer top |
above_footer | Above footer |
footer_top | Footer inner top (legacy) |
below_footer | Below footer |
float_top_left / float_top_right / float_bottom_left / float_bottom_right | Float corner variants |
Legacy auto_footer
Section titled “Legacy auto_footer”Split into auto_above_footer + auto_below_footer on 2026-04-24. Old widgets storing auto_footer still work (mapped to footer_top cascade), but new widgets don’t emit this value.
Theme overrides
Section titled “Theme overrides”5 paid themes have product form structures that normal cascade can’t align with Hoppy insertion points; hard-coded overrides apply:
| schema_name | Override behavior |
|---|---|
| Savor / Atelier (Shopify Horizon family) | Mount after [class*="shopify-payment-button"] |
| Beyond | After form’s 7th child = ATC block |
| Maker | After form’s 8th child |
| Editions | After form’s 3rd child |
Override target lookup is scoped to anchorNode.closest('form[action*="/cart/add"]') — no global document.querySelector fallback (prevents matching wrong elements).
customAnchorSelectors (escape hatch)
Section titled “customAnchorSelectors (escape hatch)”When the merchant’s theme isn’t in the built-in 65-theme list, fill customAnchorSelectors in Display tab advanced section to override:
{ "product": ["#alt-buy-button-region"], "productList": [], "productMedia": [], "exclude": [".competitor-badge"]}| Field | Purpose |
|---|---|
product | Product page widget mount location (highest priority, beats 65-theme defaults) |
productList | Each product card on collection / search / recommendation pages |
productMedia | Image / media slot inside product cards (overlay widget on image) |
exclude | Block these scenes / exclude theme-native conflicting positions |
Max 24 selectors per widget. Merchant-supplied selectors are merged into rules.js as virtual candidates with weight 50 (beats any hardcoded candidate).
65-theme selector matrix
Section titled “65-theme selector matrix”The system bundles a ~65-theme DOM selector matrix (built via theme-probe live testing). Adding new themes requires probe-first observation, code-second.
Full theme list and per-theme behavior in source docs/theme-selectors.md.
Diagnostics: actual hit anchor
Section titled “Diagnostics: actual hit anchor”Merchants can see the actual hit anchor in the Display tab StickyBar diagnostic panel — useful for debugging “widget didn’t appear at expected location”.
Diagnostic state writes to window.__TTB_DIAGNOSTICS__[widgetId] — also visible in browser console on storefront.