Created
February 22, 2026 09:32
-
-
Save saggy-rakholiya/a902b1cc6afb2e038c75e7bfa8dfbc75 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "type": "header", | |
| "content": "Upsell Settings" | |
| }, | |
| { | |
| "type": "text", | |
| "id": "upsell_heading", | |
| "label": "Upsell Heading", | |
| "default": "You may also like" | |
| }, | |
| { | |
| "type": "select", | |
| "id": "upsell_source", | |
| "label": "Upsell Source", | |
| "options": [ | |
| { "value": "manual", "label": "Manual Selection" }, | |
| { "value": "dynamic", "label": "Dynamic Recommendations" } | |
| ], | |
| "default": "manual" | |
| }, | |
| { | |
| "type": "product_list", | |
| "id": "upsell_products", | |
| "label": "Select Upsell Products", | |
| "limit": 4 | |
| } | |
| {% comment %} Cart Upsell {% endcomment %} | |
| {% liquid assign source = settings.upsell_source %} | |
| {% if source == 'manual' and settings.upsell_products != blank %} | |
| {% assign products_to_show = settings.upsell_products %} | |
| {% endif %} | |
| {% if source == 'manual' and products_to_show != blank %} | |
| <div class="cart-drawer-upsell"> | |
| <h3>{{ settings.upsell_heading }}</h3> | |
| <ul class="grid grid--2-col"> | |
| {% for product in products_to_show limit: 4 %} | |
| {% assign variant = product.first_available_variant %} | |
| {% if variant %} | |
| <li class="grid__item"> | |
| {% if product.featured_media %} | |
| <div class="cart-drawer-media"> | |
| <img | |
| src="{{ product.featured_media | image_url: width: 100 }}" | |
| alt="{{ product.featured_media.alt }}" /> | |
| </div> | |
| {% endif %} | |
| <div class="cart-drawer-content"> | |
| <h3 class="h5">{{ product.title | escape }}</h3> | |
| <button | |
| type="button" | |
| class="button button--secondary button--full-width upsell-add-btn" | |
| data-variant-id="{{ variant.id }}" | |
| {% unless product.available %}disabled{% endunless %} | |
| > | |
| {% if product.available %} | |
| Add to cart | |
| {% else %} | |
| Sold out | |
| {% endif %} | |
| </button> | |
| </div> | |
| </li> | |
| {% endif %} | |
| {% endfor %} | |
| </ul> | |
| </div> | |
| {% endif %} | |
| {% if settings.upsell_source == 'dynamic' and cart.items.size > 0 %} | |
| <div class="cart-drawer-upsell"> | |
| <h3>{{ settings.upsell_heading }}</h3> | |
| <ul id="DynamicUpsellContainer" class="grid grid--2-col"></ul> | |
| </div> | |
| {% endif %} | |
| <script> | |
| document.addEventListener('click', function(e) { | |
| const btn = e.target.closest('.upsell-add-btn'); | |
| if (!btn) return; | |
| const variantId = btn.dataset.variantId; | |
| if (!variantId) return; | |
| btn.disabled = true; | |
| btn.textContent = 'Adding...'; | |
| fetch('/cart/add.js', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify({ | |
| id: variantId, | |
| quantity: 1 | |
| }) | |
| }) | |
| .then(() => fetch('/?sections=cart-drawer')) | |
| .then(res => res.json()) | |
| .then(data => { | |
| const parser = new DOMParser(); | |
| const doc = parser.parseFromString(data['cart-drawer'], 'text/html'); | |
| const newDrawer = doc.querySelector('cart-drawer'); | |
| document.querySelector('cart-drawer').innerHTML = newDrawer.innerHTML; | |
| }) | |
| .catch(err => console.error('Upsell error:', err)); | |
| }); | |
| </script> | |
| {% if settings.upsell_source == 'dynamic' and cart.items.size > 0 %} | |
| <script> | |
| document.addEventListener("DOMContentLoaded", function () { | |
| const container = document.getElementById("DynamicUpsellContainer"); | |
| if (!container) return; | |
| const productId = {{ cart.items.first.product.id }}; | |
| fetch(`/recommendations/products.json?product_id=${productId}&limit=4&intent=related`) | |
| .then(res => res.json()) | |
| .then(data => { | |
| if (!data.products) return; | |
| data.products.forEach(product => { | |
| const variant = product.variants.find(v => v.available); | |
| if (!variant) return; | |
| const item = ` | |
| <li class="grid__item"> | |
| ${product.featured_image ? ` | |
| <div class="cart-drawer-media"> | |
| <img src="${product.featured_image}" /> | |
| </div> | |
| ` : ''} | |
| <div class="cart-drawer-content"> | |
| <h3 class="h5">${product.title}</h3> | |
| <button | |
| type="button" | |
| class="button button--secondary button--full-width upsell-add-btn" | |
| data-variant-id="${variant.id}"> | |
| Add to cart | |
| </button> | |
| </div> | |
| </li> | |
| `; | |
| container.insertAdjacentHTML("beforeend", item); | |
| }); | |
| }); | |
| }); | |
| </script> | |
| {% endif %} | |
| <style> | |
| .cart-drawer-upsell { | |
| border-top: 1px solid rgba(0,0,0,.1); | |
| } | |
| .cart-drawer-upsell .grid__item { | |
| width: 100%; | |
| max-width: 100%; | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| padding-right: 10px; | |
| } | |
| .cart-drawer-media { | |
| width: 90px; | |
| } | |
| .cart-drawer-content { | |
| flex: 1; | |
| } | |
| .cart-drawer-upsell .h5{margin-top: 0;} | |
| .cart-drawer-media img{max-width: 100%; width: 100%;} | |
| </style> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment