social-open-icon
social-close-icon
Facebook Instagram Linkedin twitter Youtube teams

Shopify Product Add-ons Without JavaScript: Complete Step-by-Step Guide

In today’s eCommerce world, increasing order value without hurting user experience is essential. Product add-ons make it easy for customers to buy complementary items directly from the product page.

Instead of relying on heavy apps or JavaScript, a smarter approach is to build add-ons using Shopify’s native features. If you want a scalable and optimized solution, it’s always best to hire shopify developers who understand performance-focused implementation.

In this guide, you’ll learn how to create fast, flexible Shopify product add-ons using only Liquid, metafields, and schema no JavaScript required.

1. What is a Product Add-on

A product add-on is an additional product that customers can select along with the main product directly from the product page.

It allows users to include complementary or bundled items in a single purchase without leaving the page.

Key idea:

  • Multiple products are added together in one form submission

2. Why Use Product Add-ons

Product add-ons are used to improve both business performance and customer experience.

Important Benefits:

  • Increase Average Order Value (AOV)
  • Encourage bundle purchases
  • Simplify buying process
  • Improve conversion rate

3. Implementation Without JavaScript (Core Concept)

This solution works using Shopify’s native form structure, making it highly efficient and lightweight something every professional shopify agency focuses on when optimizing stores.

Key Mechanism:

  • Use items[index][id]
  • Pass variant IDs directly through the product form
  • No JavaScript required

Important:

  • Each checkbox represents a product variant
  • Selected items are added together with the main product

4. Method 1: Product-specific Add-ons (Metafields)

Used when add-ons are different for each product.

Metafield Setup:

  • Namespace: custom
  • Key: product_bundle
  • Type: Product list

Code

{% when ‘addon_products_metafields’ %}

<div class=”addon addon–metafield”>

  <div class=”addon__wrapper”>

 

    {% assign bundle_index = 1 %}

 

    {% for bundle_product in product.metafields.custom.product_bundle.value %}

      {% if bundle_product.available %}

        {% assign bundle_variant = bundle_product.selected_or_first_available_variant %}

 

        <div class=”addon__item”>

          <label class=”addon-card”>

            <input

              type=”checkbox”

              name=”items[{{ bundle_index }}][id]”

              value=”{{ bundle_variant.id }}”

              form=”{{ product_form_id }}”

              class=”addon-card__checkbox”

            >

 

            <div class=”addon-card__image”>

              <img

                src=”{{ bundle_product.featured_image | image_url: width: 300 }}”

                alt=”{{ bundle_product.title | escape }}”

              >

            </div>

 

            <div class=”addon-card__info”>

              <p class=”addon-card__title”>{{ bundle_product.title }}</p>

              <p class=”addon-card__price”>{{ bundle_variant.price | money }}</p>

            </div>

          </label>

        </div>

 

        {% assign bundle_index = bundle_index | plus: 1 %}

      {% endif %}

    {% endfor %}

 

  </div>

</div>

Highlight:

  • Dynamic per product
  • Fully controlled via metafields

Schema 

{

  “type”: “addon_products_metafields”,

  “name”: “Add-on Products using metafields”,

  “settings”: []

}

Info :- The schema is used to display the block on the product page. We need to create a block in the schema so that we can use {% when ‘addon_products_metafields’ %} to render and show that block on the product page.

5. Method 2: Common Add-ons (Theme Block Schema)

Used when the same add-ons should appear across multiple products.

Schema

{

  “type”: “addon_products”,

  “name”: “Add-on Products”,

  “settings”: [

    {

      “type”: “product_list”,

      “id”: “products”,

      “label”: “Select Add-on Products”

    }

  ]

}

Code

{% when ‘addon_products’ %}

<div class=”addon addon–schema”>

  <div class=”addon__wrapper”>

 

    {% assign bundle_index = 1 %}

 

    {% for bundle_product in block.settings.products %}

      {% if bundle_product.available %}

        {% assign bundle_variant = bundle_product.selected_or_first_available_variant %}

 

        <div class=”addon__item”>

          <label class=”addon-card”>

            <input

              type=”checkbox”

              name=”items[{{ bundle_index }}][id]”

              value=”{{ bundle_variant.id }}”

              form=”{{ product_form_id }}”

              class=”addon-card__checkbox”

            >

 

            <div class=”addon-card__image”>

              <img

                src=”{{ bundle_product.featured_image | image_url: width: 300 }}”

                alt=”{{ bundle_product.title | escape }}”

              >

            </div>

 

            <div class=”addon-card__info”>

              <p class=”addon-card__title”>{{ bundle_product.title }}</p>

              <p class=”addon-card__price”>{{ bundle_variant.price | money }}</p>

            </div>

          </label>

        </div>

 

        {% assign bundle_index = bundle_index | plus: 1 %}

      {% endif %}

    {% endfor %}

 

  </div>

</div>

Highlight:

  • Reusable across products
  • Controlled via theme customizer

6. Final Key Advantages

Most Important Points:

  • No JavaScript required
  • Faster performance
  • Native Shopify compatibility
  • Simple and maintainable code

Conclusion

This approach provides a clean, scalable, and high-performance way to implement product add-ons in Shopify using only Liquid, metafields, and schema settings.

Best Practice:
Use metafields for dynamic control and schema blocks for reusable setups.

Want to implement this in your store? Contact us Today!

Let’s Connect for Your Next Web Development Project.

Plan your next web or mobile application solution with us. Let us know your requirements and our team will get in touch with you.