Membership Cart Drawer Upsell with Dynamically Calculated Cashback: Implementation Guide

File Structure

File
Purpose

snippets/membership-upsell.liquid

Renders the upsell block inside the cart drawer

assets/membership-upsell.js

Handles AJAX add-to-cart and drawer refresh

Step 1: Create the Snippet

In the Snippets folder of your theme, create a new file called membership-upsell.liquid

Then, paste the following code:

{%- comment -%}
Adjust this percentage to reflect your actual cashback offer.
{%- endcomment -%}
{% assign cashback_percentage = 20 %}
{% assign cashback_amount = cart.total_price | times: cashback_percentage | divided_by: 100 %}

<div class="drawer-membership-upsell">
  <h3 class="drawer-upsell-heading">Become a Member</h3>
  <p class="drawer-upsell-subheading">Join now to unlock your benefits</p>

  <ul class="drawer-benefits">
    {%- comment -%}
    Customize the list of membership benefits below to reflect your actual offering.
    These items are placeholder examples — replace them with your own benefits.
    {%- endcomment -%}
    <li>
      <strong>{{ cashback_percentage }}% Cashback</strong>
      {% if cart.item_count > 0 %}
        <span class="drawer-cashback-amount">
          ({{ cashback_amount | money }} on today's order!)
        </span>
      {% endif %}
    </li>
    <li>Free Shipping</li>
    <li>Exclusive Product Access</li>
    <li>Member-Only Discounts</li>
    <li>$10 Birthday Credit</li>
    <li>Priority Support</li>
  </ul>

  <button
    class="drawer-upsell-button"
    data-membership-variant="REPLACE_WITH_VARIANT_ID"  <!-- Replace with your membership product's variant ID -->
    data-membership-selling-plan="REPLACE_WITH_SELLING_PLAN_ID">  <!-- Replace with your selling plan ID -->
    Join Now for $10 Annually!  <!-- Replace with your price & CTA -->
  </button>
</div>

{%- comment -%}
Ensure this script is included so the JS functionality is loaded when the snippet renders.
{%- endcomment -%}
<script type="module" src="{{ 'membership-upsell.js' | asset_url }}"></script>

Step 2: Create the JavaScript File

In the assets folder of your theme, create a new file called membership-upsell.js

Then, paste the following code:

document.addEventListener('click', async (event) => {
  const btn = event.target.closest('.drawer-upsell-button');
  if (!btn || btn.disabled) return;

  const variantId = parseInt(btn.dataset.membershipVariant);
  const sellingPlanId = parseInt(btn.dataset.membershipSellingPlan);

  const payload = {
    items: [{
      id: variantId,
      quantity: 1
    }]
  };

  if (!isNaN(sellingPlanId)) {
    payload.items[0].selling_plan = sellingPlanId;
  }

  btn.disabled = true;
  const originalText = btn.textContent;
  btn.textContent = 'Adding...';

  try {
    const res = await fetch('/cart/add.js', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json'
      },
      body: JSON.stringify(payload)
    });

    if (!res.ok) throw new Error('Cart add failed');

    const cart = await fetch('/cart.js').then(r => r.json());
    const exists = cart.items.find(item => item.variant_id === variantId);
    if (!exists) throw new Error('Membership not found in cart');

    btn.textContent = 'Added!';
    const upsell = btn.closest('.drawer-membership-upsell');
    if (upsell) setTimeout(() => upsell.remove(), 400);

    const drawerRes = await fetch(window.location.pathname + '?sections=cart-drawer');
    const html = await drawerRes.text();
    const parser = new DOMParser();
    const doc = parser.parseFromString(html, 'text/html');
    const newDrawer = doc.querySelector('.cart-drawer');
    const currentDrawer = document.querySelector('.cart-drawer');
    if (newDrawer && currentDrawer) {
      currentDrawer.innerHTML = newDrawer.innerHTML;
    }

  } catch (err) {
    console.error('[Membership Upsell Error]', err);
    btn.textContent = 'Error';
    alert('Could not add membership.');
  }

  setTimeout(() => {
    btn.textContent = originalText;
    btn.disabled = false;
  }, 2000);
});

Step 3: Add the Snippet to the Cart Drawer

In your theme’s code editor open the file: snippets/cart-drawer.liquid

Find this section of the code:

<scroll-hint class="cart-drawer__items">
  {% render 'cart-products' %}
</scroll-hint>

<div class="cart-drawer__summary">
  {% render 'cart-summary' %}
</div>

Insert the upsell snippet above the cart summary block, like so:

<scroll-hint class="cart-drawer__items">
  {% render 'cart-products' %}
</scroll-hint>



<div class="cart-drawer__summary">
  {% render 'cart-summary' %}
</div>

Step 4: Style with CSS

Add this to your main stylesheet (theme.css, base.css, or equivalent), or inline within the snippet, and customize to your branding needs. All current values are placeholders and should be replaced to match your branding needs:

.drawer-membership-upsell {
  background: #f5f0ff;
  padding: 16px;
  margin: 16px 0;
  border-radius: 6px;
  font-size: 14px;
}

.drawer-upsell-heading {
  font-size: 16px;
  font-weight: 600;
}

.drawer-upsell-subheading {
  font-size: 13px;
  margin-bottom: 10px;
  color: #666;
}

.drawer-benefits {
  list-style: none;
  padding: 0;
  margin: 0 0 12px;
}

.drawer-upsell-button {
  width: 100%;
  background: #7b3fdb;
  color: white;
  padding: 10px 0;
  border-radius: 4px;
  font-weight: 600;
  border: none;
  cursor: pointer;
}

.drawer-upsell-button:hover {
  background: #5f2bbb;
}

.drawer-cashback-amount {
  font-weight: 600;
  color: #7b3fdb;
  margin-left: 4px;
}

Once all of the above is implemented & styled, your cart upsell will appear in the cart drawer - visually looking similar to this - but matching the CSS styling that you have adjusted to match your needs:

Functionally, the cart upsell will automatically calculate the cashback amount based on your cart total & the percentage you have defined in the snippet (note: this implementation assumes that you provide credits for orders/cashback on all products). The cart upsell will be present if a membership product has not been added to cart. If the membership product has been added to cart, the upsell will no longer be visible.

Last updated

Was this helpful?