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!