Theme mount points
Horizon needs these slots
Cart and policy embeds do not inject themselves into a stock Horizon theme. They copy their UI into empty elements the theme renders. Add the Liquid below once per theme. Turning an embed off hides that UI; the empty slots can stay.
Rules
- Use
data-vendr-cart-context="drawer"in the cart drawer and"page"on the cart page. Each embed’s Show in Cart Drawer and Show on Cart page settings follow that value. - Keep
data-skip-subtree-updateon the cart hosts so Horizon’s cart refresh does not wipe the live widget. The summary host is the exception: attributes go on the existing summary wrapper, which already contains.cart-totals. - Put drawer hosts in the non-empty cart branch, in the same order as below. Horizon only morphs markup the server still renders.
- Render the subscription host only on lines that can subscribe. A host with no matching template makes the cart refresh loop.
Cart drawer
snippets/cart-drawer.liquid, inside the non-empty scroll-hint.cart-drawer__content. Free shipping and the gifts progress bar sit above the line items. The gifts picker and upsell sit inside .cart-drawer__items, after the products. Shipping estimate uses the summary wrapper.
snippets/cart-drawer.liquid
<div
data-vendr-cart-header
data-vendr-cart-context="drawer"
data-skip-subtree-update
></div>
{%- comment -%} VENDR — App embed mount (free gifts progress bar). {%- endcomment -%}
<div
data-vendr-cart-gifts-bar
data-vendr-cart-context="drawer"
data-skip-subtree-update
></div>
<scroll-hint class="cart-drawer__items">
{% render 'cart-products', context: 'drawer' %}
{%- comment -%} VENDR — App embed mount (free gifts picker). {%- endcomment -%}
<div
data-vendr-cart-gifts
data-vendr-cart-context="drawer"
data-skip-subtree-update
></div>
<div
data-vendr-cart-upsell
data-vendr-cart-context="drawer"
data-skip-subtree-update
></div>
</scroll-hint>
<div
class="cart-drawer__summary"
data-vendr-cart-summary
data-vendr-cart-context="drawer"
>
{% render 'cart-summary', section_id: 'cart-drawer-section' %}
</div>Without the gifts slots, the app inserts them above the drawer title. The Liquid above is the placement to keep.
Cart subscription
snippets/cart-products.liquid, in place of the selling-plan name inside .cart-items__variants-wrapper. The same snippet serves the drawer and the cart page; context sets the host.
snippets/cart-products.liquid
{%- comment -%}
VENDR — App embed mount (cart subscription). Only for lines that can subscribe;
otherwise mount treats missing templates as "needs /cart refresh" and loops.
data-skip-subtree-update keeps the live picker across in-place cart morphs.
{%- endcomment -%}
{%- if item.variant.selling_plan_allocations.size > 0 and item.parent_relationship.parent == null -%}
<div
data-vendr-cart-line
data-vendr-cart-context="{% if context == 'drawer' %}drawer{% else %}page{% endif %}"
data-line-key="{{ item.key | escape }}"
data-variant-id="{{ item.variant_id }}"
data-vendr-expects-subscription="true"
data-skip-subtree-update
>
{%- if context != 'drawer' and item.selling_plan_allocation -%}
<p class="cart-items__selling-plan">
{{ item.selling_plan_allocation.selling_plan.name }}
</p>
{%- endif -%}
</div>
{%- elsif context != 'drawer' and item.selling_plan_allocation -%}
<p class="cart-items__selling-plan">
{{ item.selling_plan_allocation.selling_plan.name }}
</p>
{%- endif -%}Cart page
sections/main-cart.liquid, inside .cart-page__main. Same widgets as the drawer, with data-vendr-cart-context="page". Show on Cart page must be on for an embed to fill these.
sections/main-cart.liquid
<div class="cart-page__main">
<div
data-vendr-cart-header
data-vendr-cart-context="page"
data-skip-subtree-update
></div>
{%- comment -%} VENDR — App embed mount (free gifts progress bar). {%- endcomment -%}
<div
data-vendr-cart-gifts-bar
data-vendr-cart-context="page"
data-skip-subtree-update
></div>
<div class="cart-page__items">
{%- content_for 'block', id: 'cart-page-items', type: '_cart-products' %}
</div>
{%- comment -%} VENDR — App embed mount (free gifts picker). {%- endcomment -%}
<div
data-vendr-cart-gifts
data-vendr-cart-context="page"
data-skip-subtree-update
></div>
<div
data-vendr-cart-upsell
data-vendr-cart-context="page"
data-skip-subtree-update
></div>
</div> Add the summary attributes to the existing cart summary block. Shipping estimate prepends into .cart-totals inside it.
blocks/_cart-summary.liquid
<div
class="cart-summary border-style"
data-vendr-cart-summary
data-vendr-cart-context="page"
{{ block.shopify_attributes }}
>Policies Nav
layout/theme.liquid, as the first child of main. The embed replaces this host on policy pages. If the host is missing, the script prepends to main instead.
layout/theme.liquid
<main id="MainContent" class="content-for-layout" role="main">
<div data-vendr-policies-nav></div>