Migrating a script scoped to a tag, vendor or product type
A dropped filter is the most expensive class of mistake in a migration, because it is silent and it is confident: the percentage is read perfectly and applied to everything you sell. Note that Scripts could not read collections at all.
ReconstruídoIt skipped every line whose product did not carry the listed tag, vendor or type.
Os lojistas escreveram isso de 3 formas diferentes, e nem todas significam a mesma coisa. Cada variação está abaixo com o próprio carrinho e os próprios números.
Cole no Resgate de Scripts e veja o que ele reconstrói
- Copie o Ruby no botão ao lado de qualquer Script desta página.
- No admin da Shopify, abra o Stackable, depois Ferramentas e depois Resgate de Scripts.
- Cole lá, leia o que a ferramenta diz que vai criar e compare com as configurações desta página.
O Resgate de Scripts está no plano Pro. Nada é publicado até você informar quanto o Script antigo descontava e os dois valores baterem no centavo.
Official dialect, product selector include (D13)
ReconstruídoPar perigoso D13. Este arquivo e o parceiro dele são quase idênticos e se comportam de formas diferentes, então leia os dois antes de decidir qual é o seu.
# ================================ Customizable Settings ================================
PRODUCT_DISCOUNTS = [
{
product_selector_match_type: :include,
product_selector_type: :tag,
product_selectors: ["sale"],
discount_type: :percent,
discount_amount: 20,
discount_message: "20% off sale items",
},
]
# ================================ Script Code (do not edit) ================================
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 }
(@selectors.include?(line_item.variant.product.product_type.downcase.strip)) == (@match_type == :include)
end
def vendor(line_item)
@selectors = @selectors.map { |selector| selector.downcase.strip }
(@selectors.include?(line_item.variant.product.vendor.downcase.strip)) == (@match_type == :include)
end
def product_id(line_item)
(@selectors.include?(line_item.variant.product.id)) == (@match_type == :include)
end
def variant_id(line_item)
(@selectors.include?(line_item.variant.id)) == (@match_type == :include)
end
def all(line_item)
true
end
end
class ProductDiscountCampaign
def initialize(campaigns)
@campaigns = campaigns
end
def run(cart)
@campaigns.each do |campaign|
product_selector = ProductSelector.new(
campaign[:product_selector_match_type],
campaign[:product_selector_type],
campaign[:product_selectors],
)
cart.line_items.each do |line_item|
next unless product_selector.match?(line_item)
line_item.change_line_price(
line_item.line_price * (1 - (campaign[:discount_amount] * 0.01)),
message: campaign[:discount_message],
)
end
end
end
end
CAMPAIGNS = [
ProductDiscountCampaign.new(PRODUCT_DISCOUNTS),
]
CAMPAIGNS.each do |campaign|
campaign.run(Input.cart)
end
Output.cart = Input.cartReconhecido como Percentage off e reconstruído como uma oferta do tipo volume. Estas são as chaves de configuração reais com as quais a oferta é salva, então você pode conferir a sua própria reconstrução campo a campo.
| Configuração | Valor | Chave de configuração |
|---|---|---|
| Offer type | volume | type |
| Counting | per_product | counting |
| Recurrence | once | recurrence |
| Tier 1 | min qty 1 -> 20% off | tiers[0] |
| Target scope | tags | 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.
Montado na nossa loja de demonstração pública, Meridian Goods, para que cada preço aqui possa ser reproduzido em vez de aceito por confiança. O desconto abaixo é o que o mesmo motor que roda no checkout calcula para este carrinho exato.
| Item | Qtd | Preço unit. |
|---|---|---|
| Ceramic Travel Mug | 1 | $22.00 |
| Subtotal | $22.00 | |
| Desconto | -$4.40 | |
| Total | $17.60 | |
Sem login, ou logado como cliente sem tags.
Antes de publicar, a ferramenta pergunta o que o seu Script antigo fazia com um carrinho que você já tem. Defina como 1 de Ceramic Travel Mug a $22.00 e a resposta fica fixa.
O desconto é $4.40. O total que o cliente pagou é $17.60.
A comparação é exata, até a menor unidade da sua moeda. Um centavo de diferença e a publicação continua bloqueada, que é justamente o objetivo desta etapa.
- swap the cart for a single Braided USB-C Cable
| Item | Qtd | Preço unit. |
|---|---|---|
| Braided USB-C Cable | 1 | $14.00 |
| Subtotal | $14.00 | |
| Total | $14.00 | |
Sem login, ou logado como cliente sem tags.
Official dialect, product selector exclude (D13)
ReconstruídoPar perigoso D13. Este arquivo e o parceiro dele são quase idênticos e se comportam de formas diferentes, então leia os dois antes de decidir qual é o seu.
# ================================ Customizable Settings ================================
PRODUCT_DISCOUNTS = [
{
product_selector_match_type: :exclude,
product_selector_type: :tag,
product_selectors: ["sale"],
discount_type: :percent,
discount_amount: 20,
discount_message: "20% off full-price items",
},
]
# ================================ Script Code (do not edit) ================================
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 all(line_item)
true
end
end
class ProductDiscountCampaign
def initialize(campaigns)
@campaigns = campaigns
end
def run(cart)
@campaigns.each do |campaign|
product_selector = ProductSelector.new(
campaign[:product_selector_match_type],
campaign[:product_selector_type],
campaign[:product_selectors],
)
cart.line_items.each do |line_item|
next unless product_selector.match?(line_item)
line_item.change_line_price(
line_item.line_price * (1 - (campaign[:discount_amount] * 0.01)),
message: campaign[:discount_message],
)
end
end
end
end
CAMPAIGNS = [
ProductDiscountCampaign.new(PRODUCT_DISCOUNTS),
]
CAMPAIGNS.each do |campaign|
campaign.run(Input.cart)
end
Output.cart = Input.cartReconhecido como Percentage off e reconstruído como uma oferta do tipo volume. Estas são as chaves de configuração reais com as quais a oferta é salva, então você pode conferir a sua própria reconstrução campo a campo.
| Configuração | Valor | Chave de configuração |
|---|---|---|
| Offer type | volume | type |
| Counting | per_product | counting |
| Recurrence | once | recurrence |
| Tier 1 | min qty 1 -> 20% off | tiers[0] |
| Target scope | all | target.scope |
| Target excludes | sale | target.excludeIds |
| 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.
Montado na nossa loja de demonstração pública, Meridian Goods, para que cada preço aqui possa ser reproduzido em vez de aceito por confiança. O desconto abaixo é o que o mesmo motor que roda no checkout calcula para este carrinho exato.
- Targeting excludes sale. No Meridian Goods product carries those, so every product stays eligible and the exclusion is proved by the campaign settings, not by the cart.
| Item | Qtd | Preço unit. |
|---|---|---|
| Braided USB-C Cable | 1 | $14.00 |
| Subtotal | $14.00 | |
| Desconto | -$2.80 | |
| Total | $11.20 | |
Sem login, ou logado como cliente sem tags.
Antes de publicar, a ferramenta pergunta o que o seu Script antigo fazia com um carrinho que você já tem. Defina como 1 de Braided USB-C Cable a $14.00 e a resposta fica fixa.
O desconto é $2.80. O total que o cliente pagou é $11.20.
A comparação é exata, até a menor unidade da sua moeda. Um centavo de diferença e a publicação continua bloqueada, que é justamente o objetivo desta etapa.
- swap the cart for a single Ceramic Travel Mug
| Item | Qtd | Preço unit. |
|---|---|---|
| Ceramic Travel Mug | 1 | $22.00 |
| Subtotal | $22.00 | |
| Total | $22.00 | |
Sem login, ou logado como cliente sem tags.
Scope targeting family tag (D9)
ReconstruídoPar perigoso D9. Este arquivo e o parceiro dele são quase idênticos e se comportam de formas diferentes, então leia os dois antes de decidir qual é o seu.
Input.cart.line_items.each do |li|
next unless li.variant.product.tags.include?('sale')
li.change_line_price(li.original_line_price * (1.0 - (20 / 100.0)), message: "20% off sale")
end
Output.cart = Input.cartReconhecido como Percentage off e reconstruído como uma oferta do tipo volume. Estas são as chaves de configuração reais com as quais a oferta é salva, então você pode conferir a sua própria reconstrução campo a campo.
| Configuração | Valor | Chave de configuração |
|---|---|---|
| Offer type | volume | type |
| Counting | per_product | counting |
| Recurrence | once | recurrence |
| Tier 1 | min qty 1 -> 20% off | tiers[0] |
| Target scope | tags | 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.
Montado na nossa loja de demonstração pública, Meridian Goods, para que cada preço aqui possa ser reproduzido em vez de aceito por confiança. O desconto abaixo é o que o mesmo motor que roda no checkout calcula para este carrinho exato.
| Item | Qtd | Preço unit. |
|---|---|---|
| Ceramic Travel Mug | 1 | $22.00 |
| Subtotal | $22.00 | |
| Desconto | -$4.40 | |
| Total | $17.60 | |
Sem login, ou logado como cliente sem tags.
Antes de publicar, a ferramenta pergunta o que o seu Script antigo fazia com um carrinho que você já tem. Defina como 1 de Ceramic Travel Mug a $22.00 e a resposta fica fixa.
O desconto é $4.40. O total que o cliente pagou é $17.60.
A comparação é exata, até a menor unidade da sua moeda. Um centavo de diferença e a publicação continua bloqueada, que é justamente o objetivo desta etapa.
- swap the cart for a single Braided USB-C Cable
| Item | Qtd | Preço unit. |
|---|---|---|
| Braided USB-C Cable | 1 | $14.00 |
| Subtotal | $14.00 | |
| Total | $14.00 | |
Sem login, ou logado como cliente sem tags.
Dois arquivos que parecem iguais
Cada dupla abaixo é a mesma forma de Script escrita de dois jeitos. Elas mudam em uma ou duas linhas e fazem coisas diferentes, então leia as duas antes de decidir qual é a sua.
Dupla perigosa D9
Scope targeting family tag (D9)
ReconstruídoReconstruído como oferta volume.
Desconto no carrinho dele: $4.40
next unless li.variant.product.tags.include?('sale')
li.change_line_price(li.original_line_price * (1.0 - (20 / 100.0)), message: "20% off sale")Flat percentage off all (D9)
ReconstruídoReconstruído como oferta volume.
Desconto no carrinho dele: $2.80
li.change_line_price(li.original_line_price * (1.0 - (20 / 100.0)), message: "20% off everything")Dupla perigosa D13
Official dialect, product selector include (D13)
ReconstruídoReconstruído como oferta volume.
Desconto no carrinho dele: $4.40
product_selector_match_type: :include,
discount_message: "20% off sale items",
def type(line_item)
@selectors = @selectors.map { |selector| selector.downcase.strip }
(@selectors.include?(line_item.variant.product.product_type.downcase.strip)) == (@match_type == :include)
endE mais 10 linhas diferentes, na página dela.
Official dialect, product selector exclude (D13)
ReconstruídoReconstruído como oferta volume.
Desconto no carrinho dele: $2.80
product_selector_match_type: :exclude,
discount_message: "20% off full-price items",Perguntas frequentes
- Will Stackable rebuild this script?
- Yes. Every spelling on this page is rebuilt today as a volume offer, and the cart above is the one that proves it.
- What cart proves it works?
- 1 x Ceramic Travel Mug at $22.00. The engine takes $4.40 off, and checkout charges $17.60.
- 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.
Formatos de Script relacionados
One percentage off the whole catalogue, with no condition attached.
Already-marked-down products protected from a second discount.
Gift cards left out of a discount that would otherwise have hit them.
Cole o seu Script e veja a reconstrução
A reconstrução é comparada com o valor que o seu Script antigo cobrava antes de você poder publicá-la.