Migrating a script that limited how many units were discounted
The cap is not the trap. The trap is a single sort line: with it the CHEAPEST units are discounted, without it the FIRST ones are, and both files are dense with the same split call that also makes them look like a BOGO.
ReconstruitIt discounted only the first few matching units and left the rest at full price.
Les marchands ont écrit ceci de 3 façons différentes, et elles ne veulent pas toutes dire la même chose. Chaque variante figure ci-dessous avec son propre panier et ses propres chiffres.
Collez-le dans Sauvetage des Scripts et regardez ce qu'il reconstruit
- Copiez le Ruby avec le bouton placé à côté de chaque Script de cette page.
- Dans votre interface Shopify, ouvrez Stackable, puis Outils, puis Sauvetage des Scripts.
- Collez-le, lisez ce que l'outil annonce qu'il va construire et comparez-le aux réglages de cette page.
Sauvetage des Scripts fait partie du forfait Pro. Rien n'est publié tant que vous n'avez pas indiqué la remise de votre ancien Script et que les deux chiffres ne correspondent pas au centime près.
Quantity limit first n discounted (D5)
ReconstruitPaire à risque D5. Ce fichier et son jumeau se ressemblent presque à l'identique et se comportent différemment, alors lisez les deux avant de décider lequel vous avez.
# GENERATED BY THE SHOPIFY SCRIPT CREATOR APP
class ConditionalDiscount < Campaign
def initialize(condition, customer_qualifier, cart_qualifier, line_item_selector, discount, max_discounts)
super(condition, customer_qualifier, cart_qualifier, line_item_selector)
@discount = discount
@items_to_discount = max_discounts == 0 ? nil : max_discounts
end
def run(cart)
return unless qualifies?(cart)
applicable_items = cart.line_items.select { |item| @line_item_selector.nil? || @line_item_selector.match?(item) }
applicable_items.each do |item|
break if @items_to_discount == 0
if !@items_to_discount.nil? && (item.quantity > @items_to_discount)
new_item = item.split({ take: @items_to_discount })
@discount.apply(new_item)
position = cart.line_items.find_index(item)
cart.line_items.insert(position + 1, new_item)
@items_to_discount = 0
else
@discount.apply(item)
@items_to_discount -= item.quantity unless @items_to_discount.nil?
end
end
end
end
CAMPAIGNS = [
ConditionalDiscount.new(
:all, nil, nil,
ProductTypeSelector.new(:does, ["Sale"]),
PercentageDiscount.new(30, "30% off first 2"),
2
),
].freeze
CAMPAIGNS.each do |campaign|
campaign.run(Input.cart)
end
Output.cart = Input.cartReconnu comme Discount on the first few units et reconstruit en offre de type bxgy. Voici les vraies clés de configuration avec lesquelles l'offre est enregistrée, pour que vous puissiez comparer votre propre reconstruction champ par champ.
| Réglage | Valeur | Clé de configuration |
|---|---|---|
| Offer type | bxgy | type |
| Counting | per_variant | counting |
| Recurrence | once | recurrence |
| Tier 1 | min qty 1 -> free item | tiers[0] |
| Buy quantity | 1 | bxgy.buyQty |
| Get quantity | 2 | bxgy.getQty |
| Get selection | same_item | bxgy.getSelection |
| Reward on the get units | 30% off | bxgy.getDiscountPct |
| Free units are additional | false | bxgy.freeUnitsAreAdditional |
| Target scope | product_types | target.scope |
| Target includes | Sale | target.includeIds |
| Method | automatic | discountMethod |
| Allocation | standard | stacking.allocation |
| Combines with other discounts | no | stacking |
- Your Script limited this to a tag, vendor, or product type. We carried that filter over, so confirm it selects the products you expect.
- The unit limit counts per matching group, not per cart line, so a cart with two separate lines can reach the limit twice.
Construit sur notre boutique de démonstration publique, Meridian Goods, pour que chaque prix ici puisse être reproduit plutôt que cru sur parole. La remise ci-dessous est ce que le moteur qui tourne au paiement calcule pour ce panier précis.
- No Meridian Goods product carries the type Sale. Set it on Aria Wireless Earbuds in Shopify before you build the cart, and on nothing else.
| Article | Qté | Prix unitaire |
|---|---|---|
| Aria Wireless Earbuds | 1 | $79.00 |
| Sous-total | $79.00 | |
| Remise | -$23.70 | |
| Total | $55.30 | |
Déconnecté, ou connecté en tant que client sans tag.
Avant la publication, l'outil demande ce que votre ancien Script faisait à un panier que vous avez déjà. Réglez-le sur 1 de Aria Wireless Earbuds à $79.00 et la réponse est fixée.
La remise est de $23.70. Le total payé par l'acheteur est de $55.30.
La comparaison est exacte, jusqu'à la plus petite unité de votre devise. Un centime d'écart et la publication reste bloquée, ce qui est tout l'intérêt de l'étape.
- swap the cart for a single Braided USB-C Cable
| Article | Qté | Prix unitaire |
|---|---|---|
| Braided USB-C Cable | 1 | $14.00 |
| Sous-total | $14.00 | |
| Total | $14.00 | |
Déconnecté, ou connecté en tant que client sans tag.
Quantity limit cheapest n (D5)
ReconstruitPaire à risque D5. Ce fichier et son jumeau se ressemblent presque à l'identique et se comportent différemment, alors lisez les deux avant de décider lequel vous avez.
# GENERATED BY THE SHOPIFY SCRIPT CREATOR APP
class ConditionalDiscount < Campaign
def initialize(condition, customer_qualifier, cart_qualifier, line_item_selector, discount, max_discounts)
super(condition, customer_qualifier, cart_qualifier, line_item_selector)
@discount = discount
@items_to_discount = max_discounts == 0 ? nil : max_discounts
end
def run(cart)
return unless qualifies?(cart)
applicable_items = cart.line_items.select { |item| @line_item_selector.nil? || @line_item_selector.match?(item) }
applicable_items = applicable_items.sort_by { |item| item.variant.price }
applicable_items.each do |item|
break if @items_to_discount == 0
if !@items_to_discount.nil? && (item.quantity > @items_to_discount)
new_item = item.split({ take: @items_to_discount })
@discount.apply(new_item)
position = cart.line_items.find_index(item)
cart.line_items.insert(position + 1, new_item)
@items_to_discount = 0
else
@discount.apply(item)
@items_to_discount -= item.quantity unless @items_to_discount.nil?
end
end
end
end
CAMPAIGNS = [
ConditionalDiscount.new(
:all, nil, nil,
ProductTypeSelector.new(:does, ["Sale"]),
PercentageDiscount.new(30, "30% off your 2 cheapest"),
2
),
].freeze
CAMPAIGNS.each do |campaign|
campaign.run(Input.cart)
end
Output.cart = Input.cartReconnu comme Discount on the first few units et reconstruit en offre de type bxgy. Voici les vraies clés de configuration avec lesquelles l'offre est enregistrée, pour que vous puissiez comparer votre propre reconstruction champ par champ.
| Réglage | Valeur | Clé de configuration |
|---|---|---|
| Offer type | bxgy | type |
| Counting | per_group | counting |
| Recurrence | once | recurrence |
| Tier 1 | min qty 1 -> free item | tiers[0] |
| Buy quantity | 1 | bxgy.buyQty |
| Get quantity | 2 | bxgy.getQty |
| Get selection | cheapest_eligible | bxgy.getSelection |
| Reward on the get units | 30% off | bxgy.getDiscountPct |
| Free units are additional | false | bxgy.freeUnitsAreAdditional |
| Target scope | product_types | target.scope |
| Target includes | Sale | target.includeIds |
| Method | automatic | discountMethod |
| Allocation | standard | stacking.allocation |
| Combines with other discounts | no | stacking |
- Your Script limited this to a tag, vendor, or product type. We carried that filter over, so confirm it selects the products you expect.
- The unit limit counts per matching group, not per cart line, so a cart with two separate lines can reach the limit twice.
Construit sur notre boutique de démonstration publique, Meridian Goods, pour que chaque prix ici puisse être reproduit plutôt que cru sur parole. La remise ci-dessous est ce que le moteur qui tourne au paiement calcule pour ce panier précis.
- No Meridian Goods product carries the type Sale. Set it on Aria Wireless Earbuds and Impact Phone Case in Shopify before you build the cart, and on nothing else.
| Article | Qté | Prix unitaire |
|---|---|---|
| Impact Phone Case | 1 | $24.00 |
| Aria Wireless Earbuds | 1 | $79.00 |
| Sous-total | $103.00 | |
| Remise | -$30.90 | |
| Total | $72.10 | |
Déconnecté, ou connecté en tant que client sans tag.
Avant la publication, l'outil demande ce que votre ancien Script faisait à un panier que vous avez déjà. Réglez-le sur 1 de Impact Phone Case à $24.00 et la réponse est fixée.
La remise est de $7.20. Le total payé par l'acheteur est de $16.80.
La comparaison est exacte, jusqu'à la plus petite unité de votre devise. Un centime d'écart et la publication reste bloquée, ce qui est tout l'intérêt de l'étape.
- swap the cart for a single Braided USB-C Cable
| Article | Qté | Prix unitaire |
|---|---|---|
| Braided USB-C Cable | 1 | $14.00 |
| Sous-total | $14.00 | |
| Total | $14.00 | |
Déconnecté, ou connecté en tant que client sans tag.
Quantity limit first n discounted (D6)
ReconstruitPaire à risque D6. Ce fichier et son jumeau se ressemblent presque à l'identique et se comportent différemment, alors lisez les deux avant de décider lequel vous avez.
DISCOUNT_PERCENTAGE = 30
MAX_UNITS = 2
num_to_discount = MAX_UNITS
Input.cart.line_items.each_with_index do |line_item, position|
break if num_to_discount <= 0
next unless line_item.variant.product.tags.include?("limited")
if line_item.quantity > num_to_discount
split_line_item = line_item.split(take: num_to_discount)
Input.cart.line_items.insert(position + 1, split_line_item)
line_item = split_line_item
end
line_item.change_line_price(
line_item.line_price * (1.0 - (DISCOUNT_PERCENTAGE / 100.0)),
message: "30% off your first 2"
)
num_to_discount -= line_item.quantity
end
Output.cart = Input.cartReconnu comme Discount on the first few units et reconstruit en offre de type bxgy. Voici les vraies clés de configuration avec lesquelles l'offre est enregistrée, pour que vous puissiez comparer votre propre reconstruction champ par champ.
| Réglage | Valeur | Clé de configuration |
|---|---|---|
| Offer type | bxgy | type |
| Counting | per_variant | counting |
| Recurrence | once | recurrence |
| Tier 1 | min qty 1 -> free item | tiers[0] |
| Buy quantity | 1 | bxgy.buyQty |
| Get quantity | 2 | bxgy.getQty |
| Get selection | same_item | bxgy.getSelection |
| Reward on the get units | 30% off | bxgy.getDiscountPct |
| Free units are additional | false | bxgy.freeUnitsAreAdditional |
| Target scope | tags | target.scope |
| Target includes | limited | target.includeIds |
| Method | automatic | discountMethod |
| Allocation | standard | stacking.allocation |
| Combines with other discounts | no | stacking |
- Your Script limited this to a tag, vendor, or product type. We carried that filter over, so confirm it selects the products you expect.
- The unit limit counts per matching group, not per cart line, so a cart with two separate lines can reach the limit twice.
Construit sur notre boutique de démonstration publique, Meridian Goods, pour que chaque prix ici puisse être reproduit plutôt que cru sur parole. La remise ci-dessous est ce que le moteur qui tourne au paiement calcule pour ce panier précis.
- No Meridian Goods product carries the tag limited. Set it on Aria Wireless Earbuds in Shopify before you build the cart, and on nothing else.
| Article | Qté | Prix unitaire |
|---|---|---|
| Aria Wireless Earbuds | 1 | $79.00 |
| Sous-total | $79.00 | |
| Remise | -$23.70 | |
| Total | $55.30 | |
Déconnecté, ou connecté en tant que client sans tag.
Avant la publication, l'outil demande ce que votre ancien Script faisait à un panier que vous avez déjà. Réglez-le sur 1 de Aria Wireless Earbuds à $79.00 et la réponse est fixée.
La remise est de $23.70. Le total payé par l'acheteur est de $55.30.
La comparaison est exacte, jusqu'à la plus petite unité de votre devise. Un centime d'écart et la publication reste bloquée, ce qui est tout l'intérêt de l'étape.
- swap the cart for a single Braided USB-C Cable
| Article | Qté | Prix unitaire |
|---|---|---|
| Braided USB-C Cable | 1 | $14.00 |
| Sous-total | $14.00 | |
| Total | $14.00 | |
Déconnecté, ou connecté en tant que client sans tag.
Deux fichiers qui se ressemblent
Chaque paire ci-dessous est une même forme de Script écrite de deux façons. Une ou deux lignes les séparent et elles ne font pas la même chose, alors lisez les deux avant de décider laquelle vous avez.
Paire piégeuse D5
Quantity limit first n discounted (D5)
ReconstruitReconstruit en offre bxgy.
Remise sur son propre panier : $23.70
PercentageDiscount.new(30, "30% off first 2"),Quantity limit cheapest n (D5)
ReconstruitReconstruit en offre bxgy.
Remise sur son propre panier : $30.90
applicable_items = applicable_items.sort_by { |item| item.variant.price }
PercentageDiscount.new(30, "30% off your 2 cheapest"),Paire piégeuse D6
Quantity limit first n discounted (D6)
ReconstruitReconstruit en offre bxgy.
Remise sur son propre panier : $23.70
DISCOUNT_PERCENTAGE = 30
MAX_UNITS = 2
num_to_discount = MAX_UNITS
Input.cart.line_items.each_with_index do |line_item, position|
break if num_to_discount <= 0
next unless line_item.variant.product.tags.include?("limited")Et 9 autres lignes différentes, sur sa propre page.
Quantity limit purchase cap (D6)
Autre API ShopifyNon reconstruit. This needs a different kind of Shopify app
# GENERATED BY THE SHOPIFY SCRIPT CREATOR APP
class QuantityLimit < Campaign
def initialize(condition, customer_qualifier, cart_qualifier, line_item_selector, limit_by, limit)
super(condition, customer_qualifier, cart_qualifier, line_item_selector)
@limit_by = limit_by
@limit = limitEt 26 autres lignes différentes, sur sa propre page.
Questions fréquentes
- Will Stackable rebuild this script?
- Yes. Every spelling on this page is rebuilt today as a bxgy offer, and the cart above is the one that proves it.
- What cart proves it works?
- 1 x Aria Wireless Earbuds at $79.00. The engine takes $23.70 off, and checkout charges $55.30.
- What will I have to check before publishing?
- Your Script limited this to a tag, vendor, or product type. We carried that filter over, so confirm it selects the products you expect. The unit limit counts per matching group, not per cart line, so a cart with two separate lines can reach the limit twice.
Formes de Script apparentées
A cap on how many units a shopper could buy, enforced by trimming the cart.
A set of paid units earns an extra unit at no charge.
The same buy-and-get offer, counted so the reward sits inside each set rather than beside it.
Collez votre Script et voyez sa reconstruction
La reconstruction est comparée au montant que facturait votre ancien Script avant que vous puissiez la publier.