Conditional App Shipping Based on Product

Hi!

I have an unusual shipping issue. I have a client that is selling live pets and pet supply products. The client wants to use the third-party app ClickShip which is setup and working correctly.

Clickship will aggregate all the items in the cart and provide carrier rates.

https://apps.shopify.com/freightcom-delivery

The problem that we have is that we need to use another service to ship live animals in Canada. This needs to be done manually from my client’s end to co-ordinate delivery.

Hence, we need basic conditional logic as follows on checkout:

If the order CONTAIN live pets, no shipping is charged on checkout.

If the order DOES NOT CONTAIN live pets, Clickship rates are applied.

All the live pets are tagged with “live pets”, so one option would be to include an if statement based on the product tag, ie:

if the order contains a the tag “live pets” do not charge shipping…

else charge shipping based on the ClickShip app

I’m unsure how I can set that up if the checkout page is unaccessible.

I’ve tried reaching out to Shopify chat support, ClickShip tech support and third-party apps; however, I cannot find resolution.

Are you able to provide support?

In this example, we first loop through all line items in the checkout to check if any of them have the “live pets” tag. If we find any line items with that tag, we set a variable contains_live_pets to true. We then use an if statement to check the value of contains_live_pets, and display the appropriate content based on whether it is true or false.

You can add this code to the checkout.liquid template in your theme, in the appropriate location where you want the conditional logic to be applied

{% assign contains_live_pets = false %}
{% for line_item in checkout.line_items %}
  {% if line_item.product.tags contains 'live pets' %}
    {% assign contains_live_pets = true %}
    {% break %}
  {% endif %}
{% endfor %}

{% if contains_live_pets %}
  
{% else %}
  
{% endif %}

Another solution using Ruby

To implement the conditional logic you need, you’ll need to use a Shopify app that allows you to add custom code to your store’s checkout page. One popular app for this is called “Shopify Scripts.”

Once you have the app installed, you can create a script that checks if any items in the order have the “live pets” tag. If they do, the script can set the shipping rate to $0. If there are no items with the “live pets” tag, the script can call the ClickShip API to retrieve the shipping rates and apply them to the order.

Here’s an example script that should accomplish what you need:

# Set the default shipping rate to $0
shipping_rate = nil

# Check if any items in the order have the "live pets" tag
if Input.cart.line_items.any? { |item| item.variant.product.tags.include?('live pets') }
  # If there are live pets in the order, set the shipping rate to $0
  shipping_rate = Input.shipping_rates.find { |rate| rate.name == 'Free Shipping' }
else
  # If there are no live pets in the order, retrieve the ClickShip rates and apply them
  response = HTTParty.get('https://api.clickship.com/rates', headers: {
    'Authorization' => 'Bearer YOUR_CLICKSHIP_API_KEY',
    'Content-Type' => 'application/json'
  }, body: {
    origin: {
      city: 'YOUR_ORIGIN_CITY',
      province: 'YOUR_ORIGIN_PROVINCE',
      postal_code: 'YOUR_ORIGIN_POSTAL_CODE',
      country: 'YOUR_ORIGIN_COUNTRY_CODE'
    },
    destination: {
      city: Input.shipping_address.city,
      province: Input.shipping_address.province_code,
      postal_code: Input.shipping_address.zip,
      country: Input.shipping_address.country_code
    },
    packages: [
      {
        weight: Input.cart.total_weight,
        length: YOUR_PACKAGE_LENGTH_IN_CM,
        width: YOUR_PACKAGE_WIDTH_IN_CM,
        height: YOUR_PACKAGE_HEIGHT_IN_CM
      }
    ]
  }.to_json)

  if response.success?
    # Parse the response and find the cheapest shipping rate
    rates = response['rates']
    cheapest_rate = rates.min_by { |rate| rate['total_price'] }
    shipping_rate = Input.shipping_rates.find { |rate| rate.name == cheapest_rate['service_name'] }
  else
    # If there was an error with the ClickShip API, set the shipping rate to nil to indicate an error
    shipping_rate = nil
  end
end

# Output the shipping rate
Output.shipping_rates = [shipping_rate].compact

Note that you’ll need to replace the placeholders in the script with your own values, such as your ClickShip API key, origin location, and package dimensions.

Thanks very much for your replies, it’s very appreciated from my end :slightly_smiling_face:

It’s my understanding that to edit the checkout.liquid template we need a Shopify Plus account. Is this correct? We’re using a “Shopify” plan for $99/month.

Additionally, it appears that the checkout.liquid template will be depreciated in a year.

https://shopify.dev/docs/themes/architecture/layouts/checkout-liquid

Are there any other solutions available?

Sure, here’s an example of the improved code using React:
https://shopify.dev/docs/custom-storefronts/building-with-the-storefront-api/checkout

import React, { useState, useEffect } from "react";

const CheckOut = () => {
  const [hasLivePets, setHasLivePets] = useState(false);
  const [shippingCost, setShippingCost] = useState(0);

  useEffect(() => {
    // Check if the cart contains any live pet products
    const cart = JSON.parse(localStorage.getItem("cart"));
    if (cart.some(item => item.tags.includes("live pets"))) {
      setHasLivePets(true);
    } else {
      setHasLivePets(false);
      // Fetch shipping rates using ClickShip API
      fetch("/api/clickship-rates")
        .then(res => res.json())
        .then(data => setShippingCost(data.rate))
        .catch(error => console.error(error));
    }
  }, []);

  const handleCheckout = () => {
    if (hasLivePets) {
      // Logic to coordinate delivery for live pets
      alert("Please coordinate delivery of live pets manually.");
    } else {
      // Proceed to regular checkout process with calculated shipping cost
      alert(`Shipping cost: $${shippingCost}`);
      // ... more logic for regular checkout process
    }
  };

  return (
    
      # Checkout
      
    

  );
};

export default CheckOut;

This code uses the useState hook to manage the state of hasLivePets and shippingCost. It also uses the useEffect hook to check if the cart contains any live pet products when the component mounts. If it does, hasLivePets is set to true and no shipping cost is calculated. If it doesn’t, hasLivePets is set to false and the fetch function is called to get the shipping rates using the ClickShip API. The shipping cost is then set using setShippingCost.

The handleCheckout function is called when the “Checkout” button is clicked. If hasLivePets is true, the function alerts the user to coordinate delivery of live pets manually. If hasLivePets is false, the function alerts the user to the shipping cost and proceeds to the regular checkout process.

Note that this code assumes that you have set up an API endpoint at /api/clickship-rates that returns the shipping rates as JSON. You will need to replace this with the actual endpoint that you are using.

i also want to have this service to take my cat to Canada with me and I also have a site on pets as I am a pet lover and want to take me along.