Ran into this last week had a “Buy 2 Get 1 Free” promo running through Shopify Scripts for almost a year, and once I found out Scripts is being deprecated, I realized I had no idea how to recreate it on Functions.
Turns out BOGO logic on Functions works completely differently than the old Scripts approach. Instead of writing conditional logic in code, it’s built around discount rules that evaluate cart contents and apply the free/discounted item automatically. The tricky part for me was figuring out how to set the “trigger quantity” vs the “reward quantity” correctly messed it up twice and ended up with the discount applying to the wrong item.
A few things that would’ve saved me time if I’d known upfront:
Combined discounts matter a lot here if you’ve got other discounts running (like a sitewide sale), you need to explicitly set how BOGO stacks with them, or it can silently override your other promos
Test it with a real cart before going live the preview doesn’t always catch edge cases like mixed-variant carts
If your BOGO is tied to specific collections rather than all products, that filtering logic needs to be set up separately
Ended up rebuilding the whole thing without writing any code, which honestly surprised me since I assumed Functions meant hiring a developer. Took about 30 minutes once I understood the trigger/reward split.
Anyone else migrated a BOGO setup yet? Curious if others ran into the same trigger vs reward confusion, or if there’s a cleaner way to handle stacking with other discounts.
I had the same confusion when I first switched over. The trigger quantity vs. reward quantity sounds simple, but it’s surprisingly easy to set up backwards and end up discounting the wrong items.
The stacking behavior caught me off guard too. It’s definitely worth checking how your BOGO interacts with other automatic discounts before pushing it live. I also found that testing a few real-world cart combinations (different variants, quantities, and eligible/non-eligible products) helped catch issues that the preview missed.
The good part is that once you understand how the rules work, it’s actually much easier to manage than the old Scripts setup, and not having to write custom code is a nice bonus.
Hey, thanks for sharing this! I ran into some of the same confusion.
Just curious, how did you end up configuring yours? Did you use Shopify Functions only, or was there a specific setup that made the trigger/reward quantities work correctly? I’d love to hear what worked for you.
I had the same trigger vs. reward confusion at first. What helped was testing with different cart combinations (3, 4, and 5 items) to make sure the correct product received the discount. I also found it worth checking discount combinations early because the stacking behavior can be different from what you expect. Once everything is tested, Functions are actually much easier to manage than Scripts for standard BOGO offers.
Thanks for sharing your setup. One question—how are you handling customers adding multiple eligible products to the cart? Does your BOGO repeat automatically (e.g. Buy 2 Get 1 Free twice when they add 6 items), or did you have to configure that behavior separately?
Good writeup. One pitfall to add from porting a bunch of these: if your old script targeted specific products, the numeric product IDs from your Ruby code won’t match what Functions sees. Everything arrives as gid://shopify/Product/… now. I shipped a BOGO rule that silently never fired because of exactly this - it looked correct in every preview, passed every glance at the config, and matched nothing in production. If your Functions BOGO “runs but never triggers”, check the ID format before you debug anything else.
Two more differences worth knowing. Functions re-evaluates on every cart change, with no order-level memory like Scripts had. And the whole store shares a cap of 25 active Functions discounts, so promo-heavy stores hit a wall that Scripts never had.
The bit that trips up many BOGO rebuilds on Functions is the “which unit is free and does it repeat” logic. Buy 2 Get 1 is easy, but buy 4 get 2, and making sure the free unit is the cheapest qualifying one, is where the trigger and reward quantities and the discount’s combination settings start getting complicated and fighting each other.
Full disclosure, we created Deducto, a general purpose discounting and promotions app and this is exactly one of the scenarios that it was built for: proper BOGO and tiered logic set up as configuration rather than hand-written Functions (no coding needed), including the repeat behaviour and cheapest-unit selection. As a side benefit, your promotions all run through the one app, so you are not using a Function slot per promotion.
There’s a free plan (https://apps.shopify.com/deducto) to try it out (no time limits), so you could rebuild your Buy 2 Get 1 promos on it and not worry about the trigger/reward and stacking wrangling. We’d be very grateful for any feedback!