Script Help: Hide/Show shipping rates based on customer tag

Hey folks, I hope everyone is well.

With the new B2B functionality, we’re looking to merge our front end site with wholesale, but we have a teething issue with shipping.

I know that Shopify Script editor can help with this, but for the life of me I cannot figure out how. If someone could help me I’d appreciate it.

Basically we operate with all customers tagged either “WHOLESALE” or “RETAIL” so that’s a nice tag to hang the script on to.

I’d like to hide certain rates for both customers, and show certain rates, we use Royal Mail for retail and UPS for wholesale, so I’d like to hide the Royal Mail for wholesale customers and subsequently hide the UPS options for retail customers.

Can someone assist me with this please?

Thank you all so much!

-Dave

Hello Dave

Thanks for sharing this opportunity to audience, For the request my first question is why did you want to hide features in the website. Let me go straight to the point, as a Full stack developer base on Shopify. What you will implement is to used the developer tool in script with coding template dialog to achieve the objectives.

After changes, tested it and publish it.
If you are convince in the journey, you can notified I will help you with it.
Hope you’re few knowledge about it.

Thanks

Kenneth

Hi Kenneth,

I’ve already stated why - it’s because we wish to use a blended store under Shopify’s new B2B function - as a shopify plus user we wish to take advantage of this, but do not want to offer certain shipping rates to wholesale customers, and likewise for retail customers.

Based on the customer tag of either “wholesale” or “retail” I think this is possible.

Kind regards,
Dave

Hello Dave,

Ohh so great. Did you have someone that can help you through it. If you wish, I might render the services . Can you share your Url to audit the front end

Hi Kenneth, I’ve just figured it out!

Thank you for replying however!

Hey Dave, any chance you can share the script solution on this page? I’m looking to implement a similar thing. I’m wanting to remove free shipping to wholesale customers

Hi Chris - I can share the script, however I found out shortly after that when using a blended store (under Shopify’s new B2B offering), when logged in as a B2B customer, shopify scripts are not supported, so if you’re using that then unfortunately you and I will have to wait for this functionality to roll out.

If you’re using a third party app for wholesale then this code would work for you, but bear in mind there are specific name based rules for our system (such as Royal Mail shipping rates and specific UPS shipping terms), so this will have to be amended to work in your store:

class Campaign
  def initialize(condition, *qualifiers)
    @condition = (condition.to_s + '?').to_sym
    @qualifiers = PostCartAmountQualifier ? [] : [] rescue qualifiers.compact
    _item_selector = qualifiers.last unless _item_selector
    qualifiers.compact.each do |qualifier|
      is_multi_select = qualifier.instance_variable_get(:@conditions).is_a?(Array)
      if is_multi_select
        qualifier.instance_variable_get(:@conditions).each do |nested_q|
          @post_amount_qualifier = nested_q if nested_q.is_a?(PostCartAmountQualifier)
          @qualifiers << qualifier
        end
      else
        @post_amount_qualifier = qualifier if qualifier.is_a?(PostCartAmountQualifier)
        @qualifiers << qualifier
      end
    end if @qualifiers.empty?
  end

  def qualifies?(cart)
    return true if @qualifiers.empty?
    @unmodified_line_items = cart.line_items.map do |item|
      new_item = item.dup
      new_item.instance_variables.each do |var|
        val = item.instance_variable_get(var)
        new_item.instance_variable_set(var, val.dup) if val.respond_to?(:dup)
      end
      new_item
    end if @post_amount_qualifier
    @qualifiers.send(@condition) do |qualifier|
      is_selector = false
      if qualifier.is_a?(Selector) || qualifier.instance_variable_get(:@conditions).any? { |q| q.is_a?(Selector) }
        is_selector = true
      end rescue nil
      if is_selector
        raise "Missing line item match type" if _match_type.nil?
        cart.line_items.send(@li_match_type) { |item| qualifier.match?(item) }
      else
        qualifier.match?(cart, _item_selector)
      end
    end
  end

  def run_with_hooks(cart)
    before_run(cart) if respond_to?(:before_run)
    run(cart)
    after_run(cart)
  end

  def after_run(cart)
    .apply_final_discount if  && .respond_to?(:apply_final_discount)
    revert_changes(cart) unless @post_amount_qualifier.nil? || @post_amount_qualifier.match?(cart)
  end

  def revert_changes(cart)
    cart.instance_variable_set(:@line_items, @unmodified_line_items)
  end
end

class ConditionallyHideRates < Campaign
  def initialize(condition, customer_qualifier, cart_qualifier, li_match_type, line_item_qualifier, rate_selector)
    super(condition, customer_qualifier, cart_qualifier, line_item_qualifier)
    _match_type = (li_match_type.to_s + '?').to_sym
    @rate_selector = rate_selector
  end

  def run(rates, cart)
    rates.delete_if { |rate| @rate_selector.match?(rate) } if qualifies?(cart)
  end
end

class Qualifier
  def partial_match(match_type, item_info, possible_matches)
    match_type = (match_type.to_s + '?').to_sym
    if item_info.kind_of?(Array)
      possible_matches.any? do |possibility|
        item_info.any? do |search|
          search.send(match_type, possibility)
        end
      end
    else
      possible_matches.any? do |possibility|
        item_info.send(match_type, possibility)
      end
    end
  end

  def compare_amounts(compare, comparison_type, compare_to)
    case comparison_type
      when :greater_than
        return compare > compare_to
      when :greater_than_or_equal
        return compare >= compare_to
      when :less_than
        return compare < compare_to
      when :less_than_or_equal
        return compare <= compare_to
      when :equal_to
        return compare == compare_to
      else
        raise "Invalid comparison type"
    end
  end
end

class CustomerTagQualifier < Qualifier
  def initialize(match_type, match_condition, tags)
    _condition = match_condition
    @invert = match_type == :does_not
     = tags.map(&:downcase)
  end

  def match?(cart, selector = nil)
    return true if cart.customer.nil? && @invert
    return false if cart.customer.nil?
    customer_tags = cart.customer.tags.to_a.map(&:downcase)
    case _condition
      when :match
        return @invert ^ ((@tags & customer_tags).length > 0)
      else
        return @invert ^ partial_match(@match_condition, customer_tags, )
    end
  end
end

class Selector
  def partial_match(match_type, item_info, possible_matches)
    match_type = (match_type.to_s + '?').to_sym
    if item_info.kind_of?(Array)
      possible_matches.any? do |possibility|
        item_info.any? do |search|
          search.send(match_type, possibility)
        end
      end
    else
      possible_matches.any? do |possibility|
        item_info.send(match_type, possibility)
      end
    end
  end
end

class RateNameSelector < Selector
  def initialize(match_type, match_condition, names)
    _condition = match_condition
    @invert = match_type == :does_not
    @names = names.map(&:downcase)
  end

  def match?(shipping_rate)
    name = shipping_rate.name.downcase
    case _condition
      when :match
        return @invert ^ @names.include?(name)
      else
        return @invert ^ partial_match(@match_condition, name, @names)
    end
  end
end

CAMPAIGNS = [
  ConditionallyHideRates.new(
    :all,
    CustomerTagQualifier.new(
      :does,
      :match,
      ["WHOLESALE"]
    ),
    nil,
    :any,
    nil,
    RateNameSelector.new(
      :does,
      :match,
      ["FREE Royal Mail 24 Tracked (On all orders placed before 3pm)", "FREE Royal Mail 48 Tracked (On all orders placed before 3pm)", "Royal Mail 24 Tracked (On all orders placed before 3pm)", "Royal Mail 48 Tracked (On all orders placed before 3pm)", "Royal Mail SATURDAY Tracked (On all orders placed before 3pm)", "UPS NEXT WORKING DAY (On all orders placed before 3pm)"]
    )
  ),
  ConditionallyHideRates.new(
    :all,
    CustomerTagQualifier.new(
      :does,
      :match,
      ["RETAIL"]
    ),
    nil,
    :any,
    nil,
    RateNameSelector.new(
      :does,
      :match,
      ["DHL - UP TO 100KG", "DHL - UP TO 30KG", "DHL - UP TO 40KG", "DHL - UP TO 50KG", "DHL - UP TO 60KG", "DHL - UP TO 70KG", "DHL - UP TO 80KG", "DHL - UP TO 90KG", "PalletForce 2+ Pallet", "PalletForce Single Pallet", "UPS - OVER 70KG", "UPS - UP TO 30KG", "UPS - UP TO 40KG", "UPS - UP TO 70KG"]
    )
  )
].freeze

CAMPAIGNS.each do |campaign|
  campaign.run(Input.shipping_rates, Input.cart)
end

Output.shipping_rates = Input.shipping_rates
1 Like