Shipping rate script examples
这个页面是印在4月17日,2023年。的坏蛋rent version, visit https://help.shopify.com/en/manual/checkout-settings/script-editor/examples/shipping-scripts.
Shipping scripts interact with shipping rates, and can change a rate's title, visibility, display order, and price. These scripts run each time that your customer accesses the shipping options page at checkout.
Shipping scripts that discount asubscription apply to the first payment of the subscription only. Subsequent payments are not discounted by the script.
Shopify Plus
Shopify Scripts and the Script Editor app are available toShopify Plus merchants only. The Script Editor app is no longer available for download from the Shopify App Store.
On August 13, 2024, Shopify Scripts will be deprecated and will no longer be supported. Migrate your existing Scripts toShopify Functions before this date.
To use the templates on this page, create a new script with a blank template.
Steps:
From your Shopify admin, go toApps >Script Editor .
ClickCreate script .
ClickShipping rates .
SelectBlank template , then clickCreate script .
In theRuby source code section, delete the default line of code:Output.cart = Input.cart
Copy a script from this page and paste it into theRuby source code section.
Edit theCustomizable Settings section of the script to function in your store.
Test your script. For more information, refer toTesting and debugging Shopify Scripts .
After testing:
clickSave draft to save an unpublished draft of the script, or
clickSave and publish to create and publish the script.
Add a message to rate names for specific provinces and countries
Use this script to add a message to shipping rates based on the province and country of the shipping address.
For example, add a message to British Columbia and Ontario (Canada), and Washington and New York (United States) shipping rates that statesDue to COVID-19 disruptions, shipping may take longer than normal.
Note
The use ofprovince
andprovince_code
, andcountry
andcountry_code
is specific to the region's equivalent - ie. province/state/region, or country/region.
# ================================ Customizable Settings ================================ # ================================================================ # Add Message to Rate Names for Province or Country # # If the cart's shipping address province/country matches # the entered settings, all shipping rates will have the # entered message appended to their name. # # - 'country_code' is a 2-character abbreviation for the # applicable country # - 'province_code_match_type' determines whether we look for # provinces that do, or don't, match the entered options, or # all provinces. Can be: # - ':include' to look for provinces that DO match # - ':exclude' to look for provinces that DO NOT match # - ':all' to look for all provinces # - 'province_codes' is a list of 2-character abbreviations for # the applicable provinces # - 'message' is the message to append to rate names # ================================================================ RATE_MESSAGE_FOR_PROVINCE_COUNTRY = [ { country_code: "CA" , province_code_match_type: :include , province_codes: [ "BC" , "ON" ], message: "Due to COVID-19 disruptions, shipping may take longer than normal." }, { country_code: "US" , province_code_match_type: :include , province_codes: [ "NY" , "WA" ], message: "Due to COVID-19 disruptions, shipping may take longer than normal." }, ] # ================================ Script Code (do not edit) =============================== # ================================================================ # ProvinceSelector # # Finds whether the supplied province code matches the entered # strings. # ================================================================ class ProvinceSelector def initialize ( match_type , provinces ) @match_type = match_type @provinces = provinces . map { | province | province . upcase . strip } end def match? ( province_code ) if @match_type == :all true else ( @match_type == :include ) == @provinces . any? { | province | province_code . upcase . strip == province } end end end # ================================================================ # AddMessageToRateForProvinceCountryCampaign # # If the cart's shipping address country/province matches the # entered settings, all shipping rates will have the entered # message appended to their name # ================================================================ class AddMessageToRateForProvinceCountryCampaign def initialize ( campaigns ) @campaigns = campaigns end def run ( cart , shipping_rates ) return if cart . shipping_address . nil? address = cart . shipping_address @campaigns . each do | campaign | next unless address . country_code . upcase . strip == campaign [ :country_code ]. upcase . strip province_selector = ProvinceSelector . new ( campaign [ :province_code_match_type ], campaign [ :province_codes ]) next unless province_selector . match? ( address . province_code ) shipping_rates . each do | shipping_rate | rate_name = shipping_rate . name + ' - ' + campaign [ :message ] shipping_rate . change_name ( rate_name ) end end end end CAMPAIGNS = [ AddMessageToRateForProvinceCountryCampaign . new ( RATE_MESSAGE_FOR_PROVINCE_COUNTRY ), ] CAMPAIGNS . each do | campaign | campaign . run ( Input . cart , Input . shipping_rates ) end Output . shipping_rates = Input . shipping_rates
Show rates for a specific zip code, province, and country
Use this script to show only specific shipping rates to customers from a specific location.
For example, show only a particular shipping rate to customers in the 90210 zip code of California. The rate is hidden for all other locations.
Note
The use ofzip_code
,province
andprovince_code
, andcountry
andcountry_code
is specific to the region's equivalent - ie. zip code/postal code, province/state/region, or country/region.
# ================================ Customizable Settings ================================ # ================================================================ # Show Rate(s) for Zip/Province/Country # # If the cart's shipping address country/province/zip match the # entered settings, the entered rate(s) are shown, and all other # rates are hidden. Otherwise, the entered rate(s) are hidden. # # - 'country_code' is a 2-character abbreviation for the # applicable country # - 'province_code' is a list of 2-character abbreviations for # the applicable province(s) # - 'zip_code_match_type' determines whether the below strings # should be an exact or partial match. Can be: # - ':exact' for an exact match # - ':partial' for a partial match # - 'zip_codes' is a list of strings to identify zip codes # - 'rate_match_type' determines whether the below strings # should be an exact or partial match. Can be: # - ':exact' for an exact match # - ':partial' for a partial match # - ':all' for all rates # - 'rate_names' is a list of strings to identify rates # - if using ':all' above, this can be set to 'nil' # ================================================================ SHOW_RATES_FOR_ZIP_PROVINCE_COUNTRY = [ { country_code: "US" , province_code: "CA" , zip_code_match_type: :exact , zip_codes: [ "90210" ], rate_match_type: :exact , rate_names: [ "Shipping Rate" ], }, ] # ================================ Script Code (do not edit) ================================ # ================================================================ # ZipCodeSelector # # Finds whether the supplied zip code matches any of the entered # strings. # ================================================================ class ZipCodeSelector def initialize ( match_type , zip_codes ) @comparator = match_type == :exact ? '==' : 'include?' @zip_codes = zip_codes . map { | zip_code | zip_code . upcase . strip } end def match? ( zip_code ) @zip_codes . any? { | zip | zip_code . to_s . upcase . strip . send ( @comparator , zip ) } end end # ================================================================ # RateNameSelector # # Finds whether the supplied rate name matches 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 # ================================================================ # ShowRatesForZipProvinceCountryCampaign # # If the cart's shipping address zip/province/country match the # entered settings, the entered rate(s) are shown, and all other # rates are hidden. Otherwise, the entered rate(s) are hidden. # ================================================================ class ShowRatesForZipProvinceCountryCampaign def initialize ( campaigns ) @campaigns = campaigns end def run ( cart , shipping_rates ) address = cart . shipping_address @campaigns . each do | campaign | zip_code_selector = ZipCodeSelector . new ( campaign [ :zip_code_match_type ], campaign [ :zip_codes ]) rate_name_selector = RateNameSelector . new ( campaign [ :rate_match_type ], campaign [ :rate_names ]) if address . nil? full_match = false else country_match = address . country_code . upcase . strip == campaign [ :country_code ]. upcase . strip province_match = address . province_code . upcase . strip == campaign [ :province_code ]. upcase . strip zip_match = zip_code_selector . match? ( address . zip ) full_match = country_match && province_match && zip_match end shipping_rates . delete_if do | shipping_rate | rate_name_selector . match? ( shipping_rate ) != full_match end end end end CAMPAIGNS = [ ShowRatesForZipProvinceCountryCampaign . new ( SHOW_RATES_FOR_ZIP_PROVINCE_COUNTRY ), ] CAMPAIGNS . each do | campaign | campaign . run ( Input . cart , Input . shipping_rates ) end Output . shipping_rates = Input . shipping_rates
Hide rates for a specific zip code, province, and country
Use this script to hide specific rates from customers from a specific location.
For example, hide a particular shipping rate from customers in the 90210 zip code in California.
Note
The use ofzip_code
,province
andprovince_code
, andcountry
andcountry_code
is specific to the region's equivalent - ie. zip code/postal code, province/state/region, or country/region.
# ================================ Customizable Settings ================================ # ================================================================ # Hide Rate(s) for Zip/Province/Country # # If the cart's shipping address country/province/zip match the # entered settings, the entered rate(s) are hidden. # # - 'country_code' is a 2-character abbreviation for the # applicable country or region # - 'province_code' is a list of 2-character abbreviations for # the applicable provinces or states # - 'zip_code_match_type' determines whether the below strings # should be an exact or partial match. Can be: # - ':exact' for an exact match # - ':partial' for a partial match # - 'zip_codes' is a list of strings to identify zip codes # - 'rate_match_type' determines whether the below strings # should be an exact or partial match. Can be: # - ':exact' for an exact match # - ':partial' for a partial match # - ':all' for all rates # - 'rate_names' is a list of strings to identify rates # - if using ':all' above, this can be set to 'nil' # ================================================================ HIDE_RATES_FOR_ZIP_PROVINCE_COUNTRY = [ { country_code: "US" , province_code: "CA" , zip_code_match_type: :exact , zip_codes: [ "90210" ], rate_match_type: :exact , rate_names: [ "Shipping Rate" ], }, ] # ================================ Script Code (do not edit) ================================ # ================================================================ # ZipCodeSelector # # Finds whether the supplied zip code matches any of the entered # strings. # ================================================================ class ZipCodeSelector def initialize ( match_type , zip_codes ) @comparator = match_type == :exact ? '==' : 'include?' @zip_codes = zip_codes . map { | zip_code | zip_code . upcase . strip } end def match? ( zip_code ) @zip_codes . any? { | zip | zip_code . to_s . upcase . strip . send ( @comparator , zip ) } end end # ================================================================ # RateNameSelector # # Finds whether the supplied rate name matches 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 # ================================================================ # HideRatesForZipProvinceCountryCampaign # # If the cart's shipping address zip/province/country match the # entered settings, the entered rate(s) are hidden. # ================================================================ class HideRatesForZipProvinceCountryCampaign def initialize ( campaigns ) @campaigns = campaigns end def run ( cart , shipping_rates ) address = cart . shipping_address return if address . nil? @campaigns . each do | campaign | zip_code_selector = ZipCodeSelector . new ( campaign [ :zip_code_match_type ], campaign [ :zip_codes ]) country_match = address . country_code . upcase . strip == campaign [ :country_code ]. upcase . strip province_match = address . province_code . upcase . strip == campaign [ :province_code ]. upcase . strip zip_match = zip_code_selector . match? ( address . zip ) next unless country_match && province_match && zip_match 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 end end CAMPAIGNS = [ HideRatesForZipProvinceCountryCampaign . new ( HIDE_RATES_FOR_ZIP_PROVINCE_COUNTRY ), ] CAMPAIGNS . each do | campaign | campaign . run ( Input . cart , Input . shipping_rates ) end Output . shipping_rates = Input . shipping_rates
Hide rates for specific products in certain countries
Use this script to hide rates from customers from a specific country when they purchase a specific item.
For example, hide a particular shipping rate from customers in Canada if they purchase a T-shirt.
# ================================ Customizable Settings ================================ # ================================================================ # Hide Rate(s) for Product/Country # # If the cart contains any matching items, and we have a matching # country, the entered rate(s) are hidden. # # - 'product_selector_match_type' determines whether we look for # products that do or don't match the entered selectors. Can # be: # - ':include' to check if the product does match # - ':exclude' to make sure the product doesn't match # - 'product_selector_type' determines how eligible products # will be identified. Can be either: # - ':tag' to find products by tag # - ':type' to find products by type # - ':vendor' to find products by vendor # - ':product_id' to find products by ID # - ':variant_id' to find products by variant ID #——“:订阅订阅连续cts # - 'product_selectors' is a list of tags or IDs to identify # associated products # - 'country_code_match_type' determines whether we look for # countries that do, or don't, match the entered options, or # all countries. Can be: # - ':include' to look for countries that DO match # - ':exclude' to look for countries that DO NOT match # - ':all' to look for all countries # - 'country_codes' is a list of country code abbreviations # - ie. United States would be `US` # - 'rate_match_type' determines whether the below strings # should be an exact or partial match. Can be: # - ':exact' for an exact match # - ':partial' for a partial match # - ':all' for all rates # - 'rate_names' is a list of strings to identify rates # - if using ':all' above, this can be set to 'nil' # ================================================================ HIDE_RATES_FOR_PRODUCT_AND_COUNTRY = [ { product_selector_match_type: :include , product_selector_type: :product_id , product_selectors: [ 1234567890987 , 1234567890986 ], country_code_match_type: :include , country_codes: [ "CA" ], rate_match_type: :exact , rate_names: [ "Shipping Rate" ], }, ] # ================================ Script Code (do not edit) ================================ # ================================================================ # 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 def type ( line_item ) @selectors = @selectors . map { | selector | selector . downcase . strip } ( @match_type == :include ) == @selectors . include? ( line_item . variant . product . product_type . downcase . strip ) end def vendor ( line_item ) @selectors = @selectors . map { | selector | selector . downcase . strip } ( @match_type == :include ) == @selectors . include? ( line_item . variant . product . vendor . downcase . strip ) end def product_id ( line_item ) ( @match_type == :include ) == @selectors . include? ( line_item . variant . product . id ) end def variant_id ( line_item ) ( @match_type == :include ) == @selectors . include? ( line_item . variant . id ) end def subscription ( line_item ) ! line_item . selling_plan_id . nil? end end # ================================================================ # CountrySelector # # Finds whether the supplied country code matches the entered # strings. # ================================================================ class CountrySelector def initialize ( match_type , countries ) @match_type = match_type @countries = countries . map { | country | country . upcase . strip } end def match? ( country_code ) if @match_type == :all true else ( @match_type == :include ) == @countries . any? { | country | country_code . upcase . strip == country } end end end # ================================================================ # RateNameSelector # # Finds whether the supplied rate name matches 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 # ================================================================ # HideRatesForProductCountryCampaign # # If the cart contains any matching items, and we have a matching # country, the entered rate(s) are hidden. # ================================================================ class HideRatesForProductCountryCampaign def initialize ( campaigns ) @campaigns = campaigns end def run ( cart , shipping_rates ) address = cart . shipping_address return if address . nil? @campaigns . each do | campaign | product_selector = ProductSelector . new ( campaign [ :product_selector_match_type ], campaign [ :product_selector_type ], campaign [ :product_selectors ], ) country_selector = CountrySelector . new ( campaign [ :country_code_match_type ], campaign [ :country_codes ]) product_match = cart . line_items . any? { | line_item | product_selector . match? ( line_item ) } country_match = country_selector . match? ( address . country_code ) next unless product_match && country_match 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 end end CAMPAIGNS = [ HideRatesForProductCountryCampaign . new ( HIDE_RATES_FOR_PRODUCT_AND_COUNTRY ), ] CAMPAIGNS . each do | campaign | campaign . run ( Input . cart , Input . shipping_rates ) end Output . shipping_rates = Input . shipping_rates
Hide rates for PO box deliveries
使用这个脚本隐藏成本的一个特定的利率从mers if their shipping address is a PO box.
Note
The use ofprovince
andprovince_code
, andcountry
andcountry_code
is specific to the region's equivalent - ie. province/state/region, or country/region.
# ================================ Customizable Settings ================================ # ================================================================ # Hide Rate(s) for PO Box addresses # # If the shipping address contains any of the entered "PO Box" # identifiers, the entered rate(s) are hidden. # # - 'po_box_triggers' is a list of possible strings for a PO # Box address # - 'rate_match_type' determines whether the below strings # should be an exact or partial match. Can be: # - ':exact' for an exact match # - ':partial' for a partial match # - ':all' for all rates # - 'rate_names' is a list of rates to show/hide if the above # conditions are met # ================================================================ HIDE_RATES_FOR_PO_BOX = [ { po_box_triggers: [ "po box" , "post office" , "p o box" , "p.o.box" , "p.o. box" , "p.o box" , "pobox" , "post office box" , "post box" , "p. o. box" , "po. box" , "postal box" , ], rate_match_type: :exact , rate_names: [ "Shipping Rate" , "Other Shipping Rate" ], }, ] # ================================ Script Code (do not edit) ================================ # ================================================================ # AddressSelector # # Finds whether the supplied address contains any of the entered # strings. # ================================================================ class AddressSelector def initialize ( triggers ) @triggers = triggers . map { | trigger | trigger . downcase . strip } end def match? ( address ) address_fields = [ address . address1 , address . address2 ]. map do | line | line . nil? ? "" : line . downcase end address_fields = address_fields . 加入 ( " " ) @triggers . any? { | trigger | address_fields . include? ( trigger ) } end end # ================================================================ # RateNameSelector # # Finds whether the supplied rate name matches 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 # ================================================================ # HideRatesForPOBoxCampaign # # If the shipping address contains any of the entered "PO Box" # identifiers, the entered rate(s) are hidden. # ================================================================ class HideRatesForPOBoxCampaign def initialize ( campaigns ) @campaigns = campaigns end def run ( cart , shipping_rates ) address = cart . shipping_address return if address . nil? @campaigns . each do | campaign | next unless AddressSelector . new ( campaign [ :po_box_triggers ]). match? ( address ) 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 end end CAMPAIGNS = [ HideRatesForPOBoxCampaign . new ( HIDE_RATES_FOR_PO_BOX ), ] CAMPAIGNS . each do | campaign | campaign . run ( Input . cart , Input . shipping_rates ) end Output . shipping_rates = Input . shipping_rates
Show rates by customer tag
Use this script to show only a specific rate to specifically tagged customers.
For example, show only a particular shipping rate to customers with theVIP
tag.
# ================================ Customizable Settings ================================ # ================================================================ # Show Rate(s) for Customer Tag # # If we have a matching customer, the entered rate(s) will be # shown, and all others will be hidden. Otherwise, the entered # rate(s) will be hidden. # # - 'customer_tag_match_type' determines whether we look for the # customer to be tagged with any of the entered tags or not. # Can be: # - ':include' to check if the customer is tagged # - ':exclude' to make sure the customer isn't tagged # - 'customer_tags' is a list of customer tags to trigger the # campaign # - 'rate_match_type' determines whether the below strings # should be an exact or partial match. Can be: # - ':exact' for an exact match # - ':partial' for a partial match # - 'rate_names' is a list of strings to identify rates # ================================================================ SHOW_RATES_FOR_CUSTOMER_TAG = [ { customer_tag_match_type: :include , customer_tags: [ "customer_tag" , "another_tag" ], rate_match_type: :exact , rate_names: [ "Shipping Rate" , "Other Shipping Rate" ], }, ] # ================================ Script Code (do not edit) ================================ # ================================================================ # CustomerTagSelector # # Finds whether the supplied customer has any of the entered tags. # ================================================================ class CustomerTagSelector def initialize ( match_type , tags ) @comparator = match_type == :include ? 'any?' : 'none?' @tags = tags . map { | tag | tag . downcase . strip } end def match? ( customer ) customer_tags = customer . tags . map { | tag | tag . downcase . strip } ( @tags & customer_tags ). send ( @comparator ) end end # ================================================================ # RateNameSelector # # Finds whether the supplied rate name matches any of the entered # names. # ================================================================ class RateNameSelector def initialize ( match_type , rate_names ) @comparator = match_type == :exact ? '==' : 'include?' @rate_names = rate_names . map { | rate_name | rate_name . downcase . strip } end def match? ( shipping_rate ) @rate_names . any? { | name | shipping_rate . name . downcase . send ( @comparator , name ) } end end # ================================================================ # ShowRateForCustomerTagCampaign # # If we have a matching customer, the entered rate(s) will be # shown, and all others will be hidden. Otherwise, the entered # rate(s) will be hidden. # ================================================================ class ShowRateForCustomerTagCampaign def initialize ( campaigns ) @campaigns = campaigns end def run ( cart , shipping_rates ) @campaigns . each do | campaign | customer_tag_selector = CustomerTagSelector . new ( campaign [ :customer_tag_match_type ], campaign [ :customer_tags ] ) customer_match = cart . customer . nil? ? false : customer_tag_selector . match? ( cart . customer ) 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 ) != customer_match end end end end CAMPAIGNS = [ ShowRateForCustomerTagCampaign . new ( SHOW_RATES_FOR_CUSTOMER_TAG ), ] CAMPAIGNS . each do | campaign | campaign . run ( Input . cart , Input . shipping_rates ) end Output . shipping_rates = Input . shipping_rates
重新排序率
Use this script to change the default order of the shipping rates offered to your customers.
# ================================ Customizable Settings ================================ # ================================================================ # The order in which you would like your rates to display # ================================================================ DESIRED_RATE_ORDER = [ "Shipping Rate 1" , "Shipping Rate 2" , "Shipping Rate 3" , ] # ================================ Script Code (do not edit) ================================ # ================================================================ # ReorderRatesCampaign # # Reorders rates into the entered order # ================================================================ class ReorderRatesCampaign def initialize ( desired_order ) @desired_order = desired_order . map { | item | item . downcase . strip } end def run ( cart , shipping_rates ) shipping_rates . sort_by! { | rate | @desired_order . index ( rate . name . downcase . strip ) || Float :: INFINITY } end end CAMPAIGNS = [ ReorderRatesCampaign . new ( DESIRED_RATE_ORDER ), ] CAMPAIGNS . each do | campaign | campaign . run ( Input . cart , Input . shipping_rates ) end Output . shipping_rates = Input . shipping_rates
Discount rates by discount code
Use this script to offer a discount on a specific rate if the customer has used a specific discount code in the checkout.
For example, if your customer has used the "DISCOUNT_15" discount code, discount a particular rate.
# ================================ Customizable Settings ================================ # ================================================================ # Discount Rate(s) by Discount Code(s) # # If one of the entered discount codes is used, the entered # rate(s) are discounted by the entered amount. # # - 'discount_code_match_type' determines whether the below # strings should be an exact or partial match. Can be: # - ':exact' for an exact match # - ':partial' for a partial match # - 'discount_codes' is a list of strings to identify discount # codes # - 'rate_match_type' determines whether the below strings # should be an exact or partial match. Can be: # - ':exact' for an exact match # - ':partial' for a partial match # - 'rate_names' is a list of strings to identify rates # - 'discount_type' is the type of discount to provide. Can be # either: # - ':percent' # - ':dollar' # - 'discount_amount' is the percentage/dollar discount to # apply # - 'discount_message' is the message to show when a discount # is applied # ================================================================ DISCOUNTS_FOR_DISCOUNT_CODES = [ { discount_code_match_type: :exact , discount_codes: [ "TESTCODE1" , "TESTCODE2" ], rate_match_type: :exact , rate_names: [ "Shipping Rate" , "Other Shipping Rate" ], discount_type: :percent , discount_amount: 100 , discount_message: "Free Shipping with discount code" }, ] # ================================ Script Code (do not edit) ================================ # ================================================================ # DiscountCodeSelector # # Finds whether the supplied discount code matches any of the # entered codes. # ================================================================ class DiscountCodeSelector def initialize ( match_type , discount_codes ) @comparator = match_type == :exact ? '==' : 'include?' @discount_codes = discount_codes . map { | discount_code | discount_code . upcase . strip } end def match? ( discount_code ) @discount_codes . any? { | code | discount_code . code . upcase . send ( @comparator , code ) } end end # ================================================================ # RateNameSelector # # Finds whether the supplied rate name matches any of the entered # names. # ================================================================ class RateNameSelector def initialize ( match_type , rate_names ) @comparator = match_type == :exact ? '==' : 'include?' @rate_names = rate_names . map { | rate_name | rate_name . downcase . strip } end def match? ( shipping_rate ) @rate_names . any? { | name | shipping_rate . name . downcase . send ( @comparator , name ) } end end # ================================================================ # DiscountApplicator # # Applies the entered discount to the supplied shipping rate. # ================================================================ class DiscountApplicator def initialize ( discount_type , discount_amount , discount_message ) @discount_type = discount_type @discount_message = discount_message @discount_amount = if discount_type == :percent discount_amount * 0.01 else Money . new ( cents: 100 ) * discount_amount end end def apply ( shipping_rate ) rate_discount = if @discount_type == :percent shipping_rate . price * @discount_amount else @discount_amount end shipping_rate . apply_discount ( rate_discount , message: @discount_message ) end end # ================================================================ # DiscountRatesForDiscountCodeCampaign # # If one of the entered discount codes is used, the entered # rate(s) are discounted by the entered amount. # ================================================================ class DiscountRatesForDiscountCodeCampaign def initialize ( campaigns ) @campaigns = campaigns end def run ( cart , shipping_rates ) return if cart . discount_code . nil? @campaigns . each do | campaign | discount_code_selector = DiscountCodeSelector . new ( campaign [ :discount_code_match_type ], campaign [ :discount_codes ]) next unless discount_code_selector . match? ( cart . discount_code ) rate_name_selector = RateNameSelector . new ( campaign [ :rate_match_type ], campaign [ :rate_names ]) discount_applicator = DiscountApplicator . new ( campaign [ :discount_type ], campaign [ :discount_amount ], campaign [ :discount_message ], ) shipping_rates . each do | shipping_rate | next unless rate_name_selector . match? ( shipping_rate ) discount_applicator . apply ( shipping_rate ) end end end end CAMPAIGNS = [ DiscountRatesForDiscountCodeCampaign . new ( DISCOUNTS_FOR_DISCOUNT_CODES ), ] CAMPAIGNS . each do | campaign | campaign . run ( Input . cart , Input . shipping_rates ) end Output . shipping_rates = Input . shipping_rates
Discount rate by customer tag
Use this script to discount a specific rate for specifically tagged customers.
For example, offer a 10% discount on a particular rate if the customer has theVIP
tag.
# ================================ Customizable Settings ================================ # ================================================================ # Discount Rate(s) for Customer Tag(s) # # If we have a matching customer, the entered rate(s) are # discounted by the entered amount. # # - 'customer_tag_match_type' determines whether we look for the customer # to be tagged with any of the entered tags or not. Can be: # - ':include' to check if the customer is tagged # - ':exclude' to make sure the customer isn't tagged # - 'customer_tags' is a list of customer tags to qualify for # a discount # - 'rate_match_type' determines whether the below strings # should be an exact or partial match. Can be: # - ':exact' for an exact match # - ':partial' for a partial match # - 'rate_names' is a list of strings to identify rates # - 'discount_type' is the type of discount to provide. Can be # either: # - ':percent' # - ':dollar' # - 'discount_amount' is the percentage/dollar discount to # apply # - 'discount_message' is the message to show when a discount # is applied # ================================================================ DISCOUNTS_FOR_CUSTOMER_TAG = [ { customer_tag_match_type: :include , customer_tags: [ "customer_tag" , "another_tag" ], rate_match_type: :exact , rate_names: [ "Shipping Rate" , "Other Shipping Rate" ], discount_type: :percent , discount_amount: 10 , discount_message: "10% off shipping for tagged customers" }, ] # ================================ Script Code (do not edit) ================================ # ================================================================ # CustomerTagSelector # # Finds whether the supplied customer has any of the entered tags # ================================================================ class CustomerTagSelector def initialize ( match_type , tags ) @comparator = match_type == :include ? 'any?' : 'none?' @tags = tags . map { | tag | tag . downcase . strip } end def match? ( customer ) customer_tags = customer . tags . map { | tag | tag . downcase . strip } ( @tags & customer_tags ). send ( @comparator ) end end # ================================================================ # RateNameSelector # # Finds whether the supplied rate name matches any of the entered # names # ================================================================ class RateNameSelector def initialize ( match_type , rate_names ) @comparator = match_type == :exact ? '==' : 'include?' @rate_names = rate_names . map { | rate_name | rate_name . downcase . strip } end def match? ( shipping_rate ) @rate_names . any? { | name | shipping_rate . name . downcase . send ( @comparator , name ) } end end # ================================================================ # DiscountApplicator # # Applies the entered discount to the supplied shipping rate # ================================================================ class DiscountApplicator def initialize ( discount_type , discount_amount , discount_message ) @discount_type = discount_type @discount_message = discount_message @discount_amount = if discount_type == :percent discount_amount * 0.01 else Money . new ( cents: 100 ) * discount_amount end end def apply ( shipping_rate ) rate_discount = if @discount_type == :percent shipping_rate . price * @discount_amount else @discount_amount end shipping_rate . apply_discount ( rate_discount , message: @discount_message ) end end # ================================================================ # DiscountRatesForCustomerTagCampaign # # If we have a matching customer, the entered rate(s) are # discounted by the entered amount. # ================================================================ class DiscountRatesForCustomerTagCampaign def initialize ( campaigns ) @campaigns = campaigns end def run ( cart , shipping_rates ) return if cart . customer . nil? @campaigns . each do | campaign | customer_tag_selector = CustomerTagSelector . new ( campaign [ :customer_tag_match_type ], campaign [ :customer_tags ]) next unless customer_tag_selector . match? ( cart . customer ) rate_name_selector = RateNameSelector . new ( campaign [ :rate_match_type ], campaign [ :rate_names ]) discount_applicator = DiscountApplicator . new ( campaign [ :discount_type ], campaign [ :discount_amount ], campaign [ :discount_message ], ) shipping_rates . each do | shipping_rate | next unless rate_name_selector . match? ( shipping_rate ) discount_applicator . apply ( shipping_rate ) end end end end CAMPAIGNS = [ DiscountRatesForCustomerTagCampaign . new ( DISCOUNTS_FOR_CUSTOMER_TAG ), ] CAMPAIGNS . each do | campaign | campaign . run ( Input . cart , Input . shipping_rates ) end Output . shipping_rates = Input . shipping_rates
Show only carrier-calculated rates
Use this script to display carrier-calculated rates only. If carrier-calculated rates aren't available, your manually created rates are displayed.
# ================================================================ # Carrier Calculated Rate Fallback # # As long as carrier calculated rates are available, Shopify rates # will be hidden. # ================================================================ class CalculatedRateFallbackCampaign def run ( shipping_rates ) has_calculated_rates = shipping_rates . any? { | shipping_rate | shipping_rate . source . downcase != 'shopify' } return unless has_calculated_rates shipping_rates . delete_if { | shipping_rate | shipping_rate . source . downcase == 'shopify' } end end CAMPAIGNS = [ CalculatedRateFallbackCampaign . new (), ] CAMPAIGNS . each do | campaign | campaign . run ( Input . shipping_rates ) end Output . shipping_rates = Input . shipping_rates