Shopify Liquid: Add A Product to the Customers Cart using a Custom Section - e-commerce

How to add a product to cart in a custom section.
I have this custom section where multiple products are being selected, and I want to add them all to the cart when the customer clicks buy.
I'm guessing there is a form used to POST products into the customers cart?
Access Products
{{ for collection in collections }}
{{ for product in collection.products }}
<input type="checkbox" name="{{product.title}}" value="{{product.title}}" > {{product.title}}<br>
{% endfor %}
{% endfor %}
Add Products to cart
Do I use a <form>, or is there a shopify tag that I can use to create a form? I do not understand how to add these selected items to the customer's cart.

Pretty much you can do this.
<form action="/cart/add" method="post">
{%- for variant in product.variants -%}
<input type="checkbox" name="id[]" value="{{ variant.id }}" />
{%- endfor -%}
<input type="submit" value="Add to cart" />
</form>
Where you must name the inputs name="id[]" and not name="{{product.title}}".

Related

Shopify How to add meta fields to product in liquid

I am trying to figure out How to add meta fields to product in liquid
I have a product that has a list of meta fields (scents) how do I add the selected meta field to the product. I don’t want the scents to be variants.
Example on a candle product page user selects strawberry scent how does this get added to cart as candle strawberry scent?
I added meta-field list in settings.
This I what I have so far it renders the meta-fields.
{% if product.metafields.custom.scents != blank %}
<div class="product_scents">
{% for p in product.metafields.custom.scents.value %}
<div class="">{{ p }}</div>
{% endfor %}
</div>
{% endif %}
Thanks for having a look!
After further research this is how I solved my problem I loop over the meta fields and the selected meta field gets added to the cart as a line item of the product.
{% if product.metafields.custom.scents != blank %}
<div class="tw-flex tw-flex-col tw-py-12 tw-space-y-4">
<p>Select Your scent</p>
{% for p in product.metafields.custom.scents.value %}
<p class="line-item-property__field">
<input type="radio" name="properties[Scent]" value="{{ p }}"> <span>{{ p }}</span><br>
</p>
{% endfor %}
</div>
{% endif %}

Can I Add Discount Code To Metafield And Include In Add To Cart Button to auto apply to checkout page?

I have created a new product metafield: product.metafields.my_fields.discount_code
In my product-template.liquid, there is this section:
<button class="btn cv_addtocart{% if section.settings.enable_payment_button %} btn--secondary{% else %} btn--primary{% endif %}" type="button" name="add" data-add-to-cart {% unless current_variant.available %}disabled="disabled"{% endunless %}>
<span data-add-to-cart-text>
{% if current_variant.available %}
{{ 'products.product.add_to_cart' | t }}
{% else %}
{{ 'products.product.sold_out' | t }}
{% endif %}
</span>
</button>
{% if section.settings.enable_payment_button %}
{{ form | payment_button }}
{% endif %}
</div>
</div>
I am trying to pass the value of a metafield for a product into the add to cart button. In this case, I want the discount code which is entered into the product metafield to be included.
So am hoping to do something like this:
{% if section.settings.enable_payment_button %}
{{ form | payment_button | discountCode = product.metafields.my_fields.discount_code }}
{% endif %}
Basically, I am trying to automatically apply a normal discount to a product at checkout. I have seen the various shareable links that append the discount code to the url, but this does not suit my needs. Instead, I would like to retrieve the discount code (DISCOUNT20) from a metafield for that product on the checkout page and apply the coupon code there.
Any thoughts? I have been stuck on this for a long time
So I have figured out a more reliable route:
I located my cart template liquid file and searched for a form
<form action="/cart" method="post" >
Directly below this line I inserted this
{%- for item in cart.items -%}
{%- if item.product.metafields.my_fields.discount_code.value != blank -%}
<input type="hidden" name="discount" value="{{item.product.metafields.my_fields.discount_code.value}}" >
{%- endif -%}
{%- endfor -%}
In my case, value = an interpolated value being retrieved from a product metafield for the product in the cart.
FYI - you need to create a metafield in settings, then create a discount code, copy the discount code, go to your product that you want the discount code to apply to, access the product and scroll down to metafields, paste the discount code in the product's discount(if you named your metafield "discount", you might have named it something else) metafield.
Hence, as the form will be submitted with a name="discount" and value="discount_code", the checkout page will evaluate to true for discount and use the appropriate values. However this is only possible with the for loop.
For such a simple fix, I am surprised it was so hard to figure out. Hope this helps you!
** Some extra reading if you want: https://wearetmbr.com/shopify-auto-fill-discount-code-on-checkout-page/ **

Referencing a product in Shopify

I'm developing a Shopify website for a client who wasn't happy with the native related products section.
I started developing a custom section where my client can choose the products to display.
The only problem is I'm having a hard time find documentation relative to the product object. Or at least not understanding it well.
In my schema I added a product setting which allows to choose the product I want:
{
"type": "product",
"label": "Produit 1",
"id": "produit_premier"
}
This works fine, but the only output I'm getting is the name of my product.
How can I achieve displaying the product image?
Thanks for your help!
When you use the input type product in Shopify it returns to your handle of the product.
You need to use the all_products object to get more information regarding the product.
Update: you can use it like
This is the settings json code:
[UPDATED - FINAL]
Finished working on this, here's the final code:
<!-- GETS PRODUCT HANDLE AND ASSIGNS TO VARIABLE -->
<div class="hidden">
{% assign product = section.settings.produit_quatrieme %}
</div>
<!-- GETS PRODUCT FIRST IMAGE + LINK -->
{% for image in all_products[product].images %}
{% if forloop.first == true %}
<a href=" {{ all_products[product].url }} ">
<img src="{{image.src | img_url:"grande"}}" />
</a>
{% endif %}
{% endfor %}
<!-- GETS PRODUCT TITLE + LINK -->
{% for title in all_products[product].title %}
{% if forloop.first == true %}
<a href=" {{ all_products[product].url }} ">
<h2 class="ProductItem__Title Heading margin-none"> {{ all_products[product].title }} </h2>
</a>
{% endif %}
{% endfor %}
Add schema code to the section blocks instead of section settings. Then you can select as many products as you want.
{% for block in section.blocks %}
{% assign product = all_products[block.settings.produit_quatrieme] %}
<a href=" {{ product.url }} ">
<img src="{{product.featured_image| img_url:"grande"}}" />
</a>
<a href=" {{ product.url }} ">
<h2 class="ProductItem__Title Heading margin-none"> {{ product.title }} </h2>
</a>
{% endfor %}
If you want to display a single product then just add section instead of block, then no need to use for loop.

How to avoid calling content when two tags are partially the same in Shopify

I am currently trying to display content based on product tags that are assigned to products in Shopify.
This is working ok, but my problem is that I have two tags that contain partially the same tag name, so I am getting both sets of content appearing on the front end.
One tag shows a field that is required "r-[tag-name]" and the other shows the same field but it is not required "[tag-name]".
Obviously I know this is due to the fact that I am using 'contains' so the logic is true for both when either tag is applied, but I have tried using '==' (equals) but it when I do, nothing appears at all :/
What I would like to know is, what do I need to change so that the statement is only true if a tag exists that is exactly the same as the if statement.
I am new to Liquid so any help would be greatly appreciated!
<!--Convert the tags into a string by joining them with COMMA-->
{% assign productTags = product.tags | join: ', ' %}
<!--Now Check for the desired tag name-->
{% if productTags contains 'r-custom-name-one' %}
<p class="line-item-property__field">
<label for="name-one">Name One:</label>
<input class="required" id="name-one" type="text" name="properties[Name One]">
</p>
{% endif %}
{% if productTags contains 'custom-name-one' %}
<p class="line-item-property__field">
<label for="name-one">Name One:</label>
<input id="name-one" type="text" name="properties[Name One]">
</p>
{% endif %}
I need to change so that the statement is only true if a tag exists that is exactly the same as the if statement
This should do it:
{% for tag in product.tags %}
{% if tag == 'r-custom-name-one' %}
<p class="line-item-property__field">
<label for="name-one">Name One:</label>
<input class="required" id="name-one" type="text" name="properties[Name One]">
</p>
{% break %}
{% endif %}
{% if tag == 'custom-name-one' %}
<p class="line-item-property__field">
<label for="name-one">Name One:</label>
<input id="name-one" type="text" name="properties[Name One]">
</p>
{% break %}
{% endif %}
{% endfor %}
I added {% break %} which will
Causes the loop to stop iterating when it encounters the break tag.
I assumed that once the tag is found, you don't need need to continue looping through the rest of the tags!

Display Items in Collection that Do Not Exist In Shopping Cart Shopify

I'm trying to iterate over items in the shopping cart and generate an upsell div with products NOT in the cart. Below is the code I have so far, but I run into issues when adding two items to cart running the loop twice generating the html twice. Any ideas on how to resolve it? I'm stumped.
{% for item in cart.items %} // iterates over items in cart
{% if item.product.id == 4456879040188 %} // checks if product id matches in item in cart
<div class="upsell-pop" style="text-align:center; width: 100%;">
<h4>Frequently bought together</h4>
{% for prod in collections.upsell.products %} // iterates products in collection upsell
{% unless prod.handle contains "product-name" %} // shows only prods that do not contain url handle
<div>
<span class="upsell-title">{{ prod.title }}</span>
<span class="upsell-price">{{ prod.metafields["meta"]["promo"] }} {{ prod.price | money }}</span>
<img src="{{ prod.featured_image | img_url: '200x' }}" />
<a class="btn-product" href="{{prod.url}}">View Product</a>
</div>
{% endunless %}
{% endfor %}
</div>
{% endif %}
{% endfor %}
Another thought is to somehow check to see if product is NOT in cart items inside to replace the existing "unless" statement, but not sure how to code it.
{% unless cart.items exist then %} // I know this is not correct syntax
<div>
<span class="upsell-title">{{ prod.title }}</span>
<span class="upsell-price">{{ prod.metafields["meta"]["promo"] }} {{ prod.price | money }}</span>
<img src="{{ prod.featured_image | img_url: '200x' }}" />
<a class="btn-product" href="{{prod.url}}">View Product</a>
</div>
{% endunless %}
On my mind, there are two steps here.
First, capture your cart content to get string to compare to when you loop through your upsell collection. This could be something like that:
{%- capture cart_items -%}
{% for item in cart.items %}
{{ item.product.handle }}{% unless forloop.last %} , {% endunless %}
{% endfor %}
{%- endcapture -%}
Then loop through your collection while checking your string does not contain the handle of the current product at each iteration:
{% for product in collections['upsell'].products %}
{% unless cart_items contains product.handle %}
{{ product.title }}
{% endunless %}
{% endfor %}
Remarks:
Snippet 1 => In line_item (here called item because it's shorter to write) object you may access product object attributes: item.product.product_attr_needed
Snippet 2 => To access directly a collection object using its handle you must use collections + square brackets containing collection handle + attribute. Here 'upsell' is the handle of your upsell collection.
Not tested but this should work.
HTH