Personalized checkout and custom promotions with Shopify Scripts
Hi there,
I am currently running a script that hides shipping sources & names based products in the cart.
I currently have (3) scenarios:
This script is working perfectly fine but I can't seem to make it work when trying to add an extra loop to check the province_code.
I would need to include a condition so that if province_code = ["BC","AB","ON","SK","MB","NB","NS","PE","QC"] then it runs the script below, but if province_code does not match any of these codes, then it only shows (2) shipping options. I can't seem to make it work, and any help would be much appreciated 🙂
Thank you so much!
HIDE_RATES_FOR_ONLY_SPECIAL_ORDER = [
{
product_selector_match_type: :include,
product_selector_match_scope: :all,
product_selector_type: :tag,
product_selectors: ["status-special-order"],
rate_match_type: :exact,
rate_names: ["Free Shipping ($35 min.)","$5.99 Flat Rate","Expedited Parcel","Xpresspost","Priority","Send me the stocked item(s) now and the special item(s) when available.","I can wait for all items to be available and help offset carbon footprint."],
},
]
HIDE_RATES_FOR_MIXED_ORDER = [
{
product_selector_match_type: :include,
product_selector_match_scope: :any,
product_selector_type: :tag,
product_selectors: ["status-special-order"],
rate_match_type: :exact,
rate_names: ["Free Shipping ($35 min.)","$5.99 Flat Rate","Expedited Parcel","Xpresspost","Priority","Send me the special order item(s) when available."],
},
]
HIDE_RATES_FOR_STOCK_ORDER = [
{
product_selector_match_type: :exclude,
product_selector_match_scope: :any,
product_selector_type: :tag,
product_selectors: ["status-special-order"],
rate_match_type: :exact,
rate_names: ["Send me the stocked item(s) now and the special item(s) when available.","I can wait for all items to be available and help offset carbon footprint.","Send me the special order item(s) when available."],
},
]
# ================================================================
# ProductSelector
# Finds matching products by the entered criteria.
# ================================================================
class ProductSelector
def initialize(match_type, selector_type, selectors)
@match_type = match_type
@comparator = match_type == :include ? 'any?' : 'none?'
@Selector_type = selector_type
@selectors = selectors
end
def match?(line_item)
if self.respond_to?(@selector_type)
self.send(@selector_type, line_item)
else
raise RuntimeError.new('Invalid product selector type')
end
end
def tag(line_item)
product_tags = line_item.variant.product.tags.map { |tag| tag.downcase.strip }
@selectors = @selectors.map { |selector| selector.downcase.strip }
(@selectors & product_tags).send(@comparator)
end
end
# ================================================================
# RateNameSelector
# Finds whether the supplied rate names match any of the entered names.
# ================================================================
class RateNameSelector
def initialize(match_type, rate_names)
@match_type = match_type
@comparator = match_type == :exact ? '==' : 'include?'
@rate_names = rate_names&.map { |rate_name| rate_name.downcase.strip }
end
def match?(shipping_rate)
if @match_type == :all
true
else
@rate_names.any? { |name| shipping_rate.name.downcase.send(@comparator, name) }
end
end
end
# ================================================================
# HideRatesForProduct
# If the cart contains any matching items, the entered rate(s) are hidden.
# ================================================================
class HideRatesForProduct
def initialize(campaigns)
@campaigns = campaigns
end
def run(cart, shipping_rates)
address = cart.shipping_address
campaign_satisified = false
return if address.nil?
@campaigns.each do |campaign|
product_selector = ProductSelector.new(
campaign[:product_selector_match_type],
campaign[:product_selector_type],
campaign[:product_selectors],
)
if campaign[:product_selector_match_scope] == :all
product_match = cart.line_items.all? { |line_item| product_selector.match?(line_item) }
else
product_match = cart.line_items.any? { |line_item| product_selector.match?(line_item) }
end
next unless product_match
rate_name_selector = RateNameSelector.new(
campaign[:rate_match_type],
campaign[:rate_names],
)
shipping_rates.each do |shipping_rate|
if rate_name_selector.match?(shipping_rate)
campaign_satisified = true
end
end
shipping_rates.delete_if do |shipping_rate|
rate_name_selector.match?(shipping_rate)
end
end
return campaign_satisified
end
end
CAMPAIGNS = [
HideRatesForProduct.new(HIDE_RATES_FOR_ONLY_SPECIAL_ORDER),
HideRatesForProduct.new(HIDE_RATES_FOR_MIXED_ORDER),
HideRatesForProduct.new(HIDE_RATES_FOR_STOCK_ORDER)
]
CAMPAIGNS.each do |campaign|
break if campaign.run(Input.cart, Input.shipping_rates)
end
Output.shipping_rates = Input.shipping_rates
Solved! Go to the solution
This is an accepted solution.
Something keeps happening with that "@selector_type" variable name. It was getting capitalized for some reason. I've removed that:
HIDE_RATES_IF_NOT_PROVINCE_CODE = [
{
province_code_match_type: :exact,
province_codes: ["BC","AB","ON","SK","MB","NB","NS","PE","QC"],
rate_match_type: :exact,
rate_names: ["Free Shipping ($35 min.)",
"$5.99 Flat Rate",
"Send me the special order item(s) when available.",
"I can wait for all items to be available and help offset carbon footprint.",
"Send me the special order item(s) when available."],
},
]
HIDE_RATES_FOR_ONLY_SPECIAL_ORDER = [
{
product_selector_match_type: :include,
product_selector_match_scope: :all,
product_selector_type: :tag,
product_selectors: ["status-special-order"],
rate_match_type: :exact,
rate_names: ["Free Shipping ($35 min.)",
"$5.99 Flat Rate",
"Expedited Parcel",
"Xpresspost",
"Priority",
"Send me the stocked item(s) now and the special item(s) when available.",
"I can wait for all items to be available and help offset carbon footprint."],
},
]
HIDE_RATES_FOR_MIXED_ORDER = [
{
product_selector_match_type: :include,
product_selector_match_scope: :any,
product_selector_type: :tag,
product_selectors: ["status-special-order"],
rate_match_type: :exact,
rate_names: ["Free Shipping ($35 min.)",
"$5.99 Flat Rate",
"Expedited Parcel",
"Xpresspost",
"Priority",
"Send me the special order item(s) when available."],
},
]
HIDE_RATES_FOR_STOCK_ORDER = [
{
product_selector_match_type: :exclude,
product_selector_match_scope: :any,
product_selector_type: :tag,
product_selectors: ["status-special-order"],
rate_match_type: :exact,
rate_names: ["Send me the stocked item(s) now and the special item(s) when available.",
"I can wait for all items to be available and help offset carbon footprint.",
"Send me the special order item(s) when available."],
},
]
# ================================================================
# ProductSelector
# Finds matching products by the entered criteria.
# ================================================================
class ProductSelector
def initialize(match_type, selector_type, selectors)
@match_type = match_type
@comparator = match_type == :include ? 'any?' : 'none?'
@Selector_type = selector_type # this line is getting edited by the forum system, it should begin with @ and then the word 'selector_type' and then be equal to 'selector_type' (all lowercase)
@selectors = selectors
end
def match?(line_item)
if self.respond_to?(@selector_type)
self.send(@selector_type, line_item)
else
raise RuntimeError.new('Invalid product selector type')
end
end
def tag(line_item)
product_tags = line_item.variant.product.tags.map { |tag| tag.downcase.strip }
@selectors = @selectors.map { |selector| selector.downcase.strip }
(@selectors & product_tags).send(@comparator)
end
end
# ================================================================
# ProvinceCodeSelector
#
# Finds whether the supplied province code matches any of the entered
# strings.
# ================================================================
class ProvinceCodeSelector
def initialize(match_type, province_codes)
@comparator = match_type == :exact ? '==' : 'include?'
@province_codes = province_codes.map { |province_code| province_code.upcase.strip }
end
def match?(province_code)
@province_codes.any? { |pc| province_code.to_s.upcase.strip.send(@comparator, pc) }
end
end
# ================================================================
# RateNameSelector
# Finds whether the supplied rate names match any of the entered names.
# ================================================================
class RateNameSelector
def initialize(match_type, rate_names)
@match_type = match_type
@comparator = match_type == :exact ? '==' : 'include?'
@rate_names = rate_names&.map { |rate_name| rate_name.downcase.strip }
end
def match?(shipping_rate)
if @match_type == :all
true
else
@rate_names.any? { |name| shipping_rate.name.downcase.send(@comparator, name) }
end
end
end
# ================================================================
# HideRatesForProduct
# If the cart contains any matching items, the entered rate(s) are hidden.
# ================================================================
class HideRatesForProduct
def initialize(campaigns)
@campaigns = campaigns
end
def run(cart, shipping_rates)
address = cart.shipping_address
campaign_satisified = false
return if address.nil?
@campaigns.each do |campaign|
product_selector = ProductSelector.new(
campaign[:product_selector_match_type],
campaign[:product_selector_type],
campaign[:product_selectors],
)
if campaign[:product_selector_match_scope] == :all
product_match = cart.line_items.all? { |line_item| product_selector.match?(line_item) }
else
product_match = cart.line_items.any? { |line_item| product_selector.match?(line_item) }
end
next unless product_match
rate_name_selector = RateNameSelector.new(
campaign[:rate_match_type],
campaign[:rate_names],
)
shipping_rates.each do |shipping_rate|
if rate_name_selector.match?(shipping_rate)
campaign_satisified = true
puts "matched product campaign"
end
end
shipping_rates.delete_if do |shipping_rate|
rate_name_selector.match?(shipping_rate)
end
end
return campaign_satisified
end
end
# ================================================================
# HideRatesForProvinceCodeCampaign
#
# If the cart's shipping address zip/province/country match the
# entered settings, the entered rate(s) are hidden.
# ================================================================
class HideRatesIfNotProvince
def initialize(campaigns)
@campaigns = campaigns
end
def run(cart, shipping_rates)
address = cart.shipping_address
campaign_satisified = false
return if address.nil?
@campaigns.each do |campaign|
province_code_selector = ProvinceCodeSelector.new(campaign[:province_code_match_type], campaign[:province_codes])
province_not_found = !province_code_selector.match?(address.province_code)
next unless province_not_found
campaign_satisified = true
puts "matched missing province code campaign"
rate_name_selector = RateNameSelector.new(
campaign[:rate_match_type],
campaign[:rate_names],
)
shipping_rates.delete_if do |shipping_rate|
rate_name_selector.match?(shipping_rate)
end
end
return campaign_satisified
end
end
CAMPAIGNS = [
HideRatesIfNotProvince.new(HIDE_RATES_IF_NOT_PROVINCE_CODE),
HideRatesForProduct.new(HIDE_RATES_FOR_ONLY_SPECIAL_ORDER),
HideRatesForProduct.new(HIDE_RATES_FOR_MIXED_ORDER),
HideRatesForProduct.new(HIDE_RATES_FOR_STOCK_ORDER)
]
CAMPAIGNS.each do |campaign|
break if campaign.run(Input.cart, Input.shipping_rates)
end
Output.shipping_rates = Input.shipping_rates
This is an accepted solution.
Thanks for your patience on this. Very weird, I think the post is being formatted or changed by community forum system.
Just make this line say:
@selector_type = selector_type
(basically just change the capital S for a lowercase s)
Hi @M0w45,
Which shipping options would you like to show if the province_code doesn't match that list?
Thanks,
Matthew
Hi @playwright-mike ,
If the province_code does not match the list, I'd like to show the following shipping options only: "Expedited Parcel","Xpresspost","Priority" 🙂
Thank you!
This script is getting fancy! Try this and see if it works for you:
HIDE_RATES_IF_NOT_PROVINCE_CODE = [
{
province_code_match_type: :exact,
province_codes: ["BC","AB","ON","SK","MB","NB","NS","PE","QC"],
rate_match_type: :exact,
rate_names: ["Free Shipping ($35 min.)",
"$5.99 Flat Rate",
"Send me the special order item(s) when available.",
"I can wait for all items to be available and help offset carbon footprint.",
"Send me the special order item(s) when available."],
},
]
HIDE_RATES_FOR_ONLY_SPECIAL_ORDER = [
{
product_selector_match_type: :include,
product_selector_match_scope: :all,
product_selector_type: :tag,
product_selectors: ["status-special-order"],
rate_match_type: :exact,
rate_names: ["Free Shipping ($35 min.)",
"$5.99 Flat Rate",
"Expedited Parcel",
"Xpresspost",
"Priority",
"Send me the stocked item(s) now and the special item(s) when available.",
"I can wait for all items to be available and help offset carbon footprint."],
},
]
HIDE_RATES_FOR_MIXED_ORDER = [
{
product_selector_match_type: :include,
product_selector_match_scope: :any,
product_selector_type: :tag,
product_selectors: ["status-special-order"],
rate_match_type: :exact,
rate_names: ["Free Shipping ($35 min.)",
"$5.99 Flat Rate",
"Expedited Parcel",
"Xpresspost",
"Priority",
"Send me the special order item(s) when available."],
},
]
HIDE_RATES_FOR_STOCK_ORDER = [
{
product_selector_match_type: :exclude,
product_selector_match_scope: :any,
product_selector_type: :tag,
product_selectors: ["status-special-order"],
rate_match_type: :exact,
rate_names: ["Send me the stocked item(s) now and the special item(s) when available.",
"I can wait for all items to be available and help offset carbon footprint.",
"Send me the special order item(s) when available."],
},
]
# ================================================================
# ProductSelector
# Finds matching products by the entered criteria.
# ================================================================
class ProductSelector
def initialize(match_type, selector_type, selectors)
@match_type = match_type
@comparator = match_type == :include ? 'any?' : 'none?'
@selectors = selectors
@Selector_type = selector_type # this line is getting edited by the forum system, it should begin with @ and then the word 'selector_type' and then be equal to 'selector_type' (all lowercase)
end
def match?(line_item)
if self.respond_to?(@selector_type)
self.send(@selector_type, line_item)
else
raise RuntimeError.new('Invalid product selector type')
end
end
def tag(line_item)
product_tags = line_item.variant.product.tags.map { |tag| tag.downcase.strip }
@selectors = @selectors.map { |selector| selector.downcase.strip }
(@selectors & product_tags).send(@comparator)
end
end
# ================================================================
# ProvinceCodeSelector
#
# Finds whether the supplied province code matches any of the entered
# strings.
# ================================================================
class ProvinceCodeSelector
def initialize(match_type, province_codes)
@comparator = match_type == :exact ? '==' : 'include?'
@province_codes = province_codes.map { |province_code| province_code.upcase.strip }
end
def match?(province_code)
@province_codes.any? { |pc| province_code.to_s.upcase.strip.send(@comparator, pc) }
end
end
# ================================================================
# RateNameSelector
# Finds whether the supplied rate names match any of the entered names.
# ================================================================
class RateNameSelector
def initialize(match_type, rate_names)
@match_type = match_type
@comparator = match_type == :exact ? '==' : 'include?'
@rate_names = rate_names&.map { |rate_name| rate_name.downcase.strip }
end
def match?(shipping_rate)
if @match_type == :all
true
else
@rate_names.any? { |name| shipping_rate.name.downcase.send(@comparator, name) }
end
end
end
# ================================================================
# HideRatesForProduct
# If the cart contains any matching items, the entered rate(s) are hidden.
# ================================================================
class HideRatesForProduct
def initialize(campaigns)
@campaigns = campaigns
end
def run(cart, shipping_rates)
address = cart.shipping_address
campaign_satisified = false
return if address.nil?
@campaigns.each do |campaign|
product_selector = ProductSelector.new(
campaign[:product_selector_match_type],
campaign[:product_selector_type],
campaign[:product_selectors],
)
if campaign[:product_selector_match_scope] == :all
product_match = cart.line_items.all? { |line_item| product_selector.match?(line_item) }
else
product_match = cart.line_items.any? { |line_item| product_selector.match?(line_item) }
end
next unless product_match
rate_name_selector = RateNameSelector.new(
campaign[:rate_match_type],
campaign[:rate_names],
)
shipping_rates.each do |shipping_rate|
if rate_name_selector.match?(shipping_rate)
campaign_satisified = true
puts "matched product campaign"
end
end
shipping_rates.delete_if do |shipping_rate|
rate_name_selector.match?(shipping_rate)
end
end
return campaign_satisified
end
end
# ================================================================
# HideRatesForProvinceCodeCampaign
#
# If the cart's shipping address zip/province/country match the
# entered settings, the entered rate(s) are hidden.
# ================================================================
class HideRatesIfNotProvince
def initialize(campaigns)
@campaigns = campaigns
end
def run(cart, shipping_rates)
address = cart.shipping_address
campaign_satisified = false
return if address.nil?
@campaigns.each do |campaign|
province_code_selector = ProvinceCodeSelector.new(campaign[:province_code_match_type], campaign[:province_codes])
province_not_found = !province_code_selector.match?(address.province_code)
next unless province_not_found
campaign_satisified = true
puts "matched missing province code campaign"
rate_name_selector = RateNameSelector.new(
campaign[:rate_match_type],
campaign[:rate_names],
)
shipping_rates.delete_if do |shipping_rate|
rate_name_selector.match?(shipping_rate)
end
end
return campaign_satisified
end
end
CAMPAIGNS = [
HideRatesIfNotProvince.new(HIDE_RATES_IF_NOT_PROVINCE_CODE),
HideRatesForProduct.new(HIDE_RATES_FOR_ONLY_SPECIAL_ORDER),
HideRatesForProduct.new(HIDE_RATES_FOR_MIXED_ORDER),
HideRatesForProduct.new(HIDE_RATES_FOR_STOCK_ORDER)
]
CAMPAIGNS.each do |campaign|
break if campaign.run(Input.cart, Input.shipping_rates)
end
Output.shipping_rates = Input.shipping_rates
Thank you @playwright-mike for sharing this.
I gave it a try and got an error starting line 73:
[Error] nil is not a symbol
Test Script:73:in ProductSelector.match?
Test Script:147:in HideRatesForProduct.run
shopify/std_lib/core/list.rb:41:in List.each
Test Script:147:in HideRatesForProduct.run
Test Script:139:in HideRatesForProduct.run
Test Script:224:in Object.call
Test Script:223
Hope this helps 😕
This is an accepted solution.
Something keeps happening with that "@selector_type" variable name. It was getting capitalized for some reason. I've removed that:
HIDE_RATES_IF_NOT_PROVINCE_CODE = [
{
province_code_match_type: :exact,
province_codes: ["BC","AB","ON","SK","MB","NB","NS","PE","QC"],
rate_match_type: :exact,
rate_names: ["Free Shipping ($35 min.)",
"$5.99 Flat Rate",
"Send me the special order item(s) when available.",
"I can wait for all items to be available and help offset carbon footprint.",
"Send me the special order item(s) when available."],
},
]
HIDE_RATES_FOR_ONLY_SPECIAL_ORDER = [
{
product_selector_match_type: :include,
product_selector_match_scope: :all,
product_selector_type: :tag,
product_selectors: ["status-special-order"],
rate_match_type: :exact,
rate_names: ["Free Shipping ($35 min.)",
"$5.99 Flat Rate",
"Expedited Parcel",
"Xpresspost",
"Priority",
"Send me the stocked item(s) now and the special item(s) when available.",
"I can wait for all items to be available and help offset carbon footprint."],
},
]
HIDE_RATES_FOR_MIXED_ORDER = [
{
product_selector_match_type: :include,
product_selector_match_scope: :any,
product_selector_type: :tag,
product_selectors: ["status-special-order"],
rate_match_type: :exact,
rate_names: ["Free Shipping ($35 min.)",
"$5.99 Flat Rate",
"Expedited Parcel",
"Xpresspost",
"Priority",
"Send me the special order item(s) when available."],
},
]
HIDE_RATES_FOR_STOCK_ORDER = [
{
product_selector_match_type: :exclude,
product_selector_match_scope: :any,
product_selector_type: :tag,
product_selectors: ["status-special-order"],
rate_match_type: :exact,
rate_names: ["Send me the stocked item(s) now and the special item(s) when available.",
"I can wait for all items to be available and help offset carbon footprint.",
"Send me the special order item(s) when available."],
},
]
# ================================================================
# ProductSelector
# Finds matching products by the entered criteria.
# ================================================================
class ProductSelector
def initialize(match_type, selector_type, selectors)
@match_type = match_type
@comparator = match_type == :include ? 'any?' : 'none?'
@Selector_type = selector_type # this line is getting edited by the forum system, it should begin with @ and then the word 'selector_type' and then be equal to 'selector_type' (all lowercase)
@selectors = selectors
end
def match?(line_item)
if self.respond_to?(@selector_type)
self.send(@selector_type, line_item)
else
raise RuntimeError.new('Invalid product selector type')
end
end
def tag(line_item)
product_tags = line_item.variant.product.tags.map { |tag| tag.downcase.strip }
@selectors = @selectors.map { |selector| selector.downcase.strip }
(@selectors & product_tags).send(@comparator)
end
end
# ================================================================
# ProvinceCodeSelector
#
# Finds whether the supplied province code matches any of the entered
# strings.
# ================================================================
class ProvinceCodeSelector
def initialize(match_type, province_codes)
@comparator = match_type == :exact ? '==' : 'include?'
@province_codes = province_codes.map { |province_code| province_code.upcase.strip }
end
def match?(province_code)
@province_codes.any? { |pc| province_code.to_s.upcase.strip.send(@comparator, pc) }
end
end
# ================================================================
# RateNameSelector
# Finds whether the supplied rate names match any of the entered names.
# ================================================================
class RateNameSelector
def initialize(match_type, rate_names)
@match_type = match_type
@comparator = match_type == :exact ? '==' : 'include?'
@rate_names = rate_names&.map { |rate_name| rate_name.downcase.strip }
end
def match?(shipping_rate)
if @match_type == :all
true
else
@rate_names.any? { |name| shipping_rate.name.downcase.send(@comparator, name) }
end
end
end
# ================================================================
# HideRatesForProduct
# If the cart contains any matching items, the entered rate(s) are hidden.
# ================================================================
class HideRatesForProduct
def initialize(campaigns)
@campaigns = campaigns
end
def run(cart, shipping_rates)
address = cart.shipping_address
campaign_satisified = false
return if address.nil?
@campaigns.each do |campaign|
product_selector = ProductSelector.new(
campaign[:product_selector_match_type],
campaign[:product_selector_type],
campaign[:product_selectors],
)
if campaign[:product_selector_match_scope] == :all
product_match = cart.line_items.all? { |line_item| product_selector.match?(line_item) }
else
product_match = cart.line_items.any? { |line_item| product_selector.match?(line_item) }
end
next unless product_match
rate_name_selector = RateNameSelector.new(
campaign[:rate_match_type],
campaign[:rate_names],
)
shipping_rates.each do |shipping_rate|
if rate_name_selector.match?(shipping_rate)
campaign_satisified = true
puts "matched product campaign"
end
end
shipping_rates.delete_if do |shipping_rate|
rate_name_selector.match?(shipping_rate)
end
end
return campaign_satisified
end
end
# ================================================================
# HideRatesForProvinceCodeCampaign
#
# If the cart's shipping address zip/province/country match the
# entered settings, the entered rate(s) are hidden.
# ================================================================
class HideRatesIfNotProvince
def initialize(campaigns)
@campaigns = campaigns
end
def run(cart, shipping_rates)
address = cart.shipping_address
campaign_satisified = false
return if address.nil?
@campaigns.each do |campaign|
province_code_selector = ProvinceCodeSelector.new(campaign[:province_code_match_type], campaign[:province_codes])
province_not_found = !province_code_selector.match?(address.province_code)
next unless province_not_found
campaign_satisified = true
puts "matched missing province code campaign"
rate_name_selector = RateNameSelector.new(
campaign[:rate_match_type],
campaign[:rate_names],
)
shipping_rates.delete_if do |shipping_rate|
rate_name_selector.match?(shipping_rate)
end
end
return campaign_satisified
end
end
CAMPAIGNS = [
HideRatesIfNotProvince.new(HIDE_RATES_IF_NOT_PROVINCE_CODE),
HideRatesForProduct.new(HIDE_RATES_FOR_ONLY_SPECIAL_ORDER),
HideRatesForProduct.new(HIDE_RATES_FOR_MIXED_ORDER),
HideRatesForProduct.new(HIDE_RATES_FOR_STOCK_ORDER)
]
CAMPAIGNS.each do |campaign|
break if campaign.run(Input.cart, Input.shipping_rates)
end
Output.shipping_rates = Input.shipping_rates
Hi @playwright-mike , I just gave it a try and still getting the exact same errors.
I also compared this script to the previous version you sent, and they are identical. Was this meant to be?
Thanks again 🙂
This is an accepted solution.
Thanks for your patience on this. Very weird, I think the post is being formatted or changed by community forum system.
Just make this line say:
@selector_type = selector_type
(basically just change the capital S for a lowercase s)
I found out what was happening, the forum things I am trying to "mention" someone by typing "@" and then some name. I am not sure why it picks that particular line, but it does.
Geez!
Hahaha great find @playwright-mike !
I did make the correction, and was able to test it. Everything seems to be working just fine now.
Once again, thank you very much for your help 🙂
Lol, what a thread. Happy to help!
This is great work, and has helped me figure out a solution to my shipping issue as well! 🙂
Many thanks.
Would it be possible to add code to this same script to also handle hiding shipping options based on the cart subtotal being over £50, for example?
I am not sure how to do this, if anyone could help?
Cheers,
Rob
Hello Matt,
I am using the below script to hide all shipping methods if the product tag in the cart but I only want to block delivery for the selected postcode
When I use this scrip it blocks all the postcode
Would you able to help
# GENERATED BY THE SHOPIFY SCRIPT CREATOR APP
class Campaign
def initialize(condition, *qualifiers)
@condition = (condition.to_s + '?').to_sym
@qualifiers = PostCartAmountQualifier ? [] : [] rescue qualifiers.compact
@Anonymous_item_selector = qualifiers.last unless @Anonymous_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 @Li_match_type.nil?
cart.line_items.send(@li_match_type) { |item| qualifier.match?(item) }
else
qualifier.match?(cart, @Anonymous_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)
@discount.apply_final_discount if @discount && @discount.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)
@Li_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 ZipCodeQualifier < Qualifier
def initialize(match_type, match_condition, zips)
@match_condition = match_condition
@invert = match_type == :does_not
@zips = zips.map(&:downcase).map {|z| z.gsub(' ', '')}
end
def match?(cart, selector = nil)
return false if cart.shipping_address&.zip.nil?
zip_code = cart.shipping_address.zip.downcase.gsub(' ', '')
case @match_condition
when :match
return @invert ^ @zips.include?(zip_code)
else
return @invert ^ partial_match(@match_condition, zip_code, @zips)
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 ProductTagSelector < Selector
def initialize(match_type, match_condition, tags)
@match_condition = match_condition
@invert = match_type == :does_not
@Anonymous = tags.map(&:downcase)
end
def match?(line_item)
product_tags = line_item.variant.product.tags.to_a.map(&:downcase)
case @match_condition
when :match
return @invert ^ ((@tags & product_tags).length > 0)
else
return @invert ^ partial_match(@match_condition, product_tags, @Anonymous)
end
end
end
class AllRatesSelector
def match?(rate)
return true
end
end
CAMPAIGNS = [
ConditionallyHideRates.new(
:any,
nil,
ZipCodeQualifier.new(
:does,
:start_with,
["AB31", "AB32"]
),
:any,
ProductTagSelector.new(
:does,
:include,
["block"]
),
AllRatesSelector.new()
)
].freeze
CAMPAIGNS.each do |campaign|
campaign.run(Input.shipping_rates, Input.cart)
end
Output.shipping_rates = Input.shipping_rates
Hey Community! As the holiday season unfolds, we want to extend heartfelt thanks to a...
By JasonH Dec 6, 2024Dropshipping, a high-growth, $226 billion-dollar industry, remains a highly dynamic bus...
By JasonH Nov 27, 2024Hey Community! It’s time to share some appreciation and celebrate what we have accomplis...
By JasonH Nov 14, 2024